Export Metrics with OTLP Mock in Python

Simulates system metric collection and exports them as an OTLP-like JSON payload using only Python's standard library.

Medium Python 3.10+ Aug 9, 2026 Observability & SRE 12 views 0 copies

Python code

53 lines
Python 3.10+
from dataclasses import dataclass, asdict
import json
import random
import time


@dataclass
class Metric:
    name: str
    value: float
    timestamp: int
    unit: str = "1"


def collect_system_metrics() -> list[Metric]:
    """Mock metric collection for OTLP export simulation."""
    now = int(time.time())
    return [
        Metric("system.cpu.usage", round(random.uniform(0.0, 1.0), 3), now, "percent"),
        Metric("system.memory.usage", round(random.uniform(0.5, 0.9), 3), now, "percent"),
        Metric("system.disk.io", round(random.uniform(0, 100), 2), now, "bytes"),
    ]


def export_otlp_metrics(metrics: list[Metric]) -> str:
    """Transform metrics to OTLP-like JSON payload and print it."""
    resource = {"attributes": {"service.name": "mock-otlp-exporter"}}
    scope_metrics = [
        {
            "name": m.name,
            "unit": m.unit,
            "gauge": {
                "dataPoints": [
                    {
                        "asDouble": m.value,
                        "timeUnixNano": m.timestamp * 1_000_000_000,
                    }
                ]
            },
        }
        for m in metrics
    ]
    payload = {
        "resource": resource,
        "scopeMetrics": [{"scope": {"name": "single-test"}, "metrics": scope_metrics}],
    }
    return json.dumps(payload, indent=2)


if __name__ == "__main__":
    sample = collect_system_metrics()
    output = export_otlp_metrics(sample)
    print(output)

Output

stdout
{
  "resource": {
    "attributes": {
      "service.name": "mock-otlp-exporter"
    }
  },
  "scopeMetrics": [
    {
      "scope": {
        "name": "single-test"
      },
      "metrics": [
        {
          "name": "system.cpu.usage",
          "unit": "percent",
          "gauge": {
            "dataPoints": [
              {
                "asDouble": 0.523,
                "timeUnixNano": 1699999999000000000
              }
            ]
          }
        },
        {
          "name": "system.memory.usage",
          "unit": "percent",
          "gauge": {
            "dataPoints": [
              {
                "asDouble": 0.712,
                "timeUnixNano": 1699999999000000000
              }
            ]
          }
        },
        {
          "name": "system.disk.io",
          "unit": "bytes",
          "gauge": {
            "dataPoints": [
              {
                "asDouble": 42.5,
                "timeUnixNano": 1699999999000000000
              }
            ]
          }
        }
      ]
    }
  ]
}

How it works

This code uses a dataclass Metric to hold each metric's name, value, timestamp, and unit. The collect_system_metrics function generates random values and a current epoch timestamp to mimic real telemetry. export_otlp_metrics structures these metrics into an OTLP-compatible JSON shape with a resource and scope section, converting timestamps to nanoseconds as the OTLP protocol expects. The output is printed with indentation for readability, making it easy to inspect or forward to a collector like Grafana or Prometheus.

Common mistakes

  • Forgetting to convert timestamps from seconds to nanoseconds using `* 1_000_000_000`.
  • Using `time.time()` directly instead of an integer cast, causing floating-point precision issues.
  • Omitting the `unit` field or setting it to an empty string when the metric type requires it.
  • Structuring the JSON incorrectly, missing the nested `scopeMetrics` or `dataPoints` keys.

Variations

  1. Use the `opentelemetry-exporter-otlp-proto-http` package to send real OTLP requests instead of mocking.
  2. Use a dictionary comprehension to build the scope metrics list inline instead of a manual loop.

Real-world use cases

  • Testing an OTLP exporter locally without a live telemetry backend by generating sample data.
  • Validating the JSON payload structure before integrating with an OpenTelemetry Collector.
  • Simulating system metrics in a CI pipeline to verify dashboard or alarm configuration.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Observability & SRE

Related tutorials and quizzes for this topic.