Skip to content

Enable Span Metrics Alert Rules and Custom Span Alert Rules

Since v0.33.0, Insight has built in core monitoring alert policies for service traces (SpanMetrics). When installing Insight with Helm, you can enable them with the parameter --set victoria-metrics-k8s-stack.defaultRules.spanmetrics=true. Once enabled, you do not need to configure the basic rules manually. Automated monitoring and anomaly alerts for the two key dimensions of service or API call error rate and request latency are then available, which further lowers the barrier to adopting observability and improves the efficiency of issue discovery in microservice architectures.

This document describes in detail the SpanMetrics alert rules (of type VMRule) built into the Insight observability platform, helping you understand the meaning of the metrics and the PromQL logic behind each alert rule, so that you can correctly configure or customize the related alert rules in the Alert Center.

This group of rules supports anomaly detection at both the service level (the whole service dimension) and the Span level (the specific API/method dimension), covering overall service health and fine-grained issue localization.

Built-in Alert Rules

The built-in rules contain 4 core alerts in total, divided into the two categories of error rate and latency and covering the two granularities of service and Span. The specific configuration is shown in the following table:

Alert Name Monitoring Dimension Monitoring Metric Trigger Condition Severity Duration
ServiceErrorRate Service-level error rate calls_total Error rate of server-side spans ≥ 15% (statistical window: 10 minutes) critical 10 minutes
SpanErrorRate Span-level error rate calls_total Error rate of server-side spans of a specific API ≥ 15% (statistical window: 10 minutes) critical 10 minutes
ServiceLatency Service-level average latency duration_milliseconds_bucket Average server-side span latency ≥ 1000 ms (1 second, statistical window: 10 minutes) critical 10 minutes
SpanLatency Span-level average latency duration_milliseconds_bucket Average server-side span latency of a specific API ≥ 1000 ms (1 second, statistical window: 10 minutes) critical 10 minutes

The following is the specific content of the built-in alert rules:

apiVersion: operator.victoriametrics.com/v1beta1
kind: VMRule
metadata:
  name: spanmetrics
  namespace: insight-system
  labels:
    # Rules are deployed in the insight-system namespace by default; alert rules with this label are built-in rules
    "operator.insight.io/builtin-rule": "true" 
spec:
  groups:
  - name: spanmetrics
    rules:
    - alert: ServiceErrorRate
      annotations:
        description: Error rate of Service {{ $labels.service_name }} in cluster/namespace {{ $labels.cluster }}/{{ $labels.k8s_namespace_name }} is greater than {{ printf "%.2f" $value }}%.'
      expr: 100 * (sum(rate(calls_total{status_code="STATUS_CODE_ERROR",span_kind =~"SPAN_KIND_SERVER"}[10m])) by (cluster,namespace,k8s_namespace_name,k8s,service_name) / sum(rate(calls_total{span_kind =~"SPAN_KIND_SERVER"}[10m])) by (cluster,namespace,k8s_namespace_name,service_name)) >= 15
      for: 10m
      labels:
        severity: critical
        # namespace from k8s_namespace_name: backward Backwards-compatible scenarios where the agent is not upgraded
        namespace: '{{ $labels.k8s_namespace_name }}'
    - alert: SpanErrorRate
      annotations:
        description: Error rate of SpanName {{ $labels.span_name }} of {{ $labels.pod }} Service {{ $labels.service_name }} in cluster/namespace {{ $labels.cluster }}/{{ $labels.k8s_namespace_name }} is greater than {{ printf "%.2f" $value }}%.
      expr: 100 * (sum(rate(calls_total{status_code="STATUS_CODE_ERROR",span_kind =~"SPAN_KIND_SERVER"}[10m])) by (cluster,namespace,k8s_namespace_name,service_name,span_name) / sum(rate(calls_total{span_kind =~"SPAN_KIND_SERVER"}[10m])) by (cluster,namespace,k8s_namespace_name,service_name,span_name)) >= 15
      for: 10m
      labels:
        severity: critical
        namespace: '{{ $labels.k8s_namespace_name }}'
    - alert: ServiceLatency
      annotations:
        description: Latency of Service {{ $labels.service_name }} in cluster/namespace {{ $labels.cluster }}/{{ $labels.k8s_namespace_name }} is greater than {{ printf "%.2f" $value }}.
      expr: (sum(rate(duration_milliseconds_bucket{span_kind =~"SPAN_KIND_SERVER"}[10m])) by (cluster,namespace,k8s_namespace_name,service_name,le)) >= 1000
      for: 10m
      labels:
        severity: critical
        namespace: '{{ $labels.k8s_namespace_name }}'
    - alert: SpanLatency
      annotations:
        description: Latency of SpanName {{ $labels.span_name }} of {{ $labels.pod }} Service {{ $labels.service_name }} in cluster/namespace {{ $labels.cluster }}/{{ $labels.k8s_namespace_name }} is greater than {{ printf "%.2f" $value }}.
      expr: (sum(rate(duration_milliseconds_bucket{span_kind =~"SPAN_KIND_SERVER"}[10m])) by (cluster,namespace,k8s_namespace_name,service_name,span_name,le)) >= 1000
      for: 10m
      labels:
        severity: critical
        namespace: '{{ $labels.k8s_namespace_name }}'

Rule Characteristics

  • Statistical scope: Only span_kind=~"SPAN_KIND_SERVER" (server-side spans) is covered, focusing on the APIs that a service exposes to the outside and excluding non-core scenarios such as clients and internal traces;
  • Metric calculation: The error rate is calculated with the rate function to obtain the per-second call rate, and the latency is calculated with the increase function to obtain the counter increment, which avoids loss of precision and follows the best practices for Prometheus counter metrics;
  • Label pass-through: Alert messages include key labels such as cluster, service_name, k8s_namespace_name, and span_name, which makes it easy to quickly locate the environment and business module to which an issue belongs.

Custom Rules

This section mainly illustrates how to write PromQL statements to meet business requirements when creating rules. For UI operations, see Alert Policies.

For example:

  • First create an alert policy for the Cluster object:

    Example alert group for the payment service

  • Then add an alert rule with PromQL:

    Example alert rule for the payment service

The following are PromQL examples for different scenarios:

Example 1

Adjust the error rate threshold for a specific service (strict monitoring for a core service): for the payment service (service_name: "pay-service"), you need to lower the error rate threshold from the built-in 15% to 5%, and an alert is triggered only after the condition persists for 5 minutes.

100 * (sum(rate(calls_total{status_code="STATUS_CODE_ERROR",span_kind=~"SPAN_KIND_SERVER",service_name="pay-service"}[5m])) by (cluster,service_name,k8s_namespace_name) / sum(rate(calls_total{span_kind=~"SPAN_KIND_SERVER",service_name="pay-service"}[5m])) by (cluster,service_name,k8s_namespace_name)) >= 5

Example 2

Monitor the P95 latency of a specific service (fine-grained performance monitoring): for the "createOrder" API (span_name: "createOrder") of the order service, you need to monitor its P95 latency and trigger an alert once it exceeds 800 ms.

histogram_quantile(0.95, sum(rate(duration_milliseconds_bucket{span_kind=~"SPAN_KIND_SERVER",service_name="order-service",span_name="createOrder"}[10m])) by (cluster,k8s_namespace_name,service_name,span_name,le)) >= 800

Note

The built-in rules only monitor the average latency. The P95/P99 percentile latency must be calculated based on duration_milliseconds_bucket (a histogram metric), which better matches the real user experience.

Example 3

Monitor a sudden drop in service call volume (availability fallback monitoring): the call volume of the user service (service_name: "user-service") suddenly drops by more than 50%, which may mean that the service is unavailable or the traffic is abnormal, and an alert needs to be sent in time.

rate(calls_total{span_kind=~"SPAN_KIND_SERVER",service_name="user-service"}[5m]) / rate(calls_total{span_kind=~"SPAN_KIND_SERVER",service_name="user-service"}[5m] offset 5m) <= 0.5

Comments