otel-observability
OpenTelemetry observability - tracing, metrics, logs, instrumentation, and context propagation patterns When user works with OpenTelemetry, adds tracing/metrics/logging, configures exporters, or mentions spans and observability
What this skill does
# OpenTelemetry Observability Agent
## What's New in OpenTelemetry (2024-2025)
- **Stable Logs**: Logging API and SDK now stable in many languages
- **Events API**: New semantic event support
- **Profiling signal**: CPU/memory profiling support (experimental)
- **Enhanced semantic conventions**: Standardized attribute names
- **Collector improvements**: Better performance and reliability
- **OTLP/JSON**: JSON encoding for OTLP widely supported
## Core Concepts
OpenTelemetry (OTel) provides three observability signals:
| Signal | Purpose | Use Case |
| ----------- | ---------------------------- | -------------------------------- |
| **Traces** | Request flow across services | Debugging distributed systems |
| **Metrics** | Numerical measurements | Performance monitoring, alerting |
| **Logs** | Structured event records | Error tracking, audit trails |
| **Baggage** | Context propagation | Passing data across services |
## Installation
### Node.js Packages
```bash
# Core packages
npm install @opentelemetry/api
npm install @opentelemetry/sdk-node
npm install @opentelemetry/sdk-trace-node
npm install @opentelemetry/sdk-metrics
# Auto-instrumentation
npm install @opentelemetry/auto-instrumentations-node
# OTLP exporters
npm install @opentelemetry/exporter-trace-otlp-http
npm install @opentelemetry/exporter-metrics-otlp-http
```
## Zero-Code Instrumentation
### Environment Variables
```bash
# Run with auto-instrumentation
OTEL_TRACES_EXPORTER="otlp" \
OTEL_METRICS_EXPORTER="otlp" \
OTEL_LOGS_EXPORTER="otlp" \
OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318" \
OTEL_SERVICE_NAME="my-service" \
OTEL_RESOURCE_ATTRIBUTES="service.version=1.0.0,deployment.environment=production" \
NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register" \
node app.js
```
### Common Environment Variables
| Variable | Description | Example |
| ----------------------------- | ------------------ | ------------------------- |
| `OTEL_SERVICE_NAME` | Service identifier | `"user-service"` |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Collector endpoint | `"http://localhost:4318"` |
| `OTEL_TRACES_EXPORTER` | Trace exporter | `"otlp"`, `"console"` |
| `OTEL_METRICS_EXPORTER` | Metrics exporter | `"otlp"`, `"prometheus"` |
| `OTEL_LOGS_EXPORTER` | Logs exporter | `"otlp"`, `"console"` |
| `OTEL_TRACES_SAMPLER` | Sampling strategy | `"parentbased_always_on"` |
| `OTEL_TRACES_SAMPLER_ARG` | Sampler argument | `"0.1"` (10% sampling) |
## Programmatic Setup
### Basic Node.js SDK
```typescript
// instrumentation.ts
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";
const sdk = new NodeSDK({
serviceName: "my-service",
traceExporter: new OTLPTraceExporter({
url: "http://localhost:4318/v1/traces",
}),
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({
url: "http://localhost:4318/v1/metrics",
}),
exportIntervalMillis: 60000,
}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
// Graceful shutdown
process.on("SIGTERM", () => {
sdk.shutdown().then(() => process.exit(0));
});
```
### Import Early
```typescript
// app.ts - instrumentation MUST be imported first
import "./instrumentation";
import express from "express";
// ... rest of app
```
## Tracing
### Getting a Tracer
```typescript
import { trace } from "@opentelemetry/api";
const tracer = trace.getTracer("my-service", "1.0.0");
```
### Creating Spans
```typescript
// Automatic span management (recommended)
tracer.startActiveSpan("operation-name", (span) => {
try {
// Your code here
span.setAttribute("user.id", userId);
return result;
} catch (error) {
span.recordException(error as Error);
span.setStatus({ code: SpanStatusCode.ERROR });
throw error;
} finally {
span.end();
}
});
// Async operations
async function processOrder(orderId: string) {
return tracer.startActiveSpan("process-order", async (span) => {
try {
span.setAttribute("order.id", orderId);
const result = await orderService.process(orderId);
return result;
} finally {
span.end();
}
});
}
```
### Span Kinds
```typescript
import { SpanKind } from "@opentelemetry/api";
// CLIENT - outgoing request (HTTP client, DB call)
tracer.startActiveSpan(
"fetch-user",
{ kind: SpanKind.CLIENT },
async (span) => {
const user = await fetch("/api/users/1");
span.end();
},
);
// SERVER - incoming request (HTTP handler)
tracer.startActiveSpan("handle-request", { kind: SpanKind.SERVER }, (span) => {
// Handle incoming HTTP request
span.end();
});
// PRODUCER - message production
tracer.startActiveSpan("send-message", { kind: SpanKind.PRODUCER }, (span) => {
queue.send(message);
span.end();
});
// CONSUMER - message consumption
tracer.startActiveSpan(
"process-message",
{ kind: SpanKind.CONSUMER },
(span) => {
processMessage(message);
span.end();
},
);
// INTERNAL - internal operation (default)
tracer.startActiveSpan("calculate", { kind: SpanKind.INTERNAL }, (span) => {
const result = heavyCalculation();
span.end();
});
```
### Span Attributes
```typescript
import { SpanStatusCode } from "@opentelemetry/api";
tracer.startActiveSpan("http-request", (span) => {
// Set attributes
span.setAttribute("http.method", "GET");
span.setAttribute("http.url", "https://api.example.com/users");
span.setAttribute("http.status_code", 200);
// Set multiple attributes
span.setAttributes({
"user.id": "123",
"user.role": "admin",
"request.cached": false,
});
// Add events
span.addEvent("cache-miss", {
"cache.key": "user:123",
});
// Set status
span.setStatus({ code: SpanStatusCode.OK });
span.end();
});
```
### Error Handling
```typescript
tracer.startActiveSpan("risky-operation", (span) => {
try {
riskyOperation();
} catch (error) {
// Record the exception
span.recordException(error as Error);
// Set error status
span.setStatus({
code: SpanStatusCode.ERROR,
message: (error as Error).message,
});
throw error;
} finally {
span.end();
}
});
```
## Metrics
### Getting a Meter
```typescript
import { metrics } from "@opentelemetry/api";
const meter = metrics.getMeter("my-service", "1.0.0");
```
### Counter (Monotonic Increasing)
```typescript
// Create counter
const requestCounter = meter.createCounter("http.requests.total", {
description: "Total number of HTTP requests",
unit: "1",
});
// Increment
requestCounter.add(1, {
"http.method": "GET",
"http.route": "/api/users",
"http.status_code": 200,
});
```
### UpDownCounter (Can Decrease)
```typescript
const activeConnections = meter.createUpDownCounter("connections.active", {
description: "Number of active connections",
unit: "1",
});
// Increment on connect
activeConnections.add(1);
// Decrement on disconnect
activeConnections.add(-1);
```
### Histogram (Distribution)
```typescript
const requestDuration = meter.createHistogram("http.request.duration", {
description: "HTTP request duration",
unit: "ms",
});
// Record value
const start = performance.now();
await handleRequest();
const duration = performance.now() - start;
requestDuration.record(duration, {
"http.method": "POST",
"http.route": "/api/orders",
});
```
### Observable Gauge (Async Measurement)
```typescript
// For values that are measured periodically
const memoryUsage = meter.createObservableGaugRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.