What Are Traces and Spans in OpenTelemetry?
Trace — полный путь одного запроса через все сервисы.
Span — отдельный шаг в этом пути (функция, SQL, HTTP-вызов).
Root span — первый span (обычно входящий HTTP-запрос).
Child span — вложенный шаг.
Context — передаёт trace_id и текущий span по асинхронным вызовам.
Sampler — решает, записывать ли трассировку.
Exporter — отправляет spans в OneUptime, Jaeger и т.д.
Структура span
- name — короткое имя операции
- start/end time — длительность
- status — OK / ERROR
- attributes — произвольные метки (user_id, db.table)
- events — точки во времени (exception, cache hit)
- links — связи с другими traces
Быстрый старт в Node.js / TypeScript
npm i @opentelemetry/api @opentelemetry/sdk-node \
@opentelemetry/auto-instrumentations-node
// tracing.ts
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
const sdk = new NodeSDK({
serviceName: 'my-api',
traceExporter: new OTLPTraceExporter({ url: 'https://otlp.oneuptime.com' }),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
Ручная инструментация
import { trace } from '@opentelemetry/api';
const tracer = trace.getTracer('my-service');
async function getUser(id: string) {
return tracer.startActiveSpan('db.users.findById', async (span) => {
span.setAttributes({ 'db.table': 'users', 'user.id': id });
try {
const user = await db.users.findById(id);
span.setStatus({ code: SpanStatusCode.OK });
return user;
} catch (e) {
span.recordException(e);
span.setStatus({ code: SpanStatusCode.ERROR, message: e.message });
throw e;
} finally {
span.end();
}
});
}
Express/Fastify middleware
import { trace } from '@opentelemetry/api';
export function traceMiddleware(req, res, next) {
const span = trace.getTracer('http').startSpan(`${req.method} ${req.route?.path || req.url}`);
trace.getActiveContext().with(trace.setSpan(trace.getActiveContext(), span), () => {
res.on('finish', () => {
span.setAttributes({
'http.status_code': res.statusCode,
'http.method': req.method,
'http.route': req.route?.path,
});
span.end();
});
next();
});
}
Практические советы
- Именование:
verb noun
(GET /users
,db.users.insert
). - Атрибуты: добавляйте
user.id
,order.id
,region
. - Ошибки:
span.recordException(err)
+span.setStatus({code: ERROR})
. - Sampling: head-based (решение на старте) или tail-based (после завершения).
- Антипаттерны: слишком мелкие spans, отсутствие
span.end()
, захардкоженные ID.
Сборка всего вместе
- Запустите SDK на старте приложения.
- Добавьте auto-instrumentations (http, express, pg, redis).
- Дополните ручными spans для критичных операций.
- Отправляйте traces в OneUptime → исследуйте flame-графы, ищите узкие места.
Комментарии (28)
- OTEL хвалят как стандарт, но реальные реализации сильно разнятся между вендорами и часто усложняют жизнь.
- Базовые понятия: span — это интервал работы с уникальным ID и ссылкой на родителя, trace — DAG спанов, рассказывающий историю запроса.
- Авто-инструментация почти даром даёт данные для JVM-приложений, но вне веб-бэкендов примеров мало и приходится искать «правильный» подмножество.
- Некоторые жалуются на объём кода и хранилище (десятки ТБ трейсов за неделю), другие считают это разовой настройкой и платой за прозрачность системы.
- Появляются упрощающие обёртки (Logfire, otelize) и примеры интеграции, но документация по дашбордам Grafana всё ещё вызывает трудности.
SmallJS: Smalltalk-80 that compiles to JavaScript
SmallJS — свободная реализация Smalltalk-80, компилирующаяся в JavaScript для браузеров и Node.js.
- v1.7 уже доступна (GitHub).
- Работа ведётся в файлах, а не образах; отлично сочетается с VS Code (подсветка, отладка).
- Используются привычные JS-имена классов и методов; в комплекте обёртки для DOM, Express, БД, потоков.
Быстрый старт — примеры проектов и Todo-приложение.
Хотите помочь? Пишите на info@small-js.org.
Комментарии (34)
- SmallJS вызвал всплеск интереса; автор @Smalltalker-80 откликается на вопросы.
- Проект файл-ориентирован, без образа; VSCode вместо браузерной IDE.
- flavio81 и wild_egg сожалеют о потере «живого» Smalltalk-опыта и сложностях синхронизации образов в Lisp.
- Playground SmallJS компилирует выражения прямо в браузере, но полноценной live-среды нет.
- Упомянуты Amber (застой), Pharo (монолитная VM) и Chrome Workspace для хот-релоада.