Punk::OpenTelemetry example: an app, and something to watch it
Two servers. One is an ordinary Punk application with the plugin turned on; the other is a collector that accepts what the exporter sends and prints it to STDERR as a trace tree, so you can watch telemetry arrive rather than take a vendor's word for it.
app.psgi- the instrumented applicationcollector.psgi- OTLP/HTTP in, readable spans out
Run it
Two terminals, from the distribution root.
The collector, on the port the OTLP spec uses for HTTP:
plackup -s Hyperman -p 4318 example/collector.psgi
The application, pointed at it:
OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318 \
OTEL_EXPORTER_OTLP_PROTOCOL=http/json \
OTEL_BSP_SCHEDULE_DELAY=1000 \
plackup -s Hyperman -p 5000 example/app.psgi
Then make some requests:
curl localhost:5000/hello/world
curl localhost:5000/work # calls out, so you get a client span too
curl localhost:5000/slow
curl localhost:5000/boom # dies on purpose; the span still arrives
Within a second or so the collector prints what it received:
=== punk-otel-example instance=c89d9f58 schema=https://opentelemetry.io/schemas/1.30.0
scope: Punk::OpenTelemetry 0.02
GET /hello/:name server 4.17ms trace=0726f412 span=52eb67ff
client.address = 127.0.0.1
http.request.method = GET
http.response.status_code = 200
http.route = /hello/:name
url.path = /hello/world
greet internal 0.04ms trace=0726f412 span=6c4d6ed5
greeting.name = world
* composed
The three environment variables
OTEL_EXPORTER_OTLP_PROTOCOL=http/json is what makes the collector readable.
JSON is three to five times larger on the wire than the protobuf default, so
it is the demo's choice and not the deployment's - which is the reason the
JSON transport exists at all: you can read it in a bug report.
OTEL_BSP_SCHEDULE_DELAY=1000 drops the batch delay to a second, so the demo
does not look broken while you wait out the five-second default.
OTEL_EXPORTER_OTLP_ENDPOINT is left to the environment on purpose. The
application declares its service name in code, where it belongs, and takes its
destination from the deployment, where that belongs. Point it at a real
collector or a vendor and nothing in app.psgi changes.
What the application does not contain
Any export code. The plugin builds the tracer and the exporter and schedules
the drain between them; the application says plugin 'OpenTelemetry' and then
writes routes. That is the point of the plugin, and the part most easily got
wrong by hand - a drain on the tail of a response ships every server span one
request late, because the server span is ended by the response observer that
runs after after_dispatch.
Turning it off
OTEL_SDK_DISABLED=true plackup -s Hyperman -p 5000 example/app.psgi
No tracer, no exporter, nothing installed into the request path. The boot line says so, which is the one thing you want to see when you have just switched telemetry off at three in the morning and need to know whether it took.
This is a demonstration
The collector accepts everything, stores nothing and authenticates nobody. It exists to make the wire format visible.