coralogix-data-usage
Data usage, billing units, plan consumption, quota metrics, anomaly detection, and time-series analysis concepts and query workflow. Load when the user asks about data usage, ingestion volumes, billin
SKILL.mdskills/coralogix-data-usage/SKILL.md
GitHubData Usage Guidance
Purpose
Tool routing
Use the Data Usage Query API by default for billable usage, plan consumption, quota, or a capabilities-supported breakdown: call get_data_usage_capabilities, then query_data_usage.
Use query_promql_* only when the question is about the exported cx_data_usage_* metrics themselves, needs to be combined with other PromQL metrics, or requires monitoring-style analysis unavailable from the Data Usage Query API. Do not substitute PromQL for the Data Usage Query API when an authoritative billing answer is needed.
Complete schemas
Call get_data_usage_capabilities first. It returns the current options that may be sent to query_data_usage: labels and their values, measurement kinds, units, and request limits. Retain the response for the session and use only its returned options in the second tool.
get_data_usage_capabilities response
{
"supportedLabels": [
{
"key": "string",
"keyDescription": "string",
"highCardinality": true,
"knownValues": [
{
"value": "string",
"description": "string"
}
]
}
],
"supportedMeasurements": [
{
"kind": "server-defined measurement kind",
"description": "string",
"unit": "server-defined raw unit"
}
],
"maxUsageEntriesPerMessage": "integer",
"maxGroupByLabels": "integer",
"maxFilters": "integer",
"maxFilterValues": "integer"
}
query_data_usage request
{
"daily": {
"relativeRange": "DAILY_RELATIVE_RANGE_CURRENT_MONTH | DAILY_RELATIVE_RANGE_PREVIOUS_MONTH | DAILY_RELATIVE_RANGE_CURRENT_YEAR | DAILY_RELATIVE_RANGE_LAST_7_DAYS | DAILY_RELATIVE_RANGE_LAST_14_DAYS | DAILY_RELATIVE_RANGE_LAST_30_DAYS | DAILY_RELATIVE_RANGE_LAST_90_DAYS | DAILY_RELATIVE_RANGE_LAST_180_DAYS | DAILY_RELATIVE_RANGE_LAST_365_DAYS",
"dateRange": {
"start": {"year": 2026, "month": 7, "day": 1},
"end": {"year": 2026, "month": 7, "day": 8}
}
},
"hourly": {
"relativeRange": "HOURLY_RELATIVE_RANGE_LAST_12_HOURS | HOURLY_RELATIVE_RANGE_LAST_24_HOURS | HOURLY_RELATIVE_RANGE_LAST_48_HOURS | HOURLY_RELATIVE_RANGE_LAST_7_DAYS | HOURLY_RELATIVE_RANGE_LAST_14_DAYS",
"timeRange": {
"start": "2026-07-20T00:00:00Z",
"end": "2026-07-21T00:00:00Z"
}
},
"groupBy": {
"keys": ["capabilities.supportedLabels[].key"]
},
"filters": [
{
"key": "capabilities.supportedLabels[].key",
"operator": "FILTER_OPERATOR_IN | FILTER_OPERATOR_NOT_IN",
"values": ["string"]
}
],
"measurementKindFilter": [
"capabilities.supportedMeasurements[].kind"
],
"limit": {
"perBucket": 100
}
}
Rules:
- Send exactly one of
dailyorhourly. - Inside
daily, send exactly one ofrelativeRangeordateRange. Daily date ranges are half-open[start, end)UTC dates. - Inside
hourly, send exactly one ofrelativeRangeortimeRange. Hourly absolute timestamps must be RFC 3339 values with a timezone, resolve to the top of a UTC hour, use a half-open[start, end)interval withendafterstart, and span at most 14 days. groupBy,filters,measurementKindFilter, andlimitare optional.- When supplied,
limit.perBucketmust be a positive integer. - All labels, filter values, measurement kinds, and limits must be validated against the capabilities response.
query_data_usage response
{
"queryRange": {
"start": "RFC3339 UTC timestamp",
"end": "RFC3339 UTC timestamp"
},
"buckets": [
{
"range": {
"start": "RFC3339 UTC timestamp",
"end": "RFC3339 UTC timestamp"
},
"entries": [
{
"labels": [
{
"key": "string",
"value": "string"
}
],
"measurements": [
{
"kind": "a kind returned by supportedMeasurements",
"measuredValue": "uint64 encoded as string",
"measuredUnit": "the unit associated with that returned kind",
"cxQuotaUnits": {
"value": "decimal string"
}
}
]
}
]
}
]
}
queryRange is the server-resolved interval. buckets are one UTC day or one UTC hour each. An entry represents one unique groupBy label combination. measuredValue is raw usage in measuredUnit; cxQuotaUnits.value is the billable amount.
Capabilities field → query field mapping
get_data_usage_capabilities field |
Use in query_data_usage |
|---|---|
supportedLabels[].key |
Use as a value in groupBy.keys or filters[].key. |
supportedLabels[].knownValues[].value |
Use as a value in filters[].values for that same label key. |
supportedLabels[].keyDescription / knownValues[].description |
Choose the correct label/value for the user's question; never send these description fields in the query. |
supportedLabels[].highCardinality |
No direct query field. Prefer a narrow filter and small limit.perBucket before grouping by a high-cardinality label. |
supportedMeasurements[].kind |
Use as a value in measurementKindFilter. |
supportedMeasurements[].unit |
No direct query field. Use it to interpret measurements[].measuredValue in the response. |
maxGroupByLabels |
Maximum number of entries in groupBy.keys. |
maxFilters |
Maximum number of objects in filters. |
maxFilterValues |
Maximum number of strings in each filters[].values. |
maxUsageEntriesPerMessage |
No direct query field. Keep limit.perBucket and grouping scope small enough to avoid an oversized response. |
This document teaches the LLM how to answer customer-facing data-usage questions using the customer metrics exporter as the primary source of truth.
The LLM must understand:
- what each exported metric means
- how raw measurements relate to billable units
- which labels can be used for breakdowns
- how to calculate totals, averages, deltas, trends, and plan consumption correctly
The LLM should optimize for correctness over guesswork. If a question is about billing, plan consumption, overage, or usage attribution, it should rely on exported metrics and their labels, not on assumptions.
Core Business Model
Units
Units are the internal billing unit Coralogix charges on.
When a customer signs a plan, they agree to a number of units per day. The USD price per unit is not relevant for this document.
For billing and plan-consumption questions, the canonical metric is:
cx_data_usage_units
Other Measurements
Customers also produce other raw measurements. These measurements are not the billing unit themselves, but they can be converted into units depending on business rules and metadata such as pillar, entity type, priority, and feature.
Examples:
- processed bytes
- evaluation tokens
- egress/system bytes
- metrics samples
- events
The important rule is:
- do not try to infer units from raw bytes, tokens, samples, or events unless explicitly required and a conversion table is available
- for actual billed or plan-consumed usage, prefer
cx_data_usage_units
Measurement Types
The business measurement families in scope are:
ProcessedDataSize: processed bytesEvaluation: measured in tokensEgressDataSize: system bytesProcessedMetricsSamples: metric samplesEvents: event counts
Implementation note:
- current code also contains
InfraMonitoringIngressEvents,ReceivedDataSize, andTokens - for customer-facing metrics in this document,
InfraMonitoringIngressEventsandEventsshould be treated as the infrastructure-events family ReceivedDataSizeandTokensare not part of the current billing metrics scope described here
Source Of Truth
The LLM should use the customer metrics exporter output as the primary source for data usage answers.
Important behavior of the exporter:
- it exports usage from UTC midnight up to an export timestamp
- each exported point represents the cumulative total for the current UTC day at the time of export
- the series reset at midnight UTC (
00:00:00 UTC) - exporter logic aggregates usage for the day and publishes the current daily snapshot, not a per-interval increment
This means:
- an instant query during the day returns "today so far"
- a full-day total must be taken from the last sample of that UTC day, or an equivalent end-of-day snapshot
- the LLM must never subtract points across a midnight boundary as if the series were continuous across days
Metric Naming In Queries
See the metric catalog for Prometheus query names, metric meanings, and the default concept-to-metric mapping.
Labels And Dimensions
See the labels and dimensions reference before choosing breakdowns or filters.
Calculation Rules
See the calculation rules for daily totals, deltas, plan consumption, and PAYG interpretation.
Anomaly Detection
See the anomaly-detection guidance for metric selection, baselines, breakdowns, and partial-day cautions.
Unpacking Vague Time-Series Requests
See the time-series request guidance for bucket selection, partial-period handling, and analysis plans.
Unsafe Query Patterns And Why They Fail
The LLM must avoid query patterns that look plausible but do not match the requested bucket semantics.
Unsafe pattern: direct max_over_time(...[1d]) for weekly analysis
Example:
sum by (pillar, priority) (max_over_time(cx_data_usage_units[1d]))
Why this is unsafe:
- it returns a rolling 1-day maximum, not a completed weekly total
- the result depends on evaluation time
- if evaluated mid-day, the 1-day window can span parts of two UTC days
- by itself, it does not produce a week-by-week time series
- it does not explicitly exclude the current partial UTC day
Unsafe pattern: dropping grouping too early
Example:
sum(max_over_time(cx_data_usage_units[1d]))
Why this is unsafe:
- it removes
pillarandprioritybefore analysis - it prevents correct root-cause breakdown by slice
- it still has the same rolling-window problem as the grouped version
Required pattern for weekly or monthly usage
For weekly or monthly usage analysis, the LLM should reason in this order:
- select the correct metric
- derive completed daily UTC totals
- aggregate those daily totals into the requested bucket
- compute deltas between completed buckets
- perform anomaly analysis on those completed buckets
The LLM should not jump straight from a current-day accumulated series to weekly or monthly conclusions.
Response Quality Rules For Usage And Anomaly Answers
When answering usage-over-time or anomaly questions, the LLM should always make these points explicit:
- which metric was used
- which bucket was used
- whether current partial periods were excluded
- which grouping labels were used
- whether the anomaly analysis is completed-period or partial-period
Do not overstate precision
The LLM should not present rough heuristics as if they were computed facts.
It should not write things like:
- "about 900-1,000 units/week"
- "week-over-week deltas mostly within +-5%"
unless those numbers were actually computed from the chosen metric and bucket definition.
Separate observation from hypothesis
The LLM should distinguish between:
- observed metric behavior
- likely explanation
Good:
- "Weekly units dropped relative to the prior completed weeks."
- "The drop is concentrated in
measurement_type=...andpillar=...." - "A configuration or policy change is one possible explanation, but that is not proven by this metric alone."
Bad:
- "This was caused by a TCO change."
unless the underlying breakdown actually shows that.
Prefer completed-bucket findings
For anomaly answers, the LLM should prefer statements like:
- "Completed UTC weeks are stable except for one positive spike."
- "Completed UTC days suggest a temporary spike rather than a sustained upward trend."
This is better than mixing partial-day and completed-day interpretations in one summary.
Query Execution
This skill covers what to query and how to interpret results. Use the Data Usage Query API for billing answers. For PromQL-only analysis, load coralogix-metrics-query.
Quick reference for data-usage queries:
- Billable totals, breakdowns, plan consumption, or quota →
get_data_usage_capabilities, thenquery_data_usage - PromQL metric monitoring or correlation with other metrics →
query_promql_instant/query_promql_range- Align
startandendto UTC midnight (00:00:00 UTC). Do not use floatingnow-7d..nowwindows for daily, weekly, or monthly totals. - For completed-day/week/month totals and anomaly analysis, set
endto the most recent completed UTC midnight (exclude the current partial day) unless the user explicitly wants "today so far".
- Align
- Metric discovery (verify a metric exists or explore its labels) →
search_relevant_metrics/get_metric_labels
How The LLM Should Answer Common Questions
"How many units have we used today?"
Use:
sum(cx_data_usage_units)
Answer as:
- today's units so far, in UTC-day semantics
"What is our daily plan and how much is left?"
Use:
cx_data_plan_units_per_daysum(cx_data_usage_units)- optionally
cx_data_usage_payg_units
Answer with:
- plan units
- used units today
- remaining units before overage
- PAYG units if already exceeded
"Which feature is driving usage?"
Use:
sum by (feature_group_id, feature_id) (cx_data_usage_units)
Answer with:
- the top feature groups or features by units
"How much logs usage do we have today?"
Use:
sum(cx_data_usage_units{pillar="logs"})for billing impactsum(cx_data_usage_bytes_total{pillar="logs"})for raw processed bytes
Answer with:
- units if the user cares about plan/billing
- bytes if the user cares about raw ingestion volume
"How many AI evaluation tokens were used?"
Use:
sum(cx_data_usage_tokens_total)
If the user also asks how that affected billing:
- add
sum(cx_data_usage_units{measurement_type=\"evaluation\"})
"How did today compare with yesterday?"
If the question is about usage totals:
- compare today's current partial total with yesterday's total only if you clearly say "today so far vs full yesterday"
- otherwise compare completed-day totals for both days
The LLM must make the comparison basis explicit.
Interpretation Guardrails
The LLM must follow these rules:
- never treat bytes, tokens, samples, or events as billable units unless using
cx_data_usage_units - never compare values across UTC days without accounting for the midnight reset
- never assume optional labels exist on every series
- never assume all priorities are valid for all entity types
- never mix customers; queries must stay scoped to the relevant customer exporter or tenant scope
- when a user asks for "usage", prefer clarifying whether they want raw measurement or billable units, unless context already makes it obvious
Known Naming Gaps To Keep In Mind
There are a few naming differences between business language and implementation:
- business conversations may say
events, while current metric labels may useinfra_monitoring_ingress_events - internal code contains more enum variants than the current customer-facing metrics scope
The LLM should normalize these differences when reasoning, but should preserve the actual metric and label names when generating queries.