Derive a metric from your logs
Count matching logs, or sum one numeric log field, into a metric with fixed buckets, revisions, late accounting and freshness.
On this page
A log-derived metric rule turns your logs into a metric without changing what you ship: it counts logs that match a condition, or sums one finite numeric field across them, into fixed time buckets. Your agent creates and revises the rules, and reads the result. The result reads like any other metric (see Explore and compare metrics), through MCP, through the CLI, or in a dashboard widget. It has its own freshness and completeness reporting, so you always know whether a bucket is still settling.
Ask your agent
Create a metric
checkout.errorsthat counts error logs per minute, grouped by route. Show me the preview first. Then read it for the last 24 hours and tell me whether the buckets are complete.
| Job | MCP tool or action | CLI command |
|---|---|---|
| List the rules, and read one with every revision | list_log_metrics, get_log_metric |
anectico metrics rules list, anectico metrics rules get, anectico metrics rules revisions |
| Create a rule | create_log_metric |
anectico metrics rules create |
| Check a rule spec against every limit without storing it | the preview of create_log_metric |
anectico metrics rules validate |
| Edit a rule, or roll it back | revise_log_metric |
anectico metrics rules revise |
| Read the published series | query_log_metric |
anectico metrics rules query |
| Delete a rule | delete_log_metric |
anectico metrics rules delete |
Reading needs metrics:read. Creating, revising, and deleting need ingestion:pipelines:write and
metrics:read. MCP calls also need mcp:read or mcp:write. Every write is a preview and confirm
write.
What your agent gets back
query_log_metric returns the published per-bucket series with its watermark, its completeness, the
windows that are withheld, and the late-log count. Values are bucket counts or sums. They are never
cumulative counters. A rule read returns every immutable revision, newest first, and the instant each
one started applying to received logs.
Open the proof
A log-derived metric has no page of its own. Ask the agent to chart it on a dashboard and open the dashboard page from the link the agent returns. See Investigate service health and dashboards.
What a rule fixes and what stays revisable
A rule fixes four things for its whole life: the metric name, the aggregation (count or
sum), the unit (a short label such as 1, ms or By), and the bucket width — one of
60, 300, 600, 900, 1800, 3600 or 86400 seconds. These cannot change after creation;
create a new rule if you need a different one of them.
Everything else is a revision, and every edit — including a rollback — appends a new one rather than changing history in place:
- Match conditions (up to 8): each tests one field —
body,severity,service_name, an attribute (attributes.<key>) or a resource field (resource.<key>) — for an exact match, a regular-expression match, or presence/absence. All conditions must hold; an empty list matches every log. - Value field (
sumrules only): the numeric attribute or resource field to add up. A value that is not a finite number (not parseable,NaN, or infinite) contributes nothing for that log rather than being coerced to zero. - Labels (up to 4): fields whose distinct combination of values becomes a separate series, the
same way a dashboard groups a metric by a dimension. A label may name
service_name,severity, an attribute or a resource field — never a person or session identifier, a URL, an address, a credential, or recorded message/prompt content. A rule that tries to label on one of these is refused before anything is stored (DERIVED_LABEL_FORBIDDEN). A label value longer than 128 bytes is stored as the fixed placeholder__invalid__rather than being truncated into a different, silently-merged value. - Series ceiling (default 100, 1–1000): once a bucket has more distinct label combinations than
this, the excess collapses into one overflow series labelled
__overflow__: "true". A query reports when a bucket overflowed so you know some combinations were folded together rather than dropped. - Late cutoff (default 300 seconds, 0–3600): how long after a bucket closes a log can still
arrive and count toward its value. A log that arrives later is recorded in
late_countand never added to any value — a bucket's late count can rise after you first read it, but its stored values never change retroactively. - Source (optional): restricts the rule to logs from one intake source instead of every source in the project.
- Enabled: a disabled revision derives nothing while it is in effect; re-enabling appends another revision rather than reactivating the old one.
When a revision takes effect
A saved revision — an edit or a rollback — starts applying to logs 10 seconds after it is saved, never to logs already received. A log keeps the revision that was in effect when your platform received it, so replaying or reprocessing the same log never recounts it under a different rule. Because of this, changing a rule can never rewrite an earlier bucket's value; only what is derived going forward changes.
Rollback copies an earlier revision's definition forward as a new revision — it does not delete
or replay history. Roll back to revision N and the rule immediately starts deriving from that
definition again, itself effective 10 seconds later, exactly like any other edit.
Every edit and rollback requires the rule's current revision number so a save can never silently overwrite a change you have not seen; a stale number is refused as a conflict rather than applied.
Reading the metric
Query a log-derived metric the same way as any other: pick a time range and, optionally, a step (a whole multiple of the rule's bucket width) and up to one label to group by. Grouping by a subset of a series' labels sums the other labels away rather than merely hiding them — two series that agree on the kept label become one combined value. A value is always a per-bucket count or sum, not a running total: reading the same bucket twice returns the same number unless a late log or a correction changed it.
Every read carries its own freshness:
- Current — every bucket in range reflects every log received for it, as of the reported watermark.
- Rebuild pending — newer logs have arrived for some buckets and are being folded in; the shown values are the last settled ones, not stale placeholders.
- Invalidated — a deletion affecting this project is being applied, and the affected buckets are withheld until it finishes rather than served from a value that might include what was just deleted.
A read also reports complete through — the instant before which every bucket is settled, current and past its late cutoff — and the late count in range, so a bucket that looks low because logs are still arriving late is never confused with a bucket that is genuinely low.
Deletion
Deleting one log removes its contribution to every rule it matched, using the same identity your log already has — an identical duplicate of a log counts once, and a later log that is byte-for-byte the same after a capture or transform change is a different log and is counted separately. Deleting a rule stops deriving anything new from it and its series stop being readable; the rule's history is not recoverable.
Limits
| Limit | Value |
|---|---|
| Live rules per project | 50 |
| Revisions per rule | 200 |
| Match conditions per revision | 8 |
| Labels per revision | 4 |
| Series ceiling | 1–1000 (default 100) |
| Late cutoff | 0–3600 seconds (default 300) |
| Metric name | lowercase, [a-z][a-z0-9_.]*, at most 128 bytes, unique per project |
| Query range | at most 400 bucket windows, at most 2000 steps |
A metric name is reusable once the rule that held it is deleted.
Manage rules from the CLI and the API
anectico metrics rules list
anectico metrics rules create --body '{
"metric_name": "checkout.errors",
"aggregation": "LOG_METRIC_AGGREGATION_COUNT",
"unit": "1",
"bucket_seconds": 60,
"definition": {
"match": [{"field": "severity", "equals": "error"}],
"labels": ["attributes.http.route"],
"max_series": 100,
"enabled": true
}
}'
anectico metrics rules validate --body '{...}'
anectico metrics rules revise <rule-id> --expected-revision 1 --body '{"enabled": false}'
anectico metrics rules revise <rule-id> --expected-revision 2 --rollback-to 1
anectico metrics rules query <rule-id> --window 24h --step 5m --group-by http.route
anectico metrics rules delete <rule-id> --yes
validate checks a rule spec against every limit above without saving a metric rule — use it before
create or revise to see the exact diagnostics a save would be refused with. The complete flag
contract is in the CLI command reference.
Resolve empty or unexpected results
-
A rule was refused at creation: run
validatefirst; the diagnostics name the exact field and limit. -
A series is missing right after an edit: the new revision has not taken effect yet — wait 10 seconds past the save and query again.
-
A bucket looks lower than expected: check the late count for that read; logs arriving after the late cutoff never add to a value.
-
A series is missing labels you expect: confirm you did not group by a subset that sums it into another series, and check whether the bucket overflowed.
-
A read is withheld: the project has a deletion in progress; retry once it completes.
-
A step is refused: it must be a whole multiple of the rule's bucket width.