# Talaiot: recording what your Gradle build actually spends time on

> Talaiot is a Kotlin Gradle plugin that measures build and task durations, attaches extra metrics to each record and ships the results to a publisher such as InfluxDB, Elasticsearch or RethinkDB. It answers a question build tools leave open, which is not whether the build passed but which part of it is slow.

**cdsap/Talaiot** — Simple and extensible plugin to track task times in your Gradle Project.

- Repository: https://github.com/cdsap/Talaiot
- Stars: 617 · Forks: 39
- Language: Kotlin
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/cdsap-talaiot

## Build logs tell you the build failed, not which part was slow

A Gradle build already prints how long each task took. The problem is that the output is per invocation and per machine, so it does not accumulate. Next week, on a different laptop or on a CI runner, the same build takes twice as long, and there is no history to compare against.

Talaiot exists to close that gap. The README describes it as an extensible library targeting teams using the Gradle Build System, and says it records build and task durations to help understand build problems and detect bottlenecks. Every record can carry additional information, either from the default metrics or from metrics you define yourself.

So the audience is a team with a shared build and a shared CI setup, where the same task behaves differently from one developer to the next and nobody can point at the offending task. Talaiot is written in Kotlin and published to the Gradle Plugin Portal, so it plugs into an existing Gradle build the way any other plugin does.

What Talaiot is not is a profiler. It measures task durations at the level Gradle reports them, not the internals of a task. If the problem is that one compilation step is slow because of an annotation processor, Talaiot tells you which task got slower. It does not tell you why inside that task.

## A core library and a set of publisher plugins

The architecture is split in two, and the split is the main thing to understand before configuring anything.

The first piece is Talaiot core, which does the recording: it measures durations and prepares the records. The second piece is a publisher, which decides where the records go. The README is explicit that you need a plugin to work with Talaiot, and that you can use the standard plugin with all the functionality or an individual plugin if you have a specific requirement.

The available plugins are listed in a table. The standard plugin contains all the available publishers. The base plugin is Talaiot core with the Json, Output and Timeline publishers. Then there are dedicated plugins for Elasticsearch, InfluxDb, InfluxDb2 using Flux, Pushgateway and Rethinkdb.

That base plugin is worth a second look, because the Json, Output and Timeline publishers are local. A team that wants to see build timings in a file, in the console, or in a timeline diagram does not need a database at all. The database plugins are for teams that want the history to be queryable across machines and builds.

One practical detail to check before you copy an id from a blog post: the plugin id table lists the RethinkDB plugin as `io.github.cdsap.talaiot.plugin.rehinkdb`, with the r and h transposed, while the publisher table above it spells the publisher `rethinkdb`. The README does not comment on the discrepancy, so verify the id you use against the Plugin Portal listing.

## Six extension points on the talaiot block

Configuration happens in a `talaiot` extension block, and the README documents six properties for it.

`logger` sets the logging mode, with the options Silent and Info. `ignoreWhen` configures when Talaiot should skip its own execution, which is the hook for keeping telemetry out of local builds or out of a specific CI job. `generateBuildId` produces a unique identifier for each execution and is disabled by default, so a build is only distinguishable from another when you turn it on.

`publishers` defines where the build information is submitted. `metrics` adds extra information tracked during the execution of a task. `filter` holds the rules to filter which builds or which tasks get reported, which is how you keep a nightly or release build out of the statistics while still tracking developer builds.

Taken together, those six properties cover the three questions you will have in the first week: how do I turn it down, how do I tag a record so I can find it later, and how do I stop it reporting the tasks I do not care about. The `ignoreWhen` and `filter` combination in particular is worth setting before you connect a real publisher, because a chatty integration that arrives in a team channel is a quick way to lose goodwill.

The README also documents the coordinates for the Sonatype snapshot repository, so nightlies are available for anyone who wants to try an unreleased build.

## Metrics: objects, key value pairs and experimental providers

Metrics are where Talaiot becomes more than a stopwatch, and the API has three generations.

The first is custom metric objects. You pass instances to `customMetrics`, and the README example mixes your own objects with provided ones such as `HostnameMetric()`:

```kotlin
talaiot {
    metrics {
        // You can add your own custom Metric objects:
        customMetrics(
            MyCustomMetric(),
            // Including some of the provided metrics, individually.
            HostnameMetric()
        )

        // Or define build or task metrics directly:
        customBuildMetrics(
            "kotlinVersion" to $kotlinVersion,
            "javaVersion" to $javaVersion
        )
        customTaskMetrics(
            "customProperty" to $value
        )
    }
}
```

The second generation is the direct key value form, `customBuildMetrics` and `customTaskMetrics`, for values you already have in the build script such as the Kotlin or Java version. That is where the most useful signals usually live, because a task that only got slow on Java 21 is a different problem from one that got slow everywhere.

The third is provider based metrics, which the README marks as experimental since version 2.1.0. They are compatible with Configuration Cache and evaluate metric values lazily, only when they are needed during the build lifecycle. There are two entry points, `initialProviderMetrics` at the start of the execution phase and `finalProviderMetrics` once the build has finished. Both are marked experimental and may change in future versions, and the compiler warning can be suppressed by opting in with `@OptIn(ExperimentalMetricsApi::class)`.

The Configuration Cache compatibility is the point of the mechanism. A metric that reads the environment at configuration time would invalidate the cache, so the provider form defers that work to the point where the value is actually consumed.

## Applying the plugin in a Kotlin or Groovy build

Setting up Talaiot is a matter of applying one plugin. In a Kotlin build script using the plugins DSL:

```kotlin
plugins {
  id("io.github.cdsap.talaiot") version "<latest version>"
}
```

The legacy application form still works too, and matters for builds that are not on the plugins DSL:

```kotlin
buildscript {
  repositories {
    gradlePluginPortal()
  }
  dependencies {
    classpath("io.github.cdsap:talaiot:<latest version>")
  }
}

apply(plugin = "io.github.cdsap.talaiot")
```

Groovy builds get the same two options, with the same ids:

```groovy
plugins {
  id "io.github.cdsap.talaiot" version "<latest version>"
}
```

If you want a narrower footprint, the individual plugins follow the same pattern with their own ids, for example:

```kotlin
plugins {
  id("io.github.cdsap.talaiot.plugin.base") version "<latest version>"
}
```

For nightly builds the README points at the Sonatype snapshot repository and gives the classpath coordinates with a `-SNAPSHOT` suffix, both for the standard plugin and for the individual base plugin.

After the plugin is applied, the build runs as before and Talaiot records in the background. The output you should expect is whatever your chosen publisher produces, which for the base plugin means files, console output or a timeline, and for the database plugins means rows you can query later.

## The limits: a plugin is required, and the newest API is unstable

The first limitation is stated in the README and easy to miss: you need a plugin to work with Talaiot. Talaiot on its own records and does nothing useful with the records. If you apply only the core without a publisher, you are paying for measurement with no readout, and in a team that means the plugin will be removed within a week.

The second limitation is the stability of the newest API. `initialProviderMetrics` and `finalProviderMetrics` are explicitly labelled experimental, with the note that they may change in future versions, and the code needs an opt-in annotation to compile quietly. Building your build time reporting on an experimental surface is a reasonable choice if you are tracking a Configuration Cache problem and an unreasonable one if you want a metric that will still work next year.

The third is the measurement boundary. Talaiot reports what Gradle reports, so configuration time, dependency resolution and daemon state all influence the numbers, and nothing in the README explains how those are separated. A clean comparison between two builds assumes the same machine class, the same daemon state and the same dependency cache, and the project does not attempt to normalise for any of that.

The alternative to Talaiot is the tooling Gradle itself now provides for build analysis, which reports durations per task inside the build and can expose them through the tooling API for tooling you write yourself. The difference in approach is where the data goes. Gradle's own analysis is per invocation and local, so it answers what was slow right now. Talaiot is per invocation and historical, and it exports to a database you query later, which is the only way to notice that a task has been getting slower over three months rather than on one afternoon.

## Conclusion

Adopt Talaiot when a Gradle build is slow enough that you need a per task duration history across machines and CI runs, and you already run or can run one of the supported publishers, because Talaiot itself only records and forwards. Do not adopt it to fix one slow build today, since reading a single local build log is faster, and treat the provider metrics APIs as unstable until you accept that `initialProviderMetrics` and `finalProviderMetrics` are marked experimental and may change. Before wiring it up, check that the plugin id you publish with matches the one you registered, since the README table lists the RethinkDB plugin id with a typo, and decide early whether to start from the standard plugin or the narrower base plugin.

## FAQ

### What does Talaiot do in a Gradle build?

Talaiot records build and task durations so you can understand build problems and detect bottlenecks, and attaches extra information to each record from default or custom metrics. You need a publisher plugin to send that information anywhere.

### How do I add Talaiot to a Kotlin Gradle build?

Apply the plugin with the plugins DSL using `id("io.github.cdsap.talaiot") version "<latest version>"`. A legacy form using buildscript and apply(plugin = ...) is also documented, and Groovy build scripts use the same plugin id.

### Which publishers does Talaiot support?

The standard plugin bundles all of them, and individual plugins exist for base, elasticsearch, influxdb, influxdb2 with Flux, pushgateway and rethinkdb. The base plugin covers the Json, Output and Timeline publishers, which need no database.

### How do I add my own data to Talaiot records?

Use customMetrics for metric objects such as HostnameMetric(), or customBuildMetrics and customTaskMetrics to attach key value pairs you already have in the build script. Since version 2.1.0 there are also provider based metrics, `initialProviderMetrics` and `finalProviderMetrics`, which are experimental and evaluate values lazily for Configuration Cache compatibility.

### How do I stop Talaiot from reporting some builds or tasks?

Use the `ignoreWhen` property to configure when Talaiot skips its execution, and the `filter` property for rules that filter which builds or tasks are reported. The `generateBuildId` option is off by default and adds a unique identifier per execution when enabled.

## Sources

- [cdsap/Talaiot on GitHub](https://github.com/cdsap/Talaiot)
- [Issues](https://github.com/cdsap/Talaiot/issues)
- [License: MIT](https://github.com/cdsap/Talaiot/blob/master/LICENSE)
- [README](https://github.com/cdsap/Talaiot/blob/master/README.md)
- [Releases](https://github.com/cdsap/Talaiot/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cdsap-talaiot
