> otel-js
Instrument Node.js apps with OpenTelemetry. Use when a user asks to add distributed tracing, collect metrics, instrument HTTP requests, trace database queries, or set up observability for microservices.
curl "https://skillshub.wtf/TerminalSkills/skills/otel-js?format=md"OpenTelemetry for Node.js
Overview
OpenTelemetry (OTel) is the standard for distributed tracing, metrics, and logs. Instrument your Node.js services once, and send telemetry to any backend (Jaeger, Grafana Tempo, Datadog, Honeycomb). Auto-instrumentation captures HTTP, database, and gRPC calls without code changes.
Instructions
Step 1: Auto-Instrumentation
npm install @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-trace-otlp-http @opentelemetry/exporter-metrics-otlp-http
// instrumentation.ts — OpenTelemetry setup (import BEFORE app code)
import { NodeSDK } from '@opentelemetry/sdk-node'
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'
import { Resource } from '@opentelemetry/resources'
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions'
const sdk = new NodeSDK({
resource: new Resource({
[ATTR_SERVICE_NAME]: 'api-service',
[ATTR_SERVICE_VERSION]: process.env.npm_package_version || '1.0.0',
}),
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4318/v1/traces',
}),
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4318/v1/metrics',
}),
exportIntervalMillis: 30000,
}),
instrumentations: [
getNodeAutoInstrumentations({
'@opentelemetry/instrumentation-http': {
ignoreIncomingPaths: ['/health', '/ready'], // don't trace health checks
},
'@opentelemetry/instrumentation-express': { enabled: true },
'@opentelemetry/instrumentation-pg': { enabled: true },
'@opentelemetry/instrumentation-redis': { enabled: true },
}),
],
})
sdk.start()
console.log('OpenTelemetry initialized')
process.on('SIGTERM', () => sdk.shutdown())
Step 2: Custom Spans
// services/orders.ts — Manual instrumentation for business logic
import { trace, SpanStatusCode } from '@opentelemetry/api'
const tracer = trace.getTracer('order-service')
export async function processOrder(orderId: string) {
return tracer.startActiveSpan('processOrder', async (span) => {
span.setAttribute('order.id', orderId)
try {
// Child span for payment
const payment = await tracer.startActiveSpan('chargePayment', async (paymentSpan) => {
paymentSpan.setAttribute('payment.provider', 'stripe')
const result = await stripe.charges.create({ amount: 9999 })
paymentSpan.setAttribute('payment.id', result.id)
paymentSpan.end()
return result
})
span.setAttribute('order.status', 'completed')
span.setAttribute('payment.id', payment.id)
span.setStatus({ code: SpanStatusCode.OK })
} catch (err) {
span.recordException(err)
span.setStatus({ code: SpanStatusCode.ERROR, message: err.message })
throw err
} finally {
span.end()
}
})
}
Step 3: Run
# Start app with instrumentation loaded first
node --import ./instrumentation.ts src/server.ts
# Or in package.json
# "start": "node --import ./instrumentation.ts dist/server.js"
Guidelines
- Import instrumentation BEFORE your app code — auto-instrumentation patches libraries on import.
- Use
--importflag (ESM) or-rflag (CJS) to load instrumentation first. - Auto-instrumentation covers HTTP, Express, Fastify, PostgreSQL, Redis, MongoDB, gRPC.
- Add custom spans for business logic (order processing, payment flows) — auto-instrumentation only covers infrastructure.
- Send telemetry to an OTLP collector (Grafana Alloy, OTel Collector) for routing to multiple backends.
> related_skills --same-repo
> zustand
You are an expert in Zustand, the small, fast, and scalable state management library for React. You help developers manage global state without boilerplate using Zustand's hook-based stores, selectors for performance, middleware (persist, devtools, immer), computed values, and async actions — replacing Redux complexity with a simple, un-opinionated API in under 1KB.
> zod
You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.
> xero-accounting
Integrate with the Xero accounting API to sync invoices, expenses, bank transactions, and contacts — and generate financial reports like P&L and balance sheet. Use when: connecting apps to Xero, automating bookkeeping workflows, syncing accounting data, or pulling financial reports programmatically.
> windsurf-rules
Configure Windsurf AI coding assistant with .windsurfrules and workspace rules. Use when: customizing Windsurf for a project, setting AI coding standards, creating team-shared Windsurf configurations, or tuning Cascade AI behavior.