Skip to content

feat: add TTFS state metrics#206

Merged
Nek-12 merged 2 commits intomasterfrom
ttfs
Feb 2, 2026
Merged

feat: add TTFS state metrics#206
Nek-12 merged 2 commits intomasterfrom
ttfs

Conversation

@Nek-12
Copy link
Member

@Nek-12 Nek-12 commented Feb 2, 2026

Summary

  • add TTFS + started-in-initial-state state metrics and snapshot fields
  • gate 1.1-only metrics in OpenMetrics/OTLP surfaces
  • update tests/docs and metrics schema helpers

Testing

  • ./gradlew detektFormat
  • ./gradlew :metrics:assemble
  • ./gradlew allTests (warns in debugger DebuggerMetricsSink.kt:29 unused onFailure)

Closes #190

Summary by CodeRabbit

  • New Features

    • Added two state metrics: a flag for "started in initial state" and "time to first non-initial state"; metrics schema bumped to 1.1.
    • Telemetry outputs now include the new metrics when using schema 1.1.
  • Documentation

    • Metrics docs updated to describe the new fields and adjusted total metric count.
  • Tests

    • Added and updated tests to cover the new metrics and schema behavior.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 2, 2026

📝 Walkthrough

Walkthrough

Adds Time‑To‑First‑State (TTFS) metrics: tracks whether a run started in the initial state and measures time to the first non‑initial state. Introduces schema v1.1, updates MetricSurface/CURRENT, extends StateMetrics snapshot, records TTFS in MetricsCollector, and conditionally emits the new gauges in sinks with tests and docs updated.

Changes

Cohort / File(s) Summary
Schema Versioning & Surface
metrics/src/commonMain/kotlin/.../MetricsSchemaVersion.kt, metrics/src/commonMain/kotlin/.../MetricSurface.kt
Add V1_1 schema constant, set CURRENT→V1_1, add MetricSurface.V1_1 alias and routing in fromVersion.
Snapshot API
metrics/src/commonMain/kotlin/.../MetricsSnapshot.kt, metrics/src/commonMain/kotlin/.../MetricsSnapshotExtensions.kt
Add startedInInitialState: Boolean and timeToFirstState: Duration? to StateMetrics; update downgrade logic to clear these fields when targeting < V1_1.
Metrics Collection
metrics/src/commonMain/kotlin/.../MetricsCollector.kt
Track start-state, record time-to-first non‑initial state, expose fields in snapshots, reset fields on reset, and introduce helper to record TTFS. Refactor send path for safer emission.
Sinks (OpenMetrics & OTLP)
metrics/src/commonMain/kotlin/.../openmetrics/OpenMetricsSink.kt, metrics/src/commonMain/kotlin/.../otel/OtlpJsonSink.kt
Use buildList for state metrics and conditionally emit state_started_in_initial_state and state_time_to_first_state_seconds when snapshot.schemaVersion ≥ V1_1. Update internal function signatures accordingly.
Tests & Fixtures
metrics/src/jvmTest/kotlin/.../StateMetricsCollectorTest.kt, .../TestFixtures.kt, .../api/MetricsSurfaceTest.kt, .../openmetrics/OpenMetricsSinkJvmTest.kt, .../otel/OtlpJsonSinkTest.kt
Add tests for TTFS behaviors and initial‑state flag, update fixtures to populate new fields, adjust tests to expect schema 1.1 and new metric names.
Docs & API Signatures
docs/docs/plugins/metrics.md, skills/flowmvi/references/api-signatures.md
Document new State metrics fields and increase total metrics count; add StateMetrics signature entry including startedInInitialState and timeToFirstState.

Sequence Diagram(s)

sequenceDiagram
    participant Collector as MetricsCollector
    participant Snapshot as MetricsSnapshot
    participant Sink as MetricsSink
    participant Exporter as ExternalExporter

    Collector->>Collector: onStart(initialState)
    Collector->>Collector: record startedInInitialState, start TTFS timer if needed
    Collector->>Collector: onStateTransition(newState)
    alt first non-initial transition
        Collector->>Collector: record timeToFirstState
    end
    Collector->>Snapshot: build snapshot (includes TTFS fields)
    Snapshot->>Sink: emit snapshot
    Sink->>Exporter: publish metrics (conditionally include TTFS gauges if schema ≥ V1_1)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • 3.3.0-alpha02 #192: modifies metrics subsystem (MetricsCollector, MetricsSnapshot, sinks); likely overlaps with schema and sink changes.
  • 3.3.0-alpha01 #188: earlier work adjusting metrics types and sinks; directly related to the StateMetrics and schema evolution here.

Suggested labels

autorelease

Poem

🐰 Hooray, I tracked the very first hop,

A timestamp stored before I stop.
Started in spring or tumbled in haste,
TTFS measured — not a moment waste. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: add TTFS state metrics' accurately and concisely describes the primary change: adding Time-To-First-State metrics to the state metrics collection.
Linked Issues check ✅ Passed The PR implements TTFS metric collection (#190) with new StateMetrics fields (startedInInitialState, timeToFirstState), gated schema version handling (V1_1), and exposure through OpenMetrics and OTLP surfaces as required.
Out of Scope Changes check ✅ Passed All changes directly support TTFS implementation: new metrics fields, schema versioning, sink updates, test coverage, and documentation. No unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ttfs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @Nek-12, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the existing metrics collection system by adding new state-related metrics. Specifically, it introduces the ability to track whether a store begins its lifecycle in its initial state and, if so, how long it takes to transition to a different state. These additions provide deeper insights into state management performance and behavior, with careful consideration for schema versioning to maintain compatibility with existing metric consumers.

Highlights

  • New State Metrics: Introduced two new state metrics: 'started-in-initial-state' to indicate if a store started in its initial state, and 'time-to-first-state' (TTFS) to measure the duration until the first non-initial state transition occurs.
  • Metrics Schema Versioning: Updated the metrics schema to version 1.1 to accommodate the new state metrics. These new metrics are conditionally exposed in OpenMetrics and OTLP surfaces, ensuring backward compatibility for older schema versions.
  • Documentation and Testing: The documentation for metrics has been updated to reflect the new state metrics, and comprehensive tests have been added to verify the correct behavior and reporting of TTFS and 'started-in-initial-state'.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@Nek-12 Nek-12 enabled auto-merge February 2, 2026 17:37
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces new metrics for tracking the time to the first state transition and whether a store starts in its initial state. The changes are comprehensive, including updates to the metrics collector, data models, documentation, and metric sinks. The metrics schema has been versioned to 1.1, and sinks now conditionally expose these new metrics. The accompanying tests are thorough and cover the new functionality well. My review includes a correction for the metric count in the documentation and suggestions for more idiomatic Kotlin code in the metric sinks to improve readability. Overall, this is a well-executed feature addition.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@docs/docs/plugins/metrics.md`:
- Line 33: Update the metric count text that currently reads "Total: 67+ numeric
metrics per snapshot." to "Total: 68+ numeric metrics per snapshot." to account
for the two newly added metrics (started-in-initial-state and
time-to-first-state); locate the string "Total: 67+ numeric metrics per
snapshot." in the docs content and change the numeric value only.

In
`@metrics/src/commonMain/kotlin/pro/respawn/flowmvi/metrics/api/MetricsSnapshot.kt`:
- Around line 143-146: The new non-default properties on the public data class
are source-breaking; update the StateMetrics data class constructor to provide
defaults for the new parameters (e.g., startedInInitialState = false and
timeToFirstState = null) so existing callers compiling against the old
constructor keep working; adjust any internal factory/constructor calls that
assumed explicit values if needed, and ensure the property names
startedInInitialState and timeToFirstState are preserved for binary/source
compatibility.

In
`@metrics/src/commonMain/kotlin/pro/respawn/flowmvi/metrics/api/MetricsSnapshotExtensions.kt`:
- Around line 8-21: Update the KDoc for MetricsSnapshot.downgradeTo to reflect
its actual behavior: note that when target == meta.schemaVersion it returns
unchanged, but when downgrading to a version < MetricsSchemaVersion.V1_1 it
explicitly clears V1.1-specific fields (startedInInitialState set to false and
timeToFirstState set to null) in the returned snapshot; also mention that for
targets >= V1_1 the state is preserved and only meta.schemaVersion is updated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@metrics/src/commonMain/kotlin/pro/respawn/flowmvi/metrics/api/MetricsSnapshotExtensions.kt`:
- Around line 8-20: The function MetricsSnapshot.downgradeTo currently allows a
target schema newer than meta.schemaVersion; add a guard at the start of
MetricsSnapshot.downgradeTo that checks if target > meta.schemaVersion and in
that case do not change the snapshot (e.g., return this or throw a validation
error). Ensure the check uses the MetricsSchemaVersion comparison (target >
meta.schemaVersion) before any copy/update logic so you never mark a snapshot as
a higher schema without applying the corresponding upgrades.

@Nek-12 Nek-12 disabled auto-merge February 2, 2026 18:13
@Nek-12 Nek-12 merged commit 0c19384 into master Feb 2, 2026
2 of 3 checks passed
@Nek-12 Nek-12 deleted the ttfs branch February 2, 2026 18:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🚀: TTFS - Time to First State metric collection

1 participant