Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/otel-metrics-demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
42 changes: 42 additions & 0 deletions examples/otel-metrics-demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# OTLP Metrics Demo

A tiny standalone script that exports OpenTelemetry **metrics** to a Temps
server over OTLP/HTTP — the fastest way to confirm the metrics ingest path works
end to end.

## What

Uses the standard OpenTelemetry SDK (`@opentelemetry/sdk-metrics` +
`@opentelemetry/exporter-metrics-otlp-proto`) to push protobuf metrics straight
to Temps' `/api/otel/v1/metrics` endpoint — no collector sidecar required. It
emits three instruments, each with labels:

| Instrument | Type | Name |
|---|---|---|
| Counter | sum | `demo.requests.total` |
| Histogram | histogram | `demo.request.duration` |
| Observable gauge | gauge | `demo.active.requests` |

For a full app that wires analytics, error tracking, tracing **and** metrics,
see [`observability-starter`](../observability-starter).

## Run

```bash
bun install
TEMPS_TOKEN=tk_your_key TEMPS_PROJECT_ID=123 node index.mjs
```

Then open your project's **Monitoring → Metrics** in Temps; the three
`demo.*` metrics should appear within a few seconds.

## Configuration

| Env var | Default | Purpose |
|---|---|---|
| `TEMPS_TOKEN` | — (required) | A Temps API key (`tk_…`) with access to the project |
| `TEMPS_PROJECT_ID` | — (required) | Project to attribute metrics to (sent as the `X-Temps-Project-Id` header) |
| `TEMPS_OTLP_URL` | `http://localhost:8080/api/otel/v1/metrics` | The Temps OTLP/HTTP metrics endpoint |

Create an API key in Temps under **Settings → API Keys** (or via the CLI:
`temps api-key --name metrics-demo --role admin`).
73 changes: 73 additions & 0 deletions examples/otel-metrics-demo/bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

81 changes: 81 additions & 0 deletions examples/otel-metrics-demo/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Minimal real-OpenTelemetry-SDK app that exports OTLP/HTTP protobuf metrics to
// a Temps server. Emits a Counter, a Histogram and an ObservableGauge — each
// with labels — then force-flushes and exits. Use it to verify the Temps
// ClickHouse metrics ingest path end-to-end.
//
// TEMPS_TOKEN=tk_... TEMPS_PROJECT_ID=5 node index.mjs
//
import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-proto';
import { Resource } from '@opentelemetry/resources';
import {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
} from '@opentelemetry/semantic-conventions';

const TOKEN = process.env.TEMPS_TOKEN;
const PROJECT_ID = process.env.TEMPS_PROJECT_ID;
const URL =
process.env.TEMPS_OTLP_URL || 'http://localhost:8080/api/otel/v1/metrics';

if (!TOKEN || !PROJECT_ID) {
console.error('Set TEMPS_TOKEN and TEMPS_PROJECT_ID');
process.exit(1);
}

const exporter = new OTLPMetricExporter({
url: URL,
headers: {
Authorization: `Bearer ${TOKEN}`,
'X-Temps-Project-Id': String(PROJECT_ID),
},
});

const provider = new MeterProvider({
resource: new Resource({
[ATTR_SERVICE_NAME]: 'otel-metrics-demo',
[ATTR_SERVICE_VERSION]: '1.0.0',
}),
readers: [
new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 2000,
}),
],
});

const meter = provider.getMeter('otel-metrics-demo');

// Counter (monotonic, cumulative by default).
const requests = meter.createCounter('demo.requests.total', {
description: 'Total demo requests',
unit: '1',
});
// Histogram (explicit buckets).
const latency = meter.createHistogram('demo.request.duration', {
description: 'Demo request latency',
unit: 'ms',
});
// Observable gauge.
let inFlight = 0;
meter
.createObservableGauge('demo.active.requests', {
description: 'In-flight demo requests',
unit: '1',
})
.addCallback((res) => res.observe(inFlight, { region: 'eu' }));

// Generate some traffic.
for (let i = 0; i < 100; i++) {
const method = i % 2 === 0 ? 'GET' : 'POST';
requests.add(1, { 'http.method': method, route: '/checkout' });
latency.record(Math.round(Math.random() * 480) + 5, { 'http.method': method });
inFlight = Math.floor(Math.random() * 12);
}

console.log(`exporting metrics to ${URL} (project ${PROJECT_ID})...`);
await provider.forceFlush();
// Give the periodic reader one cycle too, then shut down cleanly.
await new Promise((r) => setTimeout(r, 2500));
await provider.shutdown();
console.log('done — metrics flushed.');
16 changes: 16 additions & 0 deletions examples/otel-metrics-demo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "otel-metrics-demo",
"private": true,
"type": "module",
"description": "Minimal real-OpenTelemetry-SDK app that exports OTLP/HTTP protobuf metrics to a Temps server, used to verify the ClickHouse metrics ingest path end-to-end.",
"scripts": {
"start": "node index.mjs"
},
"dependencies": {
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/sdk-metrics": "^1.30.1",
"@opentelemetry/exporter-metrics-otlp-proto": "^0.57.2",
"@opentelemetry/resources": "^1.30.1",
"@opentelemetry/semantic-conventions": "^1.30.0"
}
}