Snapshot surface

Snapshots are the read surface of MVX Metrics.

They expose current metric state without exposing metric internals.

A metric owns its state.

A recorder owns metric instances.

A snapshot is the structured boundary where that state becomes visible to application code, tests, diagnostics, or integration adapters.

What the snapshot surface separates

The snapshot surface separates three things:

metric internals
   |
   v
metric snapshot
   |
   v
external consumers

Metric internals remain private.

External code reads snapshots.

This allows a metric to change its internal implementation without forcing callers to read private fields.

Metric-level snapshot

Each metric defines its own snapshot.

def snapshot(self) -> Mapping[str, Any]:
    return {
        "name": self.metric_name,
        "dimensions": {
            "total": self._total,
            "success_total": self._success_total,
            "failure_total": self._failure_total,
        },
    }

The metric decides which values are part of its public state.

The recorder does not build those values.

The runtime does not build those values.

The metric owns both:

  • measured state;

  • public snapshot shape for that state.

Recorder-level snapshot collection

A recorder collects snapshots from the metrics registered inside it.

snapshots = recorder.get_metric_snapshots()

Architecturally, the recorder-level snapshot surface is:

recorder
   |
   v
registered metric
   |
   v
metric.snapshot()
   |
   v
mapping by metric name

The recorder returns a mapping:

metric name
   |
   v
metric snapshot

For example:

{
    "document_storage.save.attempts": {
        "name": "document_storage.save.attempts",
        "dimensions": {
            "total": 3,
            "success_total": 2,
            "failure_total": 1,
        },
    },
}

The recorder coordinates access.

The metric owns the content.

Scope of a recorder snapshot

A recorder snapshot is scoped to that recorder.

If the recorder represents one component instance, the snapshot describes that component instance.

If the recorder represents one connection, the snapshot describes that connection.

If an application uses one recorder per measured entity, each recorder exposes the current state for one measured entity.

recorder: connection-001
   |
   v
snapshots for connection-001

recorder: connection-002
   |
   v
snapshots for connection-002

The snapshot surface follows the recorder ownership model.

It is not automatically global.

Snapshot access and recorder ownership

A recorder is an asynchronous processing component.

Its metrics live inside the recorder’s processing model.

Snapshot access must respect recorder ownership.

From the caller’s point of view:

snapshots = recorder.get_metric_snapshots()

is a simple inspection call.

Internally, the recorder is responsible for collecting snapshots consistently from its registered metrics.

If the recorder is owned by MetricsRuntime, snapshot access is coordinated with the recorder’s runtime-owned event loop.

The caller does not need to manage that coordination directly.

Current state, not history

A snapshot exposes current aggregated state.

It does not contain the event stream that produced that state.

events processed:
   SUCCESS
   SUCCESS
   FAILURE

snapshot:
   total = 3
   success_total = 2
   failure_total = 1

The event history is not part of the snapshot surface.

If a project needs time-series storage, history retention, or long-term querying, that belongs to an external monitoring or storage layer.

Snapshot is not export

A snapshot is not an exporter.

It does not decide where metric state should go.

It only exposes state in a structured form.

metric state
   |
   v
snapshot
   |
   v
optional consumer or adapter

Possible consumers include:

  • tests;

  • diagnostic tools;

  • health checks;

  • dashboards;

  • custom exporters;

  • external monitoring adapters.

This keeps the core metrics package independent from the final monitoring platform.

Snapshot stability

Snapshot names and dimension names are part of the observable surface of a metric.

Internal metric fields may change.

Snapshot structure should change more carefully.

For example, external code may rely on:

{
    "name": "document_storage.save.attempts",
    "dimensions": {
        "total": 3,
        "success_total": 2,
        "failure_total": 1,
    },
}

Changing private fields such as _total affects only the metric implementation.

Changing public dimension names such as success_total affects tests, diagnostics, exporters, and adapters.

For this reason, snapshot shape should be treated as a public contract of the metric.

Snapshot consumers

Snapshot consumers should depend on the public snapshot shape, not on metric internals.

Good:

consumer
   |
   v
recorder.get_metric_snapshots()
   |
   v
snapshot data

Bad:

consumer
   |
   v
metric._private_field

This boundary is especially important for adapters.

An adapter should not need to know how a metric stores its internal counters.

It should consume the metric snapshot.

Integration edge

The snapshot surface is one of the main edges where MVX Metrics can connect to external systems later.

The core pipeline can already work without a final monitoring platform:

production code
   |
   v
metric events
   |
   v
metrics
   |
   v
snapshots

Later, an adapter can be added at the snapshot edge:

snapshots
   |
   v
adapter
   |
   v
external monitoring platform

That lets production code remain unchanged.

The metric event model and aggregation logic are already in place.

Only the outer integration layer changes.

Snapshot surface in the architecture

The snapshot surface sits after metric processing.

MetricEvent
   |
   v
Recorder
   |
   v
Metric.handle_event(event)
   |
   v
Metric state
   |
   v
Metric.snapshot()
   |
   v
Recorder.get_metric_snapshots()
   |
   v
External consumer

This placement matters.

Snapshots are not part of event emission.

They are not part of event dispatch.

They are the read side of the current metric state.

Summary

The snapshot surface is the read boundary of MVX Metrics.

Metrics create snapshots from their own state.

Recorders collect snapshots from registered metrics.

Consumers read snapshots instead of metric internals.

Snapshots expose current state, not event history.

They are also a natural integration edge for tests, diagnostics, dashboards, exporters, and future monitoring adapters.