Agent Skill
2/7/2026observability
This skill should be used when the user asks about "Effect logging", "Effect.log", "Effect metrics", "Effect tracing", "spans", "telemetry", "Metric.counter", "Metric.gauge", "Metric.histogram", "OpenTelemetry", "structured logging", "log levels", "Effect.logDebug", "Effect.logInfo", "Effect.logWarning", "Effect.logError", or needs to understand how Effect handles logging, metrics, and distributed tracing.
A
andrueandersoncs
3GitHub Stars
1Views
npx skills add andrueandersoncs/claude-skill-effect-ts
SKILL.md
| Name | observability |
| Description | This skill should be used when the user asks about "Effect logging", "Effect.log", "Effect metrics", "Effect tracing", "spans", "telemetry", "Metric.counter", "Metric.gauge", "Metric.histogram", "OpenTelemetry", "structured logging", "log levels", "Effect.logDebug", "Effect.logInfo", "Effect.logWarning", "Effect.logError", or needs to understand how Effect handles logging, metrics, and distributed tracing. |
name: Observability description: This skill should be used when the user asks about "Effect logging", "Effect.log", "Effect metrics", "Effect tracing", "spans", "telemetry", "Metric.counter", "Metric.gauge", "Metric.histogram", "OpenTelemetry", "structured logging", "log levels", "Effect.logDebug", "Effect.logInfo", "Effect.logWarning", "Effect.logError", or needs to understand how Effect handles logging, metrics, and distributed tracing. version: 1.0.0
Observability in Effect
Overview
Effect provides built-in observability:
- Logging - Structured, leveled logging
- Metrics - Counters, gauges, histograms
- Tracing - Distributed tracing with spans
All three integrate seamlessly with Effect's execution model.
Logging
Basic Logging
import { Effect } from "effect";
const program = Effect.gen(function* () {
yield* Effect.log("Starting process");
yield* Effect.logDebug("Debug information");
yield* Effect.logInfo("Processing item");
yield* Effect.logWarning("Resource running low");
yield* Effect.logError("Failed to connect");
yield* Effect.logFatal("Critical system failure");
});
Log Levels
import { LogLevel, Logger } from "effect";
// Set minimum log level
const filtered = program.pipe(Logger.withMinimumLogLevel(LogLevel.Info));
// Available levels (lowest to highest):
// Trace, Debug, Info, Warning, Error, Fatal, None
Structured Logging
// Log with structured data
yield *
Effect.log("User action").pipe(
Effect.annotateLogs({
userId: "123",
action: "login",
ip: "192.168.1.1",
}),
);
// Annotations apply to all logs in scope
const program = Effect.gen(function* () {
yield* Effect.log("First log"); // Has userId annotation
yield* Effect.log("Second log"); // Has userId annotation
}).pipe(Effect.annotateLogs({ userId: "123" }));
Log Spans
// Add timing/context spans
const program = Effect.gen(function* () {
yield* Effect.log("Processing");
yield* processItems();
yield* Effect.log("Complete");
}).pipe(Effect.withLogSpan("request-handler"));
// Logs include: [request-handler 45ms] Processing
Custom Logger
import { Logger } from "effect";
const JsonLogger = Logger.make(({ logLevel, message, annotations, date }) => {
console.log(
JSON.stringify({
level: logLevel.label,
message: String(message),
timestamp: date.toISOString(),
...annotations,
}),
);
});
const program = Effect.gen(function* () {
yield* Effect.log("Hello");
}).pipe(Effect.provide(Logger.replace(Logger.defaultLogger, JsonLogger)));
Metrics
Counter - Track Occurrences
import { Metric } from "effect";
const requestCount = Metric.counter("http_requests_total", {
description: "Total HTTP requests",
});
const program = Effect.gen(function* () {
yield* Metric.increment(requestCount);
yield* Metric.incrementBy(requestCount, 5);
});
const tracked = handleRequest.pipe(Metric.trackAll(requestCount));
Gauge - Track Current Value
const activeConnections = Metric.gauge("active_connections", {
description: "Current active connections",
});
const program = Effect.gen(function* () {
yield* Metric.set(activeConnections, 10);
yield* Metric.incrementBy(activeConnections, 1);
yield* Metric.decrementBy(activeConnections, 1);
});
Histogram - Track Distributions
const requestDuration = Metric.histogram("http_request_duration_ms", {
description: "Request duration in milliseconds",
boundaries: [10, 50, 100, 250, 500, 1000],
});
yield * Metric.observe(requestDuration, 125);
const tracked = handleRequest.pipe(Metric.trackDuration(requestDuration));
Summary - Statistical Summary
const responseSizes = Metric.summary("response_size_bytes", {
description: "Response payload sizes",
maxAge: "1 minute",
maxSize: 100,
quantiles: [0.5, 0.9, 0.99],
});
yield * Metric.observe(responseSizes, 1024);
Frequency - Count by Tag
const statusCodes = Metric.frequency("http_status_codes");
yield * Metric.observe(statusCodes, "200");
yield * Metric.observe(statusCodes, "404");
yield * Metric.observe(statusCodes, "500");
Tagged Metrics
const requestCount = Metric.counter("requests").pipe(Metric.tagged("service", "api"), Metric.tagged("version", "v1"));
// Dynamic tags
const taggedCount = Metric.counter("requests").pipe(Metric.taggedWithLabels(["method", "endpoint"]));
yield * Metric.increment(taggedCount).pipe(Metric.taggedWithLabels(["GET", "/users"]));
Reading Metrics
const program = Effect.gen(function* () {
yield* Metric.increment(requestCount);
yield* Metric.increment(requestCount);
const snapshot = yield* Metric.value(requestCount);
// snapshot.count === 2
});
Tracing
Creating Spans
import { Effect } from "effect";
const traced = handleRequest.pipe(Effect.withSpan("handle-request"));
const traced = handleRequest.pipe(
Effect.withSpan("handle-request", {
attributes: {
"http.method": "GET",
"http.url": "/api/users",
},
}),
);
Nested Spans
const program = Effect.gen(function* () {
yield* fetchUser(id).pipe(Effect.withSpan("fetch-user"));
yield* processData(data).pipe(Effect.withSpan("process-data"));
yield* saveResult(result).pipe(Effect.withSpan("save-result"));
}).pipe(Effect.withSpan("main-operation"));
// Creates: main-operation
// ├── fetch-user
// ├── process-data
// └── save-result
Adding Span Attributes
import { Tracer } from "effect";
const program = Effect.gen(function* () {
yield* Effect.annotateCurrentSpan("user.id", userId);
yield* Effect.annotateCurrentSpan("event", "user_validated");
const result = yield* processUser(userId);
yield* Effect.annotateCurrentSpan("result.status", result.status);
});
Span Status
const program = Effect.gen(function* () {
try {
return yield* riskyOperation;
} catch (error) {
yield* Effect.setSpanStatus({
code: "error",
message: error.message,
});
return yield* Effect.fail(error);
}
}).pipe(Effect.withSpan("risky-operation"));
Custom Tracer
import { Tracer } from "effect";
const ConsoleTracer = Tracer.make({
span: (name, parent, context, links, startTime) => ({
attribute: (key, value) => console.log(`[${name}] ${key}=${value}`),
end: (endTime, exit) => console.log(`[${name}] ended`),
event: (name, startTime, attributes) => console.log(`[${name}] event: ${name}`),
status: (status) => console.log(`[${name}] status: ${status.code}`),
}),
});
const program = myEffect.pipe(Effect.provide(Tracer.layer(ConsoleTracer)));
OpenTelemetry Integration
import { NodeSdk } from "@effect/opentelemetry";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
const TracingLive = NodeSdk.layer(() => ({
resource: { serviceName: "my-service" },
spanProcessor: new BatchSpanProcessor(new OTLPTraceExporter()),
}));
const program = myEffect.pipe(Effect.provide(TracingLive));
Combining Observability
const handleRequest = (req: Request) =>
Effect.gen(function* () {
yield* Effect.log("Request received").pipe(Effect.annotateLogs({ path: req.path, method: req.method }));
yield* Metric.increment(requestCount);
const result = yield* processRequest(req);
yield* Effect.annotateCurrentSpan("response.status", result.status);
yield* Metric.observe(requestDuration, result.duration);
return result;
}).pipe(
Effect.withSpan("handle-request", {
attributes: {
"http.method": req.method,
"http.url": req.path,
},
}),
);
Best Practices
- Use structured logging - Add context via annotations
- Name spans descriptively - Use verb-noun format
- Add meaningful attributes - Enable debugging/analysis
- Track key metrics - Request count, latency, errors
- Use appropriate log levels - Debug in dev, Info in prod
Additional Resources
For comprehensive observability documentation, consult ${CLAUDE_PLUGIN_ROOT}/references/llms-full.txt.
Search for these sections:
- "Built-in Logging" for logging APIs
- "Metrics" for metric types
- "Tracing" for distributed tracing
Skills Info
Original Name:observabilityAuthor:andrueandersoncs
Download