Skip to content

Hello World (Traces, Metrics, Logs)

A simple python console application instrumented with OpenTelemetry that generates a span and metrics in some scenarios.

Setup environment

Development Environment

You can run otel-tui as OpenTelemetry Collector, which acts as a terminal OpenTelemetry viewer

docker run -p 4317:4317 -p 4318:4318 --rm -it --name otel-tui ymtdzzz/otel-tui:latest

Install packages

Create the virtual environment and install the dependencies:

uv venv && source .venv/bin/activate

requirements.txt
opentelemetry-api
opentelemetry-sdk
opentelemetry-exporter-otlp-proto-grpc
opentelemetry-exporter-otlp-proto-http

Quick install with uv

uv pip install -r https://emdneto.github.io/opentelemetry-by-example/python/hello-world/requirements.txt

Traces

snippet_console.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace.export import (
    BatchSpanProcessor,
    ConsoleSpanExporter,
)

# Creates a resource and adds it to the tracer provider
resource = Resource.create({"service.name": "hello-world-console"})
provider = TracerProvider(resource=resource)
trace.set_tracer_provider(provider)

# Adds span processor with the OTLP exporter to the tracer provider
provider.add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))
tracer = trace.get_tracer(__name__)

# Starts and sets an attribute to a span
with tracer.start_as_current_span("HelloWorldSpan") as span:
    span.set_attribute("foo", "bar")
    print("Hello world Example")

Run this Python snippet

uv run https://emdneto.github.io/opentelemetry-by-example/python/hello-world/snippet_console.py
snippet_grpc.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
    OTLPSpanExporter,
)

# Creates a resource and adds it to the tracer provider
resource = Resource.create({"service.name": "hello-world-otlp-grpc"})
provider = TracerProvider(resource=resource)
trace.set_tracer_provider(provider)

# Adds span processor with the OTLP exporter to the tracer provider
provider.add_span_processor(
    BatchSpanProcessor(
        OTLPSpanExporter(endpoint="http://localhost:4317", insecure=True)
    )
)

tracer = trace.get_tracer(__name__, attributes={"domain": "foo"})

# Starts and sets an attribute to a span
with tracer.start_as_current_span("HelloWorldSpanGrpc") as span:
    span.set_attribute("foo", "grpc")
    span.add_event("event in span")
    print("Hello world")

Run this Python snippet

uv run https://emdneto.github.io/opentelemetry-by-example/python/hello-world/snippet_grpc.py
snippet_http.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import (
    OTLPSpanExporter,
)

# Creates a resource and adds it to the tracer provider
resource = Resource.create({"service.name": "hello-world-otlp-http"})
provider = TracerProvider(resource=resource)
trace.set_tracer_provider(provider)

# Adds span processor with the OTLP exporter to the tracer provider
provider.add_span_processor(
    BatchSpanProcessor(
        OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
    )
)

tracer = trace.get_tracer(__name__, attributes={"domain": "foo"})

# Starts and sets an attribute to a span
with tracer.start_as_current_span("HelloWorldSpanHttp") as span:
    span.set_attribute("foo", "http")
    span.add_event("event in span")
    print("Hello world")

Run this Python snippet

uv run https://emdneto.github.io/opentelemetry-by-example/python/hello-world/snippet_http.py

Metrics

snippet_metrics_console.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.metrics.export import (
    ConsoleMetricExporter,
    PeriodicExportingMetricReader,
)

# Creates a resource and adds it to the meter provider
resource = Resource.create({"service.name": "hello-world-metrics-console"})
metric_reader = PeriodicExportingMetricReader(
    exporter=ConsoleMetricExporter(),
    export_interval_millis=1000,  # Export every 1 second for demo
)
provider = MeterProvider(resource=resource, metric_readers=[metric_reader])
metrics.set_meter_provider(provider)

meter = metrics.get_meter(__name__)

# Create different metric instruments
request_counter = meter.create_counter(
    name="hello_requests_total",
    description="Total number of hello requests",
    unit="1",
)

response_time_histogram = meter.create_histogram(
    name="hello_request_duration_seconds",
    description="Hello request duration in seconds",
    unit="s",
)

active_users_gauge = meter.create_up_down_counter(
    name="hello_active_users",
    description="Number of active users",
    unit="1",
)

request_counter.add(1, {"method": "GET", "endpoint": "/hello"})
response_time_histogram.record(0.1, {"method": "GET", "endpoint": "/hello"})
active_users_gauge.add(1, {"region": "us-west"})

Run this Python snippet

uv run https://emdneto.github.io/opentelemetry-by-example/python/hello-world/snippet_metrics_console.py
snippet_metrics_grpc.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
    OTLPMetricExporter,
)

# Creates a resource and adds it to the meter provider
resource = Resource.create({"service.name": "hello-world-otlp-grpc"})
metric_reader = PeriodicExportingMetricReader(
    exporter=OTLPMetricExporter(
        endpoint="http://localhost:4317", insecure=True
    ),
    export_interval_millis=1000,  # Export every 1 second for demo
)
provider = MeterProvider(resource=resource, metric_readers=[metric_reader])
metrics.set_meter_provider(provider)

meter = metrics.get_meter(__name__)

# Create different metric instruments
request_counter = meter.create_counter(
    name="hello_requests_total",
    description="Total number of hello requests",
    unit="1",
)

response_time_histogram = meter.create_histogram(
    name="hello_request_duration_seconds",
    description="Hello request duration in seconds",
    unit="s",
)

active_users_gauge = meter.create_up_down_counter(
    name="hello_active_users",
    description="Number of active users",
    unit="1",
)

request_counter.add(
    1, {"method": "POST", "endpoint": "/hello", "transport": "grpc"}
)
response_time_histogram.record(
    0.1, {"method": "POST", "endpoint": "/hello", "transport": "grpc"}
)
active_users_gauge.add(1, {"region": "us-west", "transport": "grpc"})

Run this Python snippet

uv run https://emdneto.github.io/opentelemetry-by-example/python/hello-world/snippet_metrics_grpc.py
snippet_metrics_http.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.exporter.otlp.proto.http.metric_exporter import (
    OTLPMetricExporter,
)

# Creates a resource and adds it to the meter provider
resource = Resource.create({"service.name": "hello-world-otlp-http"})
metric_reader = PeriodicExportingMetricReader(
    exporter=OTLPMetricExporter(endpoint="http://localhost:4318/v1/metrics"),
    export_interval_millis=1000,  # Export every 1 second for demo
)
provider = MeterProvider(resource=resource, metric_readers=[metric_reader])
metrics.set_meter_provider(provider)

meter = metrics.get_meter(__name__)

# Create different metric instruments
request_counter = meter.create_counter(
    name="hello_requests_total",
    description="Total number of hello requests",
    unit="1",
)

response_time_histogram = meter.create_histogram(
    name="hello_request_duration_seconds",
    description="Hello request duration in seconds",
    unit="s",
)

active_users_gauge = meter.create_up_down_counter(
    name="hello_active_users",
    description="Number of active users",
    unit="1",
)

request_counter.add(
    1, {"method": "POST", "endpoint": "/hello", "transport": "http"}
)
response_time_histogram.record(
    0.1, {"method": "POST", "endpoint": "/hello", "transport": "http"}
)
active_users_gauge.add(1, {"region": "us-west", "transport": "http"})

Run this Python snippet

uv run https://emdneto.github.io/opentelemetry-by-example/python/hello-world/snippet_metrics_http.py

Logs

TODO

In Development