Skip to main content

Prometheus

The prometheus plugin provides the capability to integrate APISIX with Prometheus.

After enabling the plugin, APISIX will start collecting relevant metrics, such as API requests and latencies, and exporting them in a text-based exposition format to Prometheus. You can then create event monitoring and alerting in Prometheus to monitor the health of your API gateway and APIs.

Metrics

There are different types of metrics in Prometheus. To understand their differences, see metrics types.

The following metrics are exported by the prometheus plugin by default. See get APISIX metrics for an example. Note that some metrics, such as apisix_batch_process_entries, are not readily visible if there are no data.

NameTypeDescription
apisix_bandwidthcounterTotal amount of traffic flowing through APISIX in bytes.
apisix_etcd_modify_indexesgaugeNumber of changes to etcd by APISIX keys.
apisix_batch_process_entriesgaugeNumber of remaining entries in a batch when sending data in batches, such as with http logger, and other logging plugins.
apisix_etcd_reachablegaugeWhether APISIX can reach etcd. A value of 1 represents reachable and 0 represents unreachable.
apisix_http_statuscounterHTTP status codes returned to clients. This is the status the client receives after plugins and proxying, which can differ from the upstream status.
apisix_http_requests_totalgaugeNumber of HTTP requests from clients.
apisix_nginx_http_current_connectionsgaugeNumber of current connections with clients.
apisix_nginx_metric_errors_totalcounterTotal number of nginx-lua-prometheus errors.
apisix_http_latencyhistogramHTTP request latency in milliseconds.
apisix_node_infogaugeInformation about the APISIX node, such as the host name and APISIX version.
apisix_shared_dict_capacity_bytesgaugeThe total capacity of an NGINX shared dictionary.
apisix_shared_dict_free_space_bytesgaugeThe remaining space in an NGINX shared dictionary.
apisix_upstream_statusgaugeHealth check status of upstream nodes, available if health checks are configured on the upstream. A value of 1 represents healthy and 0 represents unhealthy.
apisix_stream_connection_totalcounterTotal number of connections handled per stream route.
apisix_stream_active_connectionsgaugeNumber of active TCP connections and UDP sessions for each stream listening address. Requires APISIX-Runtime. Introduced in API7 Enterprise 3.9.19 on the 3.9 line and 3.10.6 on the 3.10 line, and in APISIX 3.18.0.
apisix_stream_statuscounterNumber of completed stream sessions by termination status, listening address, and upstream node. Introduced in API7 Enterprise 3.9.19 on the 3.9 line and 3.10.6 on the 3.10 line, and in APISIX 3.18.0.
apisix_stream_bandwidthcounterNumber of bytes proxied by the stream subsystem by listening address, direction, and side. Requires APISIX-Runtime. Introduced in API7 Enterprise 3.9.19 on the 3.9 line and 3.10.6 on the 3.10 line, and in APISIX 3.18.0.
apisix_llm_prompt_tokenscounterNumber of prompt tokens. Only exported for AI request types. Introduced in API7 Enterprise 3.9.7 and APISIX 3.17.0.
apisix_llm_completion_tokenscounterNumber of completion tokens. Only exported for AI request types. Introduced in API7 Enterprise 3.9.7 and APISIX 3.17.0.
apisix_llm_latencyhistogramLLM request latency in milliseconds. Only exported for AI request types. Introduced in API7 Enterprise 3.9.7 and APISIX 3.17.0. The type label distinguishes total response latency (total) from time to first token (ttft). Introduced in API7 Enterprise 3.9.14 and 3.10.1, and APISIX 3.18.0. Queries that omit type match both observations; select type="total" to keep the previous total-latency meaning. Each streaming request records one total sample and one ttft sample.
apisix_llm_active_connectionsgaugeNumber of in-flight LLM upstream requests. Only exported for AI request types. Introduced in API7 Enterprise 3.9.7 and APISIX 3.17.0.
apisix_llm_prompt_tokens_disthistogramDistribution of prompt tokens per request. Only exported for AI request types. Introduced in API7 Enterprise 3.9.14 and 3.10.1, and APISIX 3.18.0.
apisix_llm_completion_tokens_disthistogramDistribution of completion tokens per request. Only exported for AI request types. Introduced in API7 Enterprise 3.9.14 and 3.10.1, and APISIX 3.18.0.
apisix_ai_cache_hits_totalcounterNumber of requests served from AI Cache, separated by exact or semantic cache layer. Introduced in API7 Enterprise 3.9.16 and 3.10.3, and APISIX 3.18.0.
apisix_ai_cache_misses_totalcounterNumber of AI Cache lookups that did not return a cached response. Introduced in API7 Enterprise 3.9.16 and 3.10.3, and APISIX 3.18.0.
apisix_ai_cache_bypasses_totalcounterNumber of requests that bypassed AI Cache lookup. Introduced in API7 Enterprise 3.9.16 and 3.10.3, and APISIX 3.18.0.
apisix_ai_cache_embedding_latencyhistogramLatency in milliseconds of embedding-provider calls made by the semantic cache layer. Introduced in API7 Enterprise 3.9.16 and 3.10.3, and APISIX 3.18.0.
note

LLM metrics (apisix_llm_prompt_tokens, apisix_llm_completion_tokens, apisix_llm_latency, apisix_llm_prompt_tokens_dist, and apisix_llm_completion_tokens_dist) are only exported when the request is processed by an AI plugin (such as AI Proxy). Routes without AI plugins do not produce these metrics. apisix_llm_active_connections is managed directly by AI plugins and is also only present for AI-enabled routes.

The gauge increases when an LLM upstream attempt starts and decreases once in the request log phase. For a single attempt, it tracks active LLM upstream requests. With ai-proxy-multi fallback retries, each retry increments a new per-instance series, and the request is decremented only once using the final instance labels. A failed instance series can therefore stay above the true active count until the metric expires or the storage is reset.

To reduce high-cardinality labels on LLM metrics, use disabled_labels in plugin metadata to selectively disable labels such as consumer or node.

The prompt- and completion-token histograms use configurable buckets. See the static plugin attributes for their defaults and configuration.

Labels

Labels are attributes of metrics that are used to differentiate metrics.

For example, the apisix_http_status metric can be labeled with route information to identify which route the HTTP status originates from.

The following are labels for a non-exhaustive list of APISIX metrics and their descriptions.

Labels for apisix_http_status

The following labels are used to differentiate apisix_http_status metrics.

NameDescription
codeHTTP response code returned to the client after plugins and proxying.
routeID of the route that the HTTP status originates from when prefer_name is false (default), and name of the route when prefer_name to true. Default to an empty string if a request does not match any route.
route_idAvailable only in API7 Enterprise. ID of the route that the HTTP status originates from regardless of the prefer_name setting.
matched_uriURI of the route that matches the request. Default to an empty string if a request does not match any route.
matched_hostHost of the route that matches the request. Default to an empty string if a request does not match any route, or host is not configured on the route.
serviceID of the service that the HTTP status originates from when prefer_name is false (default), and name of the service when prefer_name to true. Default to the configured value of host on the route if the matched route does not belong to any service.
service_idAvailable only in API7 Enterprise. ID of the service that the HTTP status originates from regardless of the prefer_name setting.
consumerName of the consumer associated with a request. Default to an empty string if no consumer is associated with the request.
nodeIP address of the upstream node. For AI routes, this is the LLM instance name from ai-proxy or ai-proxy-multi.
gateway_group_idID of the gateway group that the HTTP status originates from. Available only in API7 Enterprise.
instance_idID of the gateway instance that the HTTP status originates from. Available only in API7 Enterprise.
api_product_idProduct ID that the HTTP status originates from. Available only in API7 Enterprise.
request_typeRequest type associated with the HTTP status.
request_llm_modelModel name sent in the client request. Empty for ordinary HTTP traffic.
llm_modelModel the gateway actually targets. If the AI instance configures a model, that value is used; otherwise the client's requested model is used. Empty for ordinary HTTP traffic.
response_sourceSource of the HTTP response: apisix (generated by APISIX, such as plugin rejections or route-not-found), nginx (NGINX proxy errors such as connection refused or upstream timeout), or upstream (real response from the upstream service). Introduced in API7 Enterprise 3.9.10 and APISIX 3.17.0.
mcp_request_typeMCP request type, such as tools/list or tools/call. Empty for non-MCP requests. Introduced in API7 Enterprise 3.9.14.
mcp_tool_nameMCP tool name for tools/call requests. Empty for other requests. Introduced in API7 Enterprise 3.9.14.

The response_source label is mandatory on apisix_http_status and can add up to three series per existing status-label combination. Update PromQL joins, recording rules, alerts, and dashboards that match the complete label set, and review the resulting cardinality before rollout.

Labels for apisix_bandwidth

The following labels are used to differentiate apisix_bandwidth metrics.

NameDescription
typeType of traffic, egress or ingress.
routeID of the route that bandwidth corresponds to when prefer_name is false (default), and name of the route when prefer_name to true. Default to an empty string if a request does not match any route.
route_idAvailable only in API7 Enterprise. ID of the route that bandwidth corresponds to regardless of the prefer_name setting.
serviceID of the service that bandwidth corresponds to when prefer_name is false (default), and name of the service when prefer_name to true. Default to the configured value of host on the route if the matched route does not belong to any service.
service_idAvailable only in API7 Enterprise. ID of the service that bandwidth corresponds to regardless of the prefer_name setting.
consumerName of the consumer associated with a request. Default to an empty string if no consumer is associated with the request.
nodeIP address of the upstream node. For AI routes, this is the LLM instance name from ai-proxy or ai-proxy-multi.
gateway_group_idAvailable only in API7 Enterprise. ID of the gateway group that bandwidth corresponds to.
instance_idAvailable only in API7 Enterprise. ID of the gateway instance that bandwidth corresponds to.
api_product_idAvailable only in API7 Enterprise. Product ID that bandwidth corresponds to.
request_typeRequest type that bandwidth corresponds to.
request_llm_modelModel name sent in the client request. Empty for ordinary HTTP traffic.
llm_modelModel the gateway actually targets. If the AI instance configures a model, that value is used; otherwise the client's requested model is used. Empty for ordinary HTTP traffic.
mcp_request_typeMCP request type, such as tools/list or tools/call. Empty for non-MCP requests. Introduced in API7 Enterprise 3.9.14 and 3.10.1.
mcp_tool_nameMCP tool name for tools/call requests. Empty for other requests. Introduced in API7 Enterprise 3.9.14 and 3.10.1.

Labels for apisix_http_latency

The following labels are used to differentiate apisix_http_latency metrics.

NameDescription
typeType of latencies. See latency types for details.
routeID of the route that latencies correspond to when prefer_name is false (default), and name of the route when prefer_name to true. Default to an empty string if a request does not match any route.
route_idAvailable only in API7 Enterprise. ID of the route that latencies correspond to regardless of the prefer_name setting.
serviceID of the service that latencies correspond to when prefer_name is false (default), and name of the service when prefer_name to true. Default to the configured value of host on the route if the matched route does not belong to any service.
service_idAvailable only in API7 Enterprise. ID of the service that latencies correspond to regardless of the prefer_name setting.
consumerName of the consumer associated with latencies. Default to an empty string if no consumer is associated with the request.
nodeIP address of the upstream node associated with latencies. For AI routes, this is the LLM instance name from ai-proxy or ai-proxy-multi.
gateway_group_idAvailable only in API7 Enterprise. ID of the gateway group that latencies correspond to.
instance_idAvailable only in API7 Enterprise. ID of the gateway instance that latencies correspond to.
api_product_idAvailable only in API7 Enterprise. Product ID that latencies correspond to.
request_typeRequest type that latencies correspond to.
request_llm_modelModel name sent in the client request. Empty for ordinary HTTP traffic.
llm_modelModel the gateway actually targets. If the AI instance configures a model, that value is used; otherwise the client's requested model is used. Empty for ordinary HTTP traffic.
mcp_request_typeMCP request type, such as tools/list or tools/call. Empty for non-MCP requests. Introduced in API7 Enterprise 3.9.14 and 3.10.1.
mcp_tool_nameMCP tool name for tools/call requests. Empty for other requests. Introduced in API7 Enterprise 3.9.14 and 3.10.1.

Latency Types

apisix_http_latency can be labeled with one of the three types:

  • request represents the time elapsed between the first byte was read from the client and the log write after the last byte was sent to the client.

  • upstream represents the time elapsed waiting on responses from the upstream service.

  • apisix represents the difference between the request latency and upstream latency.

In other words, the APISIX latency is not only attributed to the Lua processing. It should be understood as follows:

APISIX latency
= downstream request time - upstream response time
= downstream traffic latency + NGINX latency

Labels for apisix_upstream_status

The following labels are used to differentiate apisix_upstream_status metrics.

NameDescription
nameResource ID corresponding to the upstream configured with health checks, such as /apisix/routes/1 and /apisix/upstreams/1.
ipIP address of the upstream node.
portPort number of the node.

Labels for Stream Metrics

The apisix_stream_active_connections metric uses the stream listening address as a label:

NameDescription
listen_addrAddress on which APISIX accepted the TCP connection or UDP session, such as 0.0.0.0:9100.

The apisix_stream_status counter records each stream session when it ends:

NameDescription
codeHow the session ended. 200 is a normal close. 400 is a client-side problem, such as a reset or invalid data from the client. 403 is an access-rule rejection. 500 is an internal error. 502 is an upstream or transport problem, such as a connect failure, reset, or idle timeout. 503 is a connection-limit rejection.
listen_addrAddress on which APISIX accepted the session.
nodeSelected upstream address in IP:port form. Empty when the session ends before APISIX selects an upstream.

NGINX reports Stream $status as 200 for some failures that happen after the upstream connection is established. This metric uses the session termination reason to distinguish a clean close from a later timeout or reset. 200 is also used for worker shutdown and when no recognized reason is recorded.

The apisix_stream_bandwidth counter updates while a session remains open:

NameDescription
listen_addrAddress on which APISIX accepted the session.
typeTraffic direction: ingress or egress.
sideConnection side: downstream or upstream.

Labels for apisix_llm_latency

The following labels are used to differentiate apisix_llm_latency metrics.

NameDescription
typeLLM latency type: total for full response latency, or ttft for time to first token on streaming requests. Introduced in API7 Enterprise 3.9.14 and 3.10.1, and APISIX 3.18.0. Dashboards, alerts, and recording rules that previously treated every apisix_llm_latency sample as total latency must add type="total".
routeID of the route that the HTTP status originates from when prefer_name is false (default), and name of the route when prefer_name to true. Default to an empty string if a request does not match any route.
route_idID of the route that the HTTP status originates from regardless of the prefer_name setting.
serviceID of the service that the HTTP status originates from when prefer_name is false (default), and name of the service when prefer_name to true. Default to the configured value of host on the route if the matched route does not belong to any service.
service_idID of the service that the HTTP status originates from regardless of the prefer_name setting.
consumerName of the consumer associated with a request. Default to an empty string if no consumer is associated with the request.
nodeName of the selected LLM instance from ai-proxy or ai-proxy-multi, not the upstream IP.
gateway_group_idID of the gateway group that the HTTP status originates from.
instance_idID of the gateway instance that the HTTP status originates from.
api_product_idProduct ID that the HTTP status originates from.
request_typeRequest type that the HTTP status originates from.
request_llm_modelModel name sent in the client request. Introduced in API7 Enterprise 3.9.7 and APISIX 3.17.0.
llm_modelModel the gateway actually targets. If the AI instance configures a model, that value is used; otherwise the client's requested model is used.

Labels for Other LLM Metrics

The following labels are used to differentiate apisix_llm_prompt_tokens, apisix_llm_completion_tokens, apisix_llm_active_connections, apisix_llm_prompt_tokens_dist, and apisix_llm_completion_tokens_dist metrics.

NameDescription
routeID of the route that the HTTP status originates from when prefer_name is false (default), and name of the route when prefer_name to true. Default to an empty string if a request does not match any route.
route_idID of the route that the HTTP status originates from regardless of the prefer_name setting.
matched_uriURI of the route that matches the request. Default to an empty string if a request does not match any route.
matched_hostHost of the route that matches the request. Default to an empty string if a request does not match any route, or host is not configured on the route.
serviceID of the service that the HTTP status originates from when prefer_name is false (default), and name of the service when prefer_name to true. Default to the configured value of host on the route if the matched route does not belong to any service.
service_idID of the service that the HTTP status originates from regardless of the prefer_name setting.
consumerName of the consumer associated with a request. Default to an empty string if no consumer is associated with the request.
nodeName of the selected LLM instance from ai-proxy or ai-proxy-multi, not the upstream IP.
gateway_group_idID of the gateway group that the HTTP status originates from.
instance_idID of the gateway instance that the HTTP status originates from.
api_product_idProduct ID that the HTTP status originates from.
request_typeRequest type that the HTTP status originates from.
request_llm_modelModel name sent in the client request. Introduced in API7 Enterprise 3.9.7 and APISIX 3.17.0.
llm_modelModel the gateway actually targets. If the AI instance configures a model, that value is used; otherwise the client's requested model is used.

The prompt- and completion-token counters and distribution histograms use different label sets by product. APISIX exports route_id, service_id, consumer, node, request_type, request_llm_model, and llm_model. API7 Enterprise additionally exports route, matched_uri, matched_host, and service, as well as its gateway-instance and API-product labels.

The request_llm_model and llm_model values originate from client and provider data. Their values are limited to 128 bytes. Introduced in API7 Enterprise 3.9.14 and 3.10.1, and APISIX 3.18.0. Disable the labels when per-model series are not required.

Labels for AI Cache Metrics

The four AI Cache metrics share the following labels. Only apisix_ai_cache_hits_total includes layer.

NameDescription
layerCache layer that served a hit: exact or semantic. This structural label cannot be disabled.
routeRoute name, or an empty string if the route has no name.
route_idRoute ID.
serviceService name, or an empty string if the route does not reference a service.
service_idService ID, or an empty string if the route does not reference a service.
consumerConsumer name, or an empty string when the request has no Consumer.
nodeName of the selected LLM instance from ai-proxy or ai-proxy-multi, not the upstream IP.
request_typeRequest type, such as ai_chat or ai_stream.
request_llm_modelModel name sent in the client request.
llm_modelModel the gateway actually targets. If the AI instance configures a model, that value is used; otherwise the client's requested model is used. Empty on cache hits, which are served without reaching the LLM.

API7 Enterprise also exports matched_uri, matched_host, and its gateway-instance and API-product labels for these metrics.

Examples

The examples below demonstrate how you can work with the prometheus plugin for different scenarios.

Get APISIX Metrics

The following example demonstrates how you can get metrics from APISIX.

The default Prometheus metrics endpoint and other Prometheus related configurations can be found in the static configuration. If you would like to customize these configurations, see configuration files.

If you deploy the gateway in a containerized environment and would like to access the Prometheus metrics endpoint externally, update the Prometheus export address in the gateway static configuration:

Add or update this section in the gateway configuration file:

config.yaml
plugin_attr:
prometheus:
export_addr:
ip: 0.0.0.0

Reload the gateway for changes to take effect.

Send a request to the APISIX Prometheus metrics endpoint:

curl "http://127.0.0.1:9091/apisix/prometheus/metrics"

You should see an output similar to the following:

# HELP apisix_bandwidth Total bandwidth in bytes consumed per service in Apisix
# TYPE apisix_bandwidth counter
apisix_bandwidth{type="egress",route="",service="",consumer="",node=""} 8417
apisix_bandwidth{type="egress",route="1",service="",consumer="",node="127.0.0.1"} 1420
apisix_bandwidth{type="egress",route="2",service="",consumer="",node="127.0.0.1"} 1420
apisix_bandwidth{type="ingress",route="",service="",consumer="",node=""} 189
apisix_bandwidth{type="ingress",route="1",service="",consumer="",node="127.0.0.1"} 332
apisix_bandwidth{type="ingress",route="2",service="",consumer="",node="127.0.0.1"} 332
# HELP apisix_etcd_modify_indexes Etcd modify index for APISIX keys
# TYPE apisix_etcd_modify_indexes gauge
apisix_etcd_modify_indexes{key="consumers"} 0
apisix_etcd_modify_indexes{key="global_rules"} 0
...

Reduce Metric Cardinality by Disabling Labels

Plugin metadata can collapse selected label values to an empty string, reducing the number of time series while preserving the metric's label schema. APISIX and API7 Enterprise use different metadata keys for the HTTP status and latency metrics.

The accepted labels also differ where API7 Enterprise exports additional dimensions:

Metric metadata keyAPISIX labels that can be disabledAPI7 Enterprise differences
http_statusroute, matched_uri, matched_host, service, consumer, node, request_type, request_llm_model, llm_model, response_sourceUse the key status. Adds route_id, service_id, mcp_request_type, and mcp_tool_name, but does not allow response_source to be disabled.
http_latencyroute, service, consumer, node, request_type, request_llm_model, llm_modelUse the key latency. Adds route_id, service_id, mcp_request_type, and mcp_tool_name.
bandwidthroute, service, consumer, node, request_type, request_llm_model, llm_modelAdds route_id, service_id, mcp_request_type, and mcp_tool_name.
llm_latencyroute_id, service_id, consumer, node, request_type, request_llm_model, llm_modelAlso allows route and service.
llm_prompt_tokens, llm_completion_tokens, llm_prompt_tokens_dist, llm_completion_tokens_distroute_id, service_id, consumer, node, request_type, request_llm_model, llm_modelAlso allows route, matched_uri, matched_host, and service.
llm_active_connectionsroute, route_id, matched_uri, matched_host, service, service_id, consumer, node, request_type, request_llm_model, llm_modelSame labels.
ai_cache_hits_total, ai_cache_misses_total, ai_cache_bypasses_total, ai_cache_embedding_latencyroute, route_id, service, service_id, consumer, node, request_type, request_llm_model, llm_modelAlso allows matched_uri and matched_host.

Structural labels are excluded from this table because they cannot be disabled.

In API7 Enterprise, the stream_status metadata key disables the node label on apisix_stream_status. Its code and listen_addr labels are structural. Introduced in API7 Enterprise 3.9.19 on the 3.9 line and 3.10.6 on the 3.10 line.

In APISIX, disable the node label on HTTP status and latency metrics:

curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/prometheus" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"disabled_labels": {
"http_status": ["node"],
"http_latency": ["node"]
}
}'

For API7 Enterprise, use status and latency instead:

{
"disabled_labels": {
"status": ["node"],
"latency": ["node"]
}
}

Send a request through a route with the plugin enabled, then fetch the metrics endpoint. The affected series should keep the node label with an empty value:

apisix_http_status{code="200",route="1",matched_uri="/get",matched_host="",service="",consumer="",node="",request_type="traditional_http",request_llm_model="",llm_model="",response_source="upstream"} 1

The schema rejects structural labels that distinguish different measurements, including code for HTTP status, type for HTTP latency, bandwidth, and LLM latency, and layer for AI Cache hits. The exact optional-label set differs between APISIX and API7 Enterprise; use the plugin metadata reference for the gateway you are configuring.

Expose APISIX Metrics on Public API Endpoint

The following example demonstrates how you can disable the Prometheus export server that, by default, exposes an endpoint on port 9091, and expose APISIX Prometheus metrics on a new public API endpoint on port 9080, which APISIX uses to listen to other client requests.

caution

If a large quantity of metrics are being collected, the plugin could take up a significant amount of CPU resources for metric computations and negatively impact the processing of regular requests.

To address this issue, APISIX uses privileged agent and offloads the metric computations to a separate process. This optimization applies automatically if you use the metric endpoint configured in the configuration files, as demonstrated above. If you expose the metric endpoint with the public-api plugin, you will not benefit from this optimization.

To expose metrics through public-api, first disable the default Prometheus export server:

Add or update this section in the gateway configuration file:

config.yaml
plugin_attr:
prometheus:
enable_export_server: false

Reload the gateway for changes to take effect.

Next, create a route with public-api plugin and expose a public API endpoint for APISIX metrics:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "prometheus-metrics",
"uri": "/prometheus_metrics",
"plugins": {
"public-api": {
"uri": "/apisix/prometheus/metrics"
}
}
}'

Send a request to the new metrics endpoint to verify:

curl "http://127.0.0.1:9080/prometheus_metrics"

You should see an output similar to the following:

# HELP apisix_http_requests_total The total number of client requests since APISIX started
# TYPE apisix_http_requests_total gauge
apisix_http_requests_total 1
# HELP apisix_nginx_http_current_connections Number of HTTP connections
# TYPE apisix_nginx_http_current_connections gauge
apisix_nginx_http_current_connections{state="accepted"} 1
apisix_nginx_http_current_connections{state="active"} 1
apisix_nginx_http_current_connections{state="handled"} 1
apisix_nginx_http_current_connections{state="reading"} 0
apisix_nginx_http_current_connections{state="waiting"} 0
apisix_nginx_http_current_connections{state="writing"} 1
...

Integrate APISIX with Prometheus and Grafana

To learn about how to collect APISIX metrics with Prometheus and visualize them in Grafana, see how-to guide.

Monitor Upstream Health Statuses

The following example demonstrates how to monitor the health status of upstream nodes.

Create a route with the prometheus plugin and configure upstream active health checks:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "prometheus-route",
"uri": "/get",
"plugins": {
"prometheus": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1,
"127.0.0.1:20001": 1
},
"checks": {
"active": {
"timeout": 5,
"http_path": "/status",
"healthy": {
"interval": 2,
"successes": 1
},
"unhealthy": {
"interval": 1,
"http_failures": 2
}
},
"passive": {
"healthy": {
"http_statuses": [200, 201],
"successes": 3
},
"unhealthy": {
"http_statuses": [500],
"http_failures": 3,
"tcp_failures": 3
}
}
}
}
}'

Send a request to the APISIX Prometheus metrics endpoint:

curl "http://127.0.0.1:9091/apisix/prometheus/metrics"

You should see an output similar to the following:

# HELP apisix_upstream_status upstream status from health check
# TYPE apisix_upstream_status gauge
apisix_upstream_status{name="/upstreams/<id>",ip="<healthy-node-ip>",port="80"} 1
apisix_upstream_status{name="/upstreams/<id>",ip="<unhealthy-node-ip>",port="80"} 0

In that sample output, one upstream node is healthy and another upstream node is unhealthy.

To learn more about how to configure active and passive health checks, see health checks.

Add Extra Labels for Metrics

The following example demonstrates how to add additional labels to metrics and use built-in variables in label values.

Currently, extra labels are supported on:

  • apisix_http_status
  • apisix_http_latency
  • apisix_bandwidth
  • all apisix_llm_* metrics listed above
  • all four apisix_ai_cache_* metrics

Both APISIX and API7 Gateway apply extra labels the same way.

Add extra labels to the Prometheus static configuration:

Add or update this section in the gateway configuration file:

config.yaml
plugin_attr:
prometheus: # Plugin: prometheus
metrics: # Create extra labels from built-in variables.
http_status:
extra_labels: # Set the extra labels for http_status metrics.
- upstream_addr: $upstream_addr # Add an extra upstream_addr label with value being the NGINX variable $upstream_addr.
- route_name: $route_name # Add an extra route_name label with value being the APISIX variable $route_name.

Reload the gateway for changes to take effect.

Note that if you define a variable in the label value but it does not correspond to any existing built-in variables, the label value will default to an empty string.

Create a route with the prometheus plugin:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "prometheus-route",
"uri": "/get",
"name": "extra-label",
"plugins": {
"prometheus": {}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
}
}
}'

Send a request to the route to verify:

curl -i "http://127.0.0.1:9080/get"

You should see an HTTP/1.1 200 OK response.

Send a request to the APISIX Prometheus metrics endpoint:

curl "http://127.0.0.1:9091/apisix/prometheus/metrics"

You should see an output similar to the following:

# HELP apisix_http_status HTTP status codes per service in APISIX
# TYPE apisix_http_status counter
apisix_http_status{code="200",route="1",matched_uri="/get",matched_host="",service="",consumer="",node="54.237.103.220",request_type="traditional_http",request_llm_model="",llm_model="",response_source="upstream",upstream_addr="54.237.103.220:80",route_name="extra-label"} 1

Monitor TCP/UDP Traffic with Prometheus

The following example demonstrates how to collect TCP/UDP traffic metrics in APISIX.

To collect TCP/UDP metrics, enable stream proxy and add prometheus to the existing stream plugin list. Preserve the other stream plugins used by the deployment; the host/Docker example below shows the minimal list for this walkthrough.

Add or update this section in the gateway configuration file:

config.yaml
apisix:
proxy_mode: http&stream # Enable both L4 & L7 proxies
stream_proxy: # Configure L4 proxy
tcp:
- 9100 # Set TCP proxy listening port
udp:
- 9200 # Set UDP proxy listening port

stream_plugins:
- prometheus # Enable prometheus for stream proxy

Reload the gateway for changes to take effect.

Create a stream route with the prometheus plugin:

curl "http://127.0.0.1:9180/apisix/admin/stream_routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "prometheus-route",
"plugins": {
"prometheus":{}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

Send a request to the stream route to verify:

curl -i "http://127.0.0.1:9100"

You should see an HTTP/1.1 200 OK response.

Send a request to the APISIX Prometheus metrics endpoint:

curl "http://127.0.0.1:9091/apisix/prometheus/metrics"

You should see an output similar to the following:

# HELP apisix_stream_connection_total Total number of connections handled per stream route in APISIX
# TYPE apisix_stream_connection_total counter
apisix_stream_connection_total{route="prometheus-route"} 1

APISIX also exports the termination status. When APISIX-Runtime provides the stream-metrics module, the scrape includes active connections and bandwidth:

# HELP apisix_stream_active_connections Number of stream sessions currently being proxied per listening address
# TYPE apisix_stream_active_connections gauge
apisix_stream_active_connections{listen_addr="0.0.0.0:9100"} 0
# HELP apisix_stream_status Stream sessions per termination status in APISIX
# TYPE apisix_stream_status counter
apisix_stream_status{code="200",listen_addr="0.0.0.0:9100",node="54.237.103.220:80"} 1
# HELP apisix_stream_bandwidth Total bandwidth in bytes proxied by the stream subsystem in APISIX
# TYPE apisix_stream_bandwidth counter
apisix_stream_bandwidth{listen_addr="0.0.0.0:9100",type="ingress",side="downstream"} 78
apisix_stream_bandwidth{listen_addr="0.0.0.0:9100",type="egress",side="downstream"} 219
apisix_stream_bandwidth{listen_addr="0.0.0.0:9100",type="egress",side="upstream"} 78
apisix_stream_bandwidth{listen_addr="0.0.0.0:9100",type="ingress",side="upstream"} 219

The exact upstream address and byte counts depend on the request. The active-connections gauge is 0 above because the request completed before the scrape; scrape while a connection remains open to observe a positive value.

The active-connection and bandwidth metrics use a shared memory zone that defaults to 1m. Increase the zone when a gateway exposes many stream listening addresses:

config.yaml
nginx_config:
stream:
metrics_zone_size: 2m

Reload APISIX after changing the zone size. On a runtime without the stream-metrics module, APISIX continues to export the connection-total and status metrics but does not publish active-connection or bandwidth metrics.