Skip to content

OpenTelemetry

npmJSRJSR Score

Distributed tracing for GramIO via the OpenTelemetry API. Each incoming update becomes a root span, and each Telegram API call becomes a child span. Works with any OTEL-compatible backend (Jaeger, Grafana Tempo, Axiom, etc.) and integrates with Elysia webhooks.

Installation

sh
npm install @gramio/opentelemetry
sh
yarn add @gramio/opentelemetry
sh
pnpm add @gramio/opentelemetry
sh
bun add @gramio/opentelemetry

Usage

typescript
import { Bot } from "gramio";
import { opentelemetryPlugin } from "@gramio/opentelemetry";

const bot = new Bot(process.env.BOT_TOKEN!)
    .extend(opentelemetryPlugin({
        recordApiParams: true,
    }))
    .command("start", (context) => context.send("Hello!"));

await bot.start();

Trace Hierarchy

Each update produces a trace tree like the following:

gramio.update.message (CONSUMER)
  ├── telegram.api/sendMessage (CLIENT)
  ├── telegram.api/deleteMessage (CLIENT)
  └── custom spans via record()

Methods

record(name, fn)

Creates a custom child span inside the current update trace:

typescript
bot.command("heavy", async (context) => {
    await context.record("fetch-data", async () => {
        // expensive work tracked as its own span
    });
});

getCurrentSpan()

Returns the active OpenTelemetry span for the current update:

typescript
bot.on("message", (context) => {
    const span = context.getCurrentSpan();
    span?.addEvent("custom-event");
});

setAttributes(attrs)

Adds custom attributes to the current span:

typescript
bot.command("order", (context) => {
    context.setAttributes({
        "order.id": orderId,
        "order.total": total,
    });
});