Skip to content

feat: expose worker Prometheus metrics for matching and eval ingest#1184

Draft
DarshanCode2005 wants to merge 11 commits into
NixOS:mainfrom
DarshanCode2005:metric-endpoint
Draft

feat: expose worker Prometheus metrics for matching and eval ingest#1184
DarshanCode2005 wants to merge 11 commits into
NixOS:mainfrom
DarshanCode2005:metric-endpoint

Conversation

@DarshanCode2005

Copy link
Copy Markdown
Collaborator

Description

Related to #1002. Follows #1141 and #1183.

Problem

Oneshot batch jobs already export last-run gauges through the textfile collector (job="node"). Long-running listen workers (matching and evaluation ingest) only log durations, so operators have no live Prometheus/Grafana visibility into these hot paths.

What this PR does

Adds live prometheus_client HTTP /metrics endpoints for listen workers and instruments the key execution paths.

Exports:

  • sectracker_matching_duration_seconds
  • sectracker_matching_candidates
  • sectracker_nix_evaluation_batch_ingest_duration_seconds
  • sectracker_nix_evaluation_batch_ingest_attributes

Also:

  • Adds METRICS_HTTP_PORT; metrics server starts only in listen --worker processes
  • Exposes worker metrics on :9252 and evaluator multiprocess metrics on :9253
  • Adds firewall ruls and Grafana panels under Application metrics using the sectracker-worker and sectracker-evaluator jobs

Comment thread src/shared/metrics.py
if port is None:
return
start_http_server(port)
_metrics_server_started = True
Comment thread nix/configuration.nix

script = ''
mkdir -p "$PROMETHEUS_MULTIPROC_DIR"
wst-manage serve_worker_metrics

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

My hunch is this could be an ad hoc more-or-less-inline Python HTTP server here, which we put behind the proxy. Seems kind of wrong to weave this into the application code.

Comment thread src/shared/metrics.py
Comment on lines +53 to +62
def observe_matching(duration_seconds: float, candidates: int) -> None:
"""Record matching wall time and candidate cardinality."""
_matching_duration.observe(duration_seconds)
_matching_candidates.observe(float(candidates))


def observe_eval_batch_ingest(duration_seconds: float, attributes: int) -> None:
"""Record eval batch ingest wall time and batch size."""
_eval_batch_duration.observe(duration_seconds)
_eval_batch_attributes.observe(float(attributes))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

These and their subroutines are used exactly once, they may as well be done in place. Rule of thumb: if there's no more than 2 repetitions, extracting (especially into a different place) almost never makes sense. Uncle-Bob-ing a bit for readability is not wrong, but putting into a separate file and wrapping a constructor in a procedure brings no benefit here.

self.stdout.write("\n[1/6] Deleting stale matches")
self._delete_stale_matches(cutoff, batch_size, dry_run)
step_start = time.time()
for kind, count in self._delete_stale_matches(

@fricklerhandwerk fricklerhandwerk Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why not have the helper return its own duration? Then you get rid of the boilerplate at the call site.

And maybe you could also collect the returned dicts kind: count into a list and just sum them up at the end in one go? Then you don't need DELETED_KINDS at all, which confused me quite a bit until I understood what you're trying to do.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oops, this one belongs to #1183

@fricklerhandwerk fricklerhandwerk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Metrics server should be extracted properly. Haven't looked at the dashboards and tests yet.

@fricklerhandwerk fricklerhandwerk marked this pull request as draft July 12, 2026 22:28
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.

3 participants