How to Point the OpenTelemetry Demo at Local DuckLake
Run the duckdb-otlp server image in local-ducklake mode and send OpenTelemetry Demo traces, logs, and metrics to it over OTLP/HTTP.
The demo keeps its existing observability backends. You add duckdb-otlp as one more collector exporter.
Start the Local DuckLake Server
Section titled “Start the Local DuckLake Server”Create .env:
DUCKDB_MODE=local-ducklakeDUCKDB_OTLP_TOKEN=dev-token-123456
DUCKLAKE_NAME=lakeDUCKLAKE_CATALOG_PATH=/data/ducklake/catalog.duckdbDUCKLAKE_DATA_PATH=/data/ducklake/storage
DUCKDB_QUACK_ENABLED=1DUCKDB_QUACK_ADDR=0.0.0.0:9494DUCKDB_QUACK_TOKEN=dev-quack-token-123456Start the server:
mkdir -p data
docker run --rm --name duckdb-otlp \ --env-file .env \ -p 4318:4318 \ -p 9494:9494 \ -v "$(pwd)/data:/data" \ ghcr.io/smithclay/duckdb-otlp:latestLeave this container running. It accepts OTLP/HTTP at http://localhost:4318.
Configure the OpenTelemetry Demo Collector
Section titled “Configure the OpenTelemetry Demo Collector”In another terminal, clone the OpenTelemetry Demo:
git clone https://github.com/open-telemetry/opentelemetry-demo.gitcd opentelemetry-demoCreate src/otel-collector/otelcol-config-extras.yml:
exporters: otlp_http/duckdb: endpoint: http://host.docker.internal:4318 headers: Authorization: Bearer dev-token-123456
service: pipelines: traces: exporters: [otlp, debug, spanmetrics, otlp_http/duckdb] logs: exporters: [opensearch, debug, otlp_http/duckdb] metrics: exporters: [otlp_http/prometheus, debug, otlp_http/duckdb]The OpenTelemetry Demo merges this file with its main collector config. The merge replaces pipeline arrays, so keep the demo’s existing exporters in each list and add otlp_http/duckdb.
On Linux, add host.docker.internal to the otelcol service in docker-compose.yml:
services: otelcol: extra_hosts: - "host.docker.internal:host-gateway"Docker Desktop for macOS and Windows provides host.docker.internal.
Start the Demo
Section titled “Start the Demo”docker compose up -dGenerate traffic by opening the demo frontend and using the store:
http://localhost:8080Query the DuckLake Tables
Section titled “Query the DuckLake Tables”Flush buffered telemetry and query the running duckdb-otlp container:
duckdb <<'SQL'INSTALL quack;LOAD quack;
FROM quack_query( 'quack:localhost:9494', 'SELECT * FROM otlp_flush(''otlp:0.0.0.0:4318'')', token = 'dev-quack-token-123456');
FROM quack_query( 'quack:localhost:9494', $$ SELECT service_name, name, count(*) AS spans FROM lake.main.otlp_traces GROUP BY service_name, name ORDER BY spans DESC LIMIT 20 $$, token = 'dev-quack-token-123456');SQLInspect recent logs:
duckdb <<'SQL'INSTALL quack;LOAD quack;
FROM quack_query( 'quack:localhost:9494', $$ SELECT time_unix_nano, service_name, severity_text, body FROM lake.main.otlp_logs ORDER BY time_unix_nano DESC LIMIT 20 $$, token = 'dev-quack-token-123456');SQLThe server image is distroless and has no shell or DuckDB CLI, so run inspection SQL from a host DuckDB process through Quack instead of docker exec ... sh -c.
Stop Cleanly
Section titled “Stop Cleanly”Stop the demo:
docker compose downStop the DuckLake server:
docker stop duckdb-otlpDuring shutdown, the image sends otlp_stop('otlp:0.0.0.0:4318'), so the server commits remaining buffered rows before the process exits.
Troubleshooting
Section titled “Troubleshooting”- If the collector logs connection errors, confirm the
duckdb-otlpcontainer is still running anddocker logs duckdb-otlpshowsOTLP HTTP: 0.0.0.0:4318. - If you run the collector in Linux Docker and it cannot resolve
host.docker.internal, add theextra_hostsentry above. - If the server returns
401, confirm the collectorAuthorizationheader matchesDUCKDB_OTLP_TOKEN. - If you cannot see rows before the next background commit, run
otlp_flushbefore querying.