Skip to content

Metric Labels and Conventions⚓︎

Every metric xView stores carries labels, and they do two jobs. Some identify where a measurement came from — which site, which customer, which network function — and xView attaches those itself as metrics travel in from the sites. Others describe what was measured, and those come from the component that produced the metric.

This page specifies both: the identity labels the platform adds to every xCore metric, and the convention Expeto components follow when labelling protocol traffic. Read it before writing a PromQL query, an alert rule or a dashboard — nearly every useful query aggregates over one of these labels.

Identity labels⚓︎

These labels answer "where did this come from?". They are attached automatically; no component has to emit them.

Label Meaning Attached by Example
site Human-readable Site name, as configured in xControl xControl, at discovery AcmeCorp-Plant-01
siteId Stable identifier for the Site, as a full API URI xControl, at discovery https://api.example.com/v1/sites/81251
customer Human-readable Customer name xControl, at discovery AcmeCorp
customerId Stable identifier for the Customer, as a full API URI xControl, at discovery https://api.example.com/v1/customers/20806
site_state Operational state of the Site; suppresses alerts when set Site extension in xControl maintenance
xName Name of the monitoring endpoint the metrics came from The Expeto Agent xAgent
vmName Name of the xView deployment that collected the metric xView expeto-central
cluster Name of the cluster xView is running in xView expeto-central
nfnode, nfnodeip The individual network function instance a metric describes The Expeto Agent mme-a, 192.0.2.122
job The scrape job that collected the metric The scrape configuration xAgent
instance The target address that was scraped Prometheus convention 192.0.2.10:9767

Important

siteId and customerId are full URIs, not numbers. Match them with =~".*/v1/sites/81251" or compare them to the value exactly as it appears; a query written as siteId="81251" matches nothing. The URI is stable across renames, which is why alert annotations quote it alongside the human-readable name.

Where identity labels are attached⚓︎

Identity labels are added at xControl, when it publishes the list of sites for xView to scrape — not at the site and not by the network functions. This matters in two ways.

First, renaming a Site in xControl changes the site label on everything that site reports from the next scrape onward, with no change at the site itself.

Second, the labels can be overridden. xControl applies them in a fixed order of precedence:

  1. Extensions on the site's monitoring feature (highest)
  2. Extensions on the Site
  3. The default labels above (lowest)

Any extension whose key begins with label. becomes a metric label, with the prefix stripped — so an extension label.region with value west adds region="west" to everything that site reports. Overriding customer or site is a supported way to keep human-readable customer names out of a monitoring system that other parties can see.

Note

Scrapes are configured to honor labels already present in the scraped data. If a site's metrics already carry a label, that value wins over the one xView would attach. This is what lets each site's identity survive being collected through a single shared endpoint.

Suspending monitoring for a site⚓︎

Nearly every Expeto alert expression carries the guard site_state!~"decommissioned|maintenance". Setting the Site's state is therefore how you suppress a site's alerts for planned work — it is a property of the Site, not a silence that expires.

To suspend monitoring for a Site:

  1. Open xControl, navigate to Sites, and click the name of the Site.
  2. Click Edit.
  3. Create or edit the extension label.site_state.
  4. Set the value to maintenance (planned work, expected to return) or decommissioned (the site is being retired).
  5. Click Save.

The extension appears with the Site's other key parameters. To resume monitoring, delete the extension or set it to enabled.

Warning

A suspended Site raises no alerts at all — including alerts that would tell you the maintenance itself has gone wrong. Clear the state as soon as the work is finished.

Traffic-metric conventions⚓︎

Protocol counters are the metrics you reach for when answering "is this interface healthy?". They follow one pattern across the platform:

xcore_<nf>_<protocol>_total{direction, message, type, cause}

One metric per protocol, with the detail in labels rather than in the metric name. The four labels are:

Label Answers Values
direction Which way did it go? inbound, outbound, and the drop/retry variants below
message Which protocol message was it? The message name, lowercased, e.g. session_establishment
type Which part of the exchange? request, response, and the protocol-specific variants below
cause How did it end? The protocol's own result code, by name, e.g. request_accepted

This shape is what makes cross-protocol queries possible. To find every rejected request a site handled, regardless of protocol, count the responses whose cause is neither success value:

sum by (site, job) (
  rate({__name__=~"xcore_.+_total", type="response", cause!="", cause!~"success|request_accepted"}[5m])
)

Both extra matchers are load-bearing. type="response" keeps requests out: they carry no cause, and a negative regex match against an absent label succeeds, so without it every request would be counted as a rejection. cause!="" then drops responses that carry no cause at all — which is the case for the MME's counters — since those would otherwise be counted as rejections too.

direction⚓︎

Value Meaning
inbound Received by this network function
outbound Sent by this network function
inbound_drop Received and discarded without being processed
outbound_retry Re-sent after no response arrived in time

Counting drops and retries separately is deliberate: inbound_drop isolates overload and malformed traffic from healthy receive volume, and outbound_retry exposes a peer that is failing to answer before the retransmission shows up as a timeout elsewhere.

Note

A few of the smaller MME interfaces use the abbreviated forms in, out and in_drop rather than the full words. When writing a query that must cover every interface, match with direction=~"in.*" and direction=~"out.*" rather than listing exact values.

type⚓︎

request and response cover most traffic. Protocols with richer exchanges add their own values: S1AP uses indication, command, complete, confirm, failure, notify, ack and others; NAS uses accept, reject, complete, fail and command. Where a protocol has no request/response structure for a message, type is msg.

cause⚓︎

cause carries the protocol's own result, converted to a lowercase name — request_accepted, user_unknown, system_failure. It is present only on responses, so a query that groups by cause should filter to type="response" to avoid counting requests into an empty bucket.

Note

On the service-based interface the cause label holds the HTTP status code as a string ("200", "404"), because that is the result the protocol defines. Treat it as a name, not a number — PromQL will not order it numerically.

Per-protocol reference⚓︎

Labels carried by each protocol counter, as deployed:

Protocol Metric direction message type cause
PFCP (N4) xcore_smf_pfcp_total ● ● ● ●
GTP-C v2 (S5/S8, S11) xcore_smf_gtp_2_total ● ● ● ●
GTP-C v1 (Gn/Gp) xcore_smf_gtp_1_total ● ● ● ●
SBI (N11) xcore_smf_n11_total ● ● ● ●
S1AP xcore_mme_s1ap_total ● ● ●
NAS xcore_mme_nas_total ● ● ●
GTP-C v2 (MME) xcore_mme_gtpv2_total ● ● ●
GTP-C v1 (MME) xcore_mme_gtpv1_total ● ● ●
Diameter (MME) xcore_mme_diameter_total ● ● ●
S6a/S6d xcore_hss_s6_messages_total ● ● ●
Other Diameter interfaces xcore_hss_<interface>_messages_total ● ● ●
MAP xcore_hss_map_messages_total ● ● ●

The HSS family covers every Diameter reference point the platform implements — s6, s6b, s6c, s6t, s6mn, s13, sh, slh, swm, swx, staswa, cxdx and zh — plus map and sip. They share one shape, so a query written for one works for all of them by changing the interface.

Where a cell is blank, that dimension is not currently reported for that protocol: the MME's counters do not carry cause, and the HSS's do not carry direction (the message name and type together imply it on those interfaces).

Message and cause vocabularies⚓︎

The values are the protocol's own message and result names, lowercased with words separated by underscores. Representative sets:

message: association_setup, heartbeat, session_establishment, session_modification, session_deletion, session_report

cause: request_accepted, request_rejected, mandatory_ie_incorrect, session_context_not_found, system_failure

message: create_session, modify_bearer, modify_bearer_cmd, delete_session, create_bearer, update_bearer, delete_bearer, release_access_bearers, downlink_data_notif, downlink_data_notif_ack, echo

cause: request_accepted, request_rejected_(reason_not_specified), context_not_found, imsi/imei_not_known, invalid_message_format, no_resources_available, unable_to_page_ue, system_failure

message: authentication_information, update_location, cancel_location, insert_subscriber_data, delete_subscriber_data, purge_ue, notification, reset, routing_info

cause: success, user_unknown, unknown_eps_subscription, rat_not_allowed, roaming_not_allowed, authentication_data_unavailable, authentication_rejected, authorization_rejected, diameter_too_busy, missing_avp, unable_to_comply, system_error

message: s1_setup, initial_uemsg, initial_ctxt_setup, uectxt_mod, uectxt_rel, e_rabsetup, e_rabmod, e_rabrel, handover, path_switch_req, paging, uplink_nastrnspt, downlink_nastrnspt, reset, error

type: request, response, command, complete, confirm, failure, indication, notify, ack, required, preparation_failure

message: att, det, tau, auth, auth_fail, ident, sec_mod, service, pdn_conn, pdn_disconn, act_def_eps_brr_ctx, act_ded_eps_brr_ctx, deact_eps_brr_ctx, mod_eps_brr_ctx, uplink_sms, downlink_sms

type: request, accept, reject, complete, fail, command, msg

message: smcontextcreate, smcontextupdate, smcontextrelease

cause: the HTTP status code as a string — 200, 201, 404, 500

Additional labels on protocol metrics⚓︎

smf_id appears on SMF counters, identifying which SMF instance within the site reported the metric. Aggregate over it unless you are specifically comparing instances:

sum without (smf_id) (rate(xcore_smf_pfcp_total{type="request"}[5m]))

Peer identity is carried by nfnode and nfnodeip rather than by a dedicated peer label, and the interface is part of the metric name rather than a label.

Writing queries against these labels⚓︎

A few patterns cover most needs.

Per-site message rate for one interface:

sum by (site) (rate(xcore_smf_pfcp_total{message="session_establishment", type="request"}[5m]))

Failure ratio on an interface, as a proportion of responses:

sum by (site) (rate(xcore_hss_s6_messages_total{type="response", cause!="success"}[5m]))
  /
sum by (site) (rate(xcore_hss_s6_messages_total{type="response"}[5m]))

One customer's sites only, using the stable identifier:

sum by (site) (rate(xcore_mme_nas_total{customerId=~".*/v1/customers/20806", message="att"}[5m]))

Retransmissions, which usually indicate an unresponsive peer:

sum by (site, nfnode) (rate(xcore_mme_diameter_total{direction="outbound_retry"}[5m]))

Tip

Always aggregate away instance and nfnode unless you need them. A site with several instances of a function reports one series per instance, and a query that keeps them produces a graph per instance rather than the per-site figure you probably wanted.

Conventions for new instrumentation⚓︎

If you are adding a metric to an Expeto component, follow the pattern above rather than inventing a new one. In particular:

  • Put the varying part in a label, not in the metric name. One ..._total with a message label, not one metric per message. Metric names that encode the outcome cannot be aggregated, and every dashboard has to be rewritten when a new message type appears.
  • Use the vocabularies on this page. direction is inbound/outbound, not rx/tx or in/out; type is request/response; success and failure belong in cause, not in the metric name.
  • Name the protocol's own values, don't renumber them. A cause is the protocol's result name, lowercased — not an internal enum ordinal.
  • Keep cardinality bounded. Labels take values from a fixed, protocol-defined set. An address, a session identifier or a subscriber identity must never become a label value.
  • Let the platform add identity. Do not emit site, customer or their identifiers yourself; they are attached centrally, and a locally-emitted copy will win over the correct value and be wrong the moment a Site is renamed.