Collapse the Params-panel ParamDeclaration and the metric-embedded
RegexToMetricPrimitiveMatcher into a single ParamDeclaration type
(name, regex/capture-group-or-json-field-path, kind). MetricDeclaration
now references params by name via label_params: Vec<String> and
value_param: Option<String> instead of embedding its own extractor per
param, so a param declared once in the Params panel can be reused as a
label or value by any number of metrics. Declaring a metric that
references an undeclared param name is now rejected at declare-time.
Backend:
- src/data_value.rs: unified ParamDeclaration struct; MetricDeclaration
data value now carries label_params/value_param instead of a Vec of
inline matchers.
- src/engine.rs: DeclareParamRequest is now an alias for
ParamDeclaration; DeclareMetricRequest carries label_params/
value_param; validate_metric_request checks referenced param names
against the declared-param store; apply_metric_to_log resolves
label_params/value_param against a per-ingest resolved-param map
instead of reading an inline matcher list.
- src/profile.rs: MetricDeclarationRecord carries label_params/
value_param plus a private, serialize-skipped legacy_params field
that only ever gets populated by deserializing a pre-037 profile
file's old "params" key. ProfileStore::load migrates any such legacy
metric into the unified shape (reusing an existing same-shaped bare
param by name, or creating one implicitly named
"<metric_name>.<param_name>"), then persists the migrated store so
the on-disk file only carries the legacy shape once. Migration is
idempotent (deterministic naming) and covered by dedicated tests.
- src/api.rs / src/dto.rs: MetricDeclarationDto and the declare/update
metric response bodies updated to the new shape.
Frontend:
- webapp/src/lib/api.ts: MetricDeclaration type now has label_params/
value_param; MetricParamMatcher/ParamRole types removed.
- webapp/src/components/Metrics.tsx: the declaration form now fetches
declared params and lets you check off label params / pick a value
param from that list, instead of re-entering a regex/capture-group/
kind per metric param.
Leaves ticket 038 (duration as a derived param kind) and 039 (param
query resolving declared params) untouched, as scoped.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o