Skip to content

Apache HTTP Server OpenTelemetry Dashboards

Dashboards for monitoring Apache HTTP Server using OpenTelemetry metrics collected by the Apache receiver.

Overview

These dashboards provide comprehensive monitoring for Apache HTTP Server 2.4.13+ installations, displaying metrics collected via the server-status?auto endpoint by the OpenTelemetry Collector's Apache receiver.

Dashboards

Dashboard File Description
Overview 01-apache-overview.yaml Apache HTTP Server performance and health metrics

Dashboard Definitions

Overview (01-apache-overview.yaml)
---
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License 2.0;
# you may not use this file except in compliance with the Elastic License 2.0.
# See ../../licenses/ELASTIC-LICENSE-2.0.txt for the full license text.
#
# Dashboard for Apache HTTP Server metrics collected via OpenTelemetry apachereceiver.
# Uses ES|QL with TS command for time-series optimization.
# Source: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/apachereceiver
#
# Apache OTel Receiver Metrics Reference:
# - apache.uptime (counter): Server uptime in seconds
# - apache.requests (counter): Total requests serviced
# - apache.traffic (counter): Total traffic in bytes
# - apache.cpu.time (counter): CPU time in jiffies
# - apache.request.time (counter): Request processing time in ms
# - apache.cpu.load (gauge): Current CPU load percentage
# - apache.load.1, apache.load.5, apache.load.15 (gauge): Load averages
# - apache.current_connections (gauge): Current connections
# - apache.connections.async (gauge): Async connections by state
# - apache.workers (gauge): Worker counts by state (busy/idle)
# - apache.scoreboard (gauge): Detailed worker status
#
# Attributes:
# - attributes.state: Used by apache.workers (busy/idle) and apache.scoreboard (various states)
# - attributes.connection_state: Used by apache.connections.async (writing/keepalive/closing)
#
# Resource Attributes:
# - resource.attributes.apache.server.name
# - resource.attributes.apache.server.port
dashboards:
  - id: otel-apache-overview
    name: '[OTel] Apache HTTP Server - Overview'
    description: Overview of Apache HTTP Server metrics from OpenTelemetry apachereceiver
    controls:
      - type: options
        label: Server Name
        data_view: metrics-*
        field: resource.attributes.apache.server.name
      - type: options
        label: Server Port
        data_view: metrics-*
        field: resource.attributes.apache.server.port
    filters:
      - field: data_stream.dataset
        equals: apachereceiver.otel
    panels:
      # Overview Metrics Row
      - title: Request Rate
        hide_title: true
        size: {w: 12, h: 4}
        esql:
          type: metric
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.requests IS NOT NULL
            - STATS requests_rate = SUM(RATE(apache.requests))
          primary:
            field: requests_rate
            label: Requests/sec
            format:
              type: number
      - title: Traffic Rate
        hide_title: true
        size: {w: 12, h: 4}
        esql:
          type: metric
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.traffic IS NOT NULL
            - STATS traffic_rate = SUM(RATE(apache.traffic))
          primary:
            field: traffic_rate
            label: Traffic/sec
            format:
              type: bytes
      - title: Active Connections
        hide_title: true
        size: {w: 12, h: 4}
        esql:
          type: metric
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.current_connections IS NOT NULL
            - STATS connections = MAX(LAST_OVER_TIME(apache.current_connections))
          primary:
            field: connections
            label: Connections
            format:
              type: number
              pattern: 0,0
              decimals: 0
      - title: CPU Load
        hide_title: true
        size: {w: 12, h: 4}
        esql:
          type: metric
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.cpu.load IS NOT NULL
            - STATS cpu_load = AVG(AVG_OVER_TIME(apache.cpu.load))
          primary:
            field: cpu_load
            label: CPU Load
            format:
              type: percent

      # Time Series Charts
      - title: Request Rate Over Time
        size: {w: 24, h: 10}
        esql:
          type: line
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.requests IS NOT NULL
            - STATS requests_rate = SUM(RATE(apache.requests)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), resource.attributes.apache.server.name
            - SORT time_bucket ASC
          legend:
            visible: show
            position: right
          dimension:
            field: time_bucket
            label: Time
            data_type: date
          metrics:
            - field: requests_rate
              label: Requests/sec
              format:
                type: number
          breakdown:
            field: resource.attributes.apache.server.name
      - title: Traffic Rate Over Time
        size: {w: 24, h: 10}
        esql:
          type: line
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.traffic IS NOT NULL
            - STATS traffic_rate = SUM(RATE(apache.traffic)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), resource.attributes.apache.server.name
            - SORT time_bucket ASC
          legend:
            visible: show
            position: right
          dimension:
            field: time_bucket
            label: Time
            data_type: date
          metrics:
            - field: traffic_rate
              label: Traffic/sec
              format:
                type: bytes
          breakdown:
            field: resource.attributes.apache.server.name
      - title: CPU Time Rate
        size: {w: 24, h: 10}
        esql:
          type: area
          mode: stacked
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.cpu.time IS NOT NULL
            - STATS cpu_time_rate = SUM(RATE(apache.cpu.time)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), resource.attributes.apache.server.name
            - SORT time_bucket ASC
          legend:
            visible: show
            position: right
          dimension:
            field: time_bucket
            label: Time
            data_type: date
          metrics:
            - field: cpu_time_rate
              label: CPU Time/sec
              format:
                type: number
          breakdown:
            field: resource.attributes.apache.server.name
      - title: Request Processing Time Rate
        size: {w: 24, h: 10}
        esql:
          type: area
          mode: stacked
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.request.time IS NOT NULL
            - STATS request_time_rate = SUM(RATE(apache.request.time)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), resource.attributes.apache.server.name
            - SORT time_bucket ASC
          legend:
            visible: show
            position: right
          dimension:
            field: time_bucket
            label: Time
            data_type: date
          metrics:
            - field: request_time_rate
              label: Request Time/sec
              format:
                type: number
                suffix: ms
          breakdown:
            field: resource.attributes.apache.server.name

      # Server Load and Connection Metrics
      - title: Server Load Average
        size: {w: 16, h: 10}
        esql:
          type: line
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE `apache.load.1` IS NOT NULL
            - STATS load_1m = AVG(AVG_OVER_TIME(`apache.load.1`)), load_5m = AVG(AVG_OVER_TIME(`apache.load.5`)), load_15m = AVG(AVG_OVER_TIME(`apache.load.15`))
              BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), resource.attributes.apache.server.name
            - SORT time_bucket ASC
          legend:
            visible: show
            position: bottom
          dimension:
            field: time_bucket
            label: Time
            data_type: date
          metrics:
            - field: load_1m
              label: 1-min Load
              format:
                type: percent
            - field: load_5m
              label: 5-min Load
              format:
                type: percent
            - field: load_15m
              label: 15-min Load
              format:
                type: percent
          breakdown:
            field: resource.attributes.apache.server.name
      - title: Connection Metrics
        size: {w: 16, h: 10}
        esql:
          type: line
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.current_connections IS NOT NULL
            - STATS connections = AVG(AVG_OVER_TIME(apache.current_connections)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), resource.attributes.apache.server.name
            - SORT time_bucket ASC
          legend:
            visible: show
            position: bottom
          dimension:
            field: time_bucket
            label: Time
            data_type: date
          metrics:
            - field: connections
              label: Current Connections
              format:
                type: number
                pattern: 0,0
          breakdown:
            field: resource.attributes.apache.server.name
      - title: CPU Load Over Time
        size: {w: 16, h: 10}
        esql:
          type: line
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.cpu.load IS NOT NULL
            - STATS cpu_load = AVG(AVG_OVER_TIME(apache.cpu.load)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), resource.attributes.apache.server.name
            - SORT time_bucket ASC
          legend:
            visible: show
            position: bottom
          dimension:
            field: time_bucket
            label: Time
            data_type: date
          metrics:
            - field: cpu_load
              label: CPU Load
              format:
                type: percent
          breakdown:
            field: resource.attributes.apache.server.name

      # Async Connections and Workers
      - title: Async Connections by State
        size: {w: 24, h: 12}
        esql:
          type: area
          mode: stacked
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.connections.async IS NOT NULL
            - STATS connections = AVG(AVG_OVER_TIME(apache.connections.async)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), attributes.connection_state
            - SORT time_bucket ASC
          legend:
            visible: show
            position: right
          dimension:
            field: time_bucket
            label: Time
            data_type: date
          metrics:
            - field: connections
              label: Async Connections
              format:
                type: number
                pattern: 0,0
          breakdown:
            field: attributes.connection_state
      - title: Worker Distribution
        size: {w: 24, h: 12}
        esql:
          type: pie
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.workers IS NOT NULL
            - STATS workers = AVG(AVG_OVER_TIME(apache.workers)) BY state = attributes.state
            - SORT workers DESC
            - LIMIT 10
          metrics:
            - field: workers
              label: Workers
              format:
                type: number
                pattern: 0,0
          breakdowns:
            - field: state
              label: Worker State
          appearance:
            donut: medium

      # Scoreboard and Workers Over Time
      - title: Scoreboard Status
        size: {w: 48, h: 12}
        esql:
          type: bar
          mode: stacked
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.scoreboard IS NOT NULL
            - STATS scoreboard = AVG(AVG_OVER_TIME(apache.scoreboard)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), attributes.state
            - SORT time_bucket ASC
          legend:
            visible: show
            position: right
          dimension:
            field: time_bucket
            label: Time
            data_type: date
          metrics:
            - field: scoreboard
              label: Scoreboard
              format:
                type: number
                pattern: 0,0
          breakdown:
            field: attributes.state
      - title: Workers by State Over Time
        size: {w: 48, h: 12}
        esql:
          type: area
          mode: stacked
          query:
            - TS metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE apache.workers IS NOT NULL
            - STATS workers = AVG(AVG_OVER_TIME(apache.workers)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), attributes.state
            - SORT time_bucket ASC
          legend:
            visible: show
            position: right
          dimension:
            field: time_bucket
            label: Time
            data_type: date
          metrics:
            - field: workers
              label: Workers
              format:
                type: number
                pattern: 0,0
          breakdown:
            field: attributes.state

      # Server Performance Summary
      - title: Server Performance Summary
        size: {w: 48, h: 20}
        description: Shows current state metrics per server. For request and traffic rates, see the time-series charts above.
        esql:
          type: datatable
          query:
            - FROM metrics-*
            - WHERE data_stream.dataset == "apachereceiver.otel"
            - WHERE resource.attributes.apache.server.name IS NOT NULL
            - STATS connections = ROUND(MAX(apache.current_connections), 0), cpu_load_pct = ROUND(AVG(apache.cpu.load) * 100, 1), load_1m = ROUND(AVG(`apache.load.1`),
              2), busy_workers = ROUND(MAX(apache.workers), 0) BY server_name = resource.attributes.apache.server.name, server_port = resource.attributes.apache.server.port
            - KEEP server_name, server_port, connections, cpu_load_pct, load_1m, busy_workers
            - SORT server_name ASC
            - LIMIT 100
          breakdowns:
            - field: server_name
              label: Server Name
            - field: server_port
              label: Port
            - field: connections
              label: Connections
            - field: cpu_load_pct
              label: CPU Load %
            - field: load_1m
              label: 1-min Load
            - field: busy_workers
              label: Busy Workers

Prerequisites

  • Apache HTTP Server: Version 2.4.13 or later with mod_status enabled
  • OpenTelemetry Collector: Collector with Apache receiver configured
  • Kibana: Version 9.2 or later (dashboards use ES|QL TS command)

Data Requirements

  • Data stream dataset: apachereceiver.otel
  • Data view: metrics-*

OpenTelemetry Collector Configuration

receivers:
  apache:
    endpoint: "http://localhost/server-status?auto"
    collection_interval: 10s

processors:
  resource:
    attributes:
      - key: server.address
        from_attribute: apache.server.name
        action: upsert
      - key: server.port
        from_attribute: apache.server.port
        action: upsert

exporters:
  elasticsearch:
    endpoints: ["https://your-elasticsearch-instance:9200"]
    # Additional Elasticsearch configuration...

service:
  pipelines:
    metrics:
      receivers: [apache]
      processors: [resource]
      exporters: [elasticsearch]

Metrics Reference

All metrics are enabled by default.

Metric Type Unit Description Attributes
apache.requests Sum {requests} Number of requests serviced
apache.traffic Sum By Total HTTP server traffic
apache.current_connections Sum {connections} Number of active connections currently attached
apache.connections.async Gauge {connections} Number of connections in different asynchronous states connection_state
apache.uptime Sum s Time the server has been running
apache.cpu.load Gauge % Current processor load
apache.cpu.time Sum {jiff} Jiffs used by processes of given category level, mode
apache.request.time Sum ms Total time spent on handling requests
apache.load.1 Gauge % Average server load over last 1 minute
apache.load.5 Gauge % Average server load over last 5 minutes
apache.load.15 Gauge % Average server load over last 15 minutes
apache.workers Sum {workers} Number of workers currently attached state
apache.scoreboard Sum {workers} Count of workers decoded from Apache's scoreboard state

Metric Attributes

Attribute Values Description
connection_state writing, keepalive, closing Async connection state
level self, children CPU level
mode system, user CPU mode
state (workers) busy, idle Worker state
state (scoreboard) open, waiting, starting, reading, sending, keepalive, dnslookup, closing, logging, finishing, idle_cleanup, unknown Scoreboard state

Resource Attributes

Attribute Description
apache.server.name Apache HTTP server name
apache.server.port Apache HTTP server port