Skip to content

feat(runner): add live-log streaming metrics - #7947

Merged
dejanzele merged 7 commits into
mainfrom
fix/live-log-metrics
Sep 7, 2026
Merged

dejanzele merged 7 commits into
mainfrom
fix/live-log-metrics

Conversation

@dejanzele

@dejanzele dejanzele commented Jul 9, 2026 •

Copy link
Copy Markdown
Contributor

How

Instruments the agent's live-log notification stream (the session manager, replay buffer, and resume path in pkg/controlplaneclient) with Prometheus metrics so we can build dashboards and alerts for live-log streaming. Pure observability, additive, no behaviour change.

Metrics are registered on the default registry, which the agent already serves at /metrics, and are labelled by stream kind (workflow, parallel, service).

Gauges are read at scrape time from the live session managers through one collector, so they always equal the state the managers hold and no code path has to keep them in step:

  • testkube_live_log_sessions (kind, state=active|done) — live and draining session counts.
  • testkube_live_log_replay_bytes (kind) — total buffered replay memory, the number to graph against the buffer budget.
  • testkube_live_log_subscribers (kind) — concurrent viewers.

Counters and the histogram record events where they happen:

  • testkube_live_log_sessions_created_total (kind).
  • testkube_live_log_sessions_evicted_total (kind, reason=ttl|errored|replaced) — every removal from the manager goes through one function, so each eviction is counted once with its reason.
  • testkube_live_log_resume_total (kind, result=available|unavailable) — how often a reconnect actually resumed versus fell back to a full reset. This is the signal that the resume path is working in production.
  • testkube_live_log_source_duration_seconds (kind, result=ok|error) — buckets span 1 s to 2 h, because a source lives as long as the execution it follows.

The replay buffer limits become fields on the manager so the tests can set them. The tests live next to the other session manager tests in testworkflows_test.go and assert the manager's stats snapshot directly; the collector has one test against its exposition text.

@dejanzele
dejanzele requested a review from a team as a code owner July 9, 2026 20:07
@dejanzele
dejanzele requested a review from vsukhin July 9, 2026 20:07
@greptile-apps

greptile-apps Bot commented Jul 9, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds Prometheus observability to the agent's live-log streaming layer — pure additive instrumentation with no behaviour change. Counters and the duration histogram are recorded inline at each event site; session-count and replay-bytes gauges use a pull-based custom collector that reads from the session managers at scrape time, keeping the gauges permanently in step with the managers without any explicit increment/decrement bookkeeping.

  • pkg/controlplaneclient/metrics.go — new file: liveLogCollector (pull-based gauge collector), four counter/histogram Vecs, and prometheus.MustRegister in init().
  • pkg/controlplaneclient/utils.go — removeSessionLocked centralises all map removals (counts each eviction once by reason); liveLogStats() reads the manager under its lock for the scrape; notificationReplayLimits makes buffer bounds a field so tests can tighten them; the previous review concern about a "done" gauge leak when overwriting a non-expired session is resolved — removeSessionLocked calls delete(m.sessions, key) before the new session is inserted, so the pull-based gauge can never observe both the old and new session simultaneously.
  • Test coverage spans session lifecycle, replay-byte accounting, resume and eviction counters, and the collector's exposition text.

Confidence Score: 5/5

  • Pure observability addition with no behaviour changes; the gauge-leak concern from a previous review is fully resolved by the pull-based collector design.
  • All session-map mutations go through removeSessionLocked, which deletes the old entry before the new session is inserted, so the scrape-time gauge computation from the sessions map is always consistent. The lock ordering (manager → session) is uniform across liveLogStats, attach, and scheduleExpiration, ruling out deadlocks. The init() Prometheus registration follows the standard pattern used elsewhere in the codebase. Tests cover the lifecycle end-to-end including eviction, resume, and replay-byte accounting.
  • No files require special attention.

Important Files Changed

Filename Overview
pkg/controlplaneclient/metrics.go New file: adds Prometheus counters, histogram, and a pull-based custom collector (liveLogCollector) for live-log session gauges. Thread-safety is correct — the collector snapshots sources under its own lock before calling liveLogStats (which takes the manager lock), preventing any ordering deadlock.
pkg/controlplaneclient/utils.go Instruments the session manager: adds removeSessionLocked (centralises eviction + counter), liveLogStats (pull-based gauge read from the sessions map), configurable replay limits, and source-duration histogram in runSource. The previous review concern about gauge leaks when overwriting a non-expired session is resolved — removeSessionLocked calls delete(m.sessions, key) before the new session is inserted, so the pull-based gauge can never see the old and new session simultaneously.
pkg/controlplaneclient/runner.go Adds the kind label ("workflow", "parallel", "service") to each session-manager constructor call. Straightforward additive change.
pkg/controlplaneclient/testworkflows_test.go Extends existing tests to pass the new kind parameter, and adds ~370 lines of new metric tests covering session lifecycle stats, replay byte accounting, resume counter results, eviction reason counters, and collector exposition text. counterSince/histogramSamplesSince helpers correctly take baselines to isolate test-local increments on the shared default registry.

Sequence Diagram

sequenceDiagram
    participant Manager as SessionManager
    participant Metrics as liveLogCollector
    participant Prom as Prometheus

    Note over Manager,Prom: Session creation
    Manager->>Manager: attach(req) — lock held
    Manager->>Manager: removeSessionLocked(old, "replaced")
    Manager->>Manager: "sessions[key] = newSession"
    Manager->>Prom: liveLogSessionsCreatedTotal.Inc()

    Note over Manager,Prom: Source lifetime
    Manager->>Manager: runSource(ctx, key, session)
    Manager->>Prom: liveLogSourceDurationSeconds.Observe()
    Manager->>Manager: scheduleExpiration(key, session)

    Note over Manager,Prom: Scrape time (gauges)
    Prom->>Metrics: Collect()
    Metrics->>Metrics: totalsByKind() — snapshot sources (collector lock)
    Metrics->>Manager: liveLogStats() — read sessions (manager lock)
    Manager-->>Metrics: "{active, done, subscribers, replayBytes}"
    Metrics-->>Prom: MustNewConstMetric × 4 per kind

    Note over Manager,Prom: Context ends
    Manager->>Metrics: liveLogMetrics.remove(manager)
Loading

Reviews (2): Last reviewed commit: "test(runner): trim the live-log metrics ..." | Re-trigger Greptile

Comment thread pkg/controlplaneclient/metrics_test.go Outdated
"github.com/kubeshop/testkube/pkg/repository/channels"
)

func TestLiveLogMetricsMoveOnAttachAndPublish(t *testing.T) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do you think this metrics_test should be testing the implementation of the notification stream session manager? It feels like the metrics just defines the metrics and we should have the tests living alongside other tests for the stream manager.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Makes sense, I'll port it so the metrics are tested through an actual flow and test it in testworklows_test.go

@dejanzele
dejanzele force-pushed the fix/live-log-metrics branch from 5bb0132 to 30f8c03 Compare September 7, 2026 09:55
@testkubebot

testkubebot Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

✅ Testkube GitHub Integration

Review based on commit 4ed9810.

All tests and quality gates passed.


Phase Status
Test Workflow Execution ✅ Passed
Quality Gate ✅ Passed

7 workflows executed

✅ lint-go passed
in 4m31s (🚀 07. Sep. 2026 - 11:55:50 UTC / 🏁 07. Sep. 2026 - 12:00:22 UTC)

✅ lint-proto passed
in 8s (🚀 07. Sep. 2026 - 11:55:50 UTC / 🏁 07. Sep. 2026 - 11:55:59 UTC)

✅ integration-tests passed
in 5m57s (🚀 07. Sep. 2026 - 11:55:50 UTC / 🏁 07. Sep. 2026 - 12:01:48 UTC)

✅ unit-tests passed
in 3m23s (🚀 07. Sep. 2026 - 11:55:50 UTC / 🏁 07. Sep. 2026 - 11:59:14 UTC)

✅ verify-crds passed
in 1m6s (🚀 07. Sep. 2026 - 11:55:50 UTC / 🏁 07. Sep. 2026 - 11:56:57 UTC)

✅ verify-protobuf passed
in 14s (🚀 07. Sep. 2026 - 11:55:50 UTC / 🏁 07. Sep. 2026 - 11:56:05 UTC)

✅ lint-pr passed
in 13s (🚀 07. Sep. 2026 - 11:55:50 UTC / 🏁 07. Sep. 2026 - 11:56:04 UTC)


Manage this Integration

@dejanzele

Copy link
Copy Markdown
Contributor Author

@greptileai

@dejanzele
dejanzele merged commit 34a54bf into main Sep 7, 2026
10 checks passed
@dejanzele
dejanzele deleted the fix/live-log-metrics branch September 7, 2026 13:12
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.

2 participants