<A, E, R>(self: Effect<A, E, R>): Effect<A, E, R>Enables automatic collection of fiber runtime metrics for the provided Effect.
Details
When enabled, automatically tracks fiber lifecycle metrics including active fibers, started fibers, successful completions, and failures. These metrics provide valuable insights into the concurrency patterns and health of your Effect application.
Example (Enabling runtime metrics for an effect)
import { Console, Data, Effect, Layer, Metric } from "effect"
class RuntimeMetricsError extends Data.TaggedError("RuntimeMetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create a concurrent workload to demonstrate fiber metrics
const heavyWorkload = Effect.gen(function*() {
// Simulate concurrent operations
const tasks = Array.from({ length: 10 }, (_, i) =>
Effect.gen(function*() {
yield* Effect.sleep(`${100 + i * 50} millis`)
if (i % 4 === 0) {
// Simulate some failures
return yield* new RuntimeMetricsError({ operation: `task-${i}` })
}
return `Task ${i} completed`
}).pipe(
Effect.catchTag("RuntimeMetricsError", () =>
Effect.succeed(`Task ${i} failed`))
))
// Run tasks concurrently
const results = yield* Effect.all(tasks, { concurrency: 5 })
return results
})
// Enable runtime metrics collection for our workload
const workloadWithMetrics = Metric.enableRuntimeMetrics(heavyWorkload)
// Execute the workload
const results = yield* workloadWithMetrics
// After execution, we can inspect the runtime metrics
// The following metrics are automatically collected:
// - child_fibers_active: Current number of active child fibers (Gauge)
// - child_fibers_started: Total child fibers started (Counter, incremental)
// - child_fiber_successes: Total successful child fibers (Counter, incremental)
// - child_fiber_failures: Total failed child fibers (Counter, incremental)
yield* Console.log(`Workload completed with ${results.length} results`)
// Get all metrics including the runtime metrics
const allMetrics = yield* Metric.snapshot
const runtimeMetrics = allMetrics.filter((m) =>
m.id.startsWith("child_fiber") || m.id.includes("fiber")
)
yield* Console.log("Runtime Metrics:")
for (const metric of runtimeMetrics) {
yield* Console.log(` ${metric.id}: ${JSON.stringify(metric.state)}`)
}
return results
})
// Alternative: Use the layer version for broader application coverage
const BaseAppLayer = Layer.empty // Your base application layers
const AppLayerWithMetrics = BaseAppLayer.pipe(
Layer.provide(Metric.enableRuntimeMetricsLayer)
)
const programWithLayer = program.pipe(
Effect.provide(AppLayerWithMetrics)
)export const const enableRuntimeMetrics: <A, E, R>(
self: Effect<A, E, R>
) => Effect<A, E, R>
Enables automatic collection of fiber runtime metrics for the provided Effect.
Details
When enabled, automatically tracks fiber lifecycle metrics including active fibers,
started fibers, successful completions, and failures. These metrics provide valuable
insights into the concurrency patterns and health of your Effect application.
Example (Enabling runtime metrics for an effect)
import { Console, Data, Effect, Layer, Metric } from "effect"
class RuntimeMetricsError extends Data.TaggedError("RuntimeMetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create a concurrent workload to demonstrate fiber metrics
const heavyWorkload = Effect.gen(function*() {
// Simulate concurrent operations
const tasks = Array.from({ length: 10 }, (_, i) =>
Effect.gen(function*() {
yield* Effect.sleep(`${100 + i * 50} millis`)
if (i % 4 === 0) {
// Simulate some failures
return yield* new RuntimeMetricsError({ operation: `task-${i}` })
}
return `Task ${i} completed`
}).pipe(
Effect.catchTag("RuntimeMetricsError", () =>
Effect.succeed(`Task ${i} failed`))
))
// Run tasks concurrently
const results = yield* Effect.all(tasks, { concurrency: 5 })
return results
})
// Enable runtime metrics collection for our workload
const workloadWithMetrics = Metric.enableRuntimeMetrics(heavyWorkload)
// Execute the workload
const results = yield* workloadWithMetrics
// After execution, we can inspect the runtime metrics
// The following metrics are automatically collected:
// - child_fibers_active: Current number of active child fibers (Gauge)
// - child_fibers_started: Total child fibers started (Counter, incremental)
// - child_fiber_successes: Total successful child fibers (Counter, incremental)
// - child_fiber_failures: Total failed child fibers (Counter, incremental)
yield* Console.log(`Workload completed with ${results.length} results`)
// Get all metrics including the runtime metrics
const allMetrics = yield* Metric.snapshot
const runtimeMetrics = allMetrics.filter((m) =>
m.id.startsWith("child_fiber") || m.id.includes("fiber")
)
yield* Console.log("Runtime Metrics:")
for (const metric of runtimeMetrics) {
yield* Console.log(` ${metric.id}: ${JSON.stringify(metric.state)}`)
}
return results
})
// Alternative: Use the layer version for broader application coverage
const BaseAppLayer = Layer.empty // Your base application layers
const AppLayerWithMetrics = BaseAppLayer.pipe(
Layer.provide(Metric.enableRuntimeMetricsLayer)
)
const programWithLayer = program.pipe(
Effect.provide(AppLayerWithMetrics)
)
enableRuntimeMetrics: <function (type parameter) A in <A, E, R>(self: Effect<A, E, R>): Effect<A, E, R>A, function (type parameter) E in <A, E, R>(self: Effect<A, E, R>): Effect<A, E, R>E, function (type parameter) R in <A, E, R>(self: Effect<A, E, R>): Effect<A, E, R>R>(self: Effect<A, E, R>(parameter) self: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
self: import EffectEffect<function (type parameter) A in <A, E, R>(self: Effect<A, E, R>): Effect<A, E, R>A, function (type parameter) E in <A, E, R>(self: Effect<A, E, R>): Effect<A, E, R>E, function (type parameter) R in <A, E, R>(self: Effect<A, E, R>): Effect<A, E, R>R>) => import EffectEffect<function (type parameter) A in <A, E, R>(self: Effect<A, E, R>): Effect<A, E, R>A, function (type parameter) E in <A, E, R>(self: Effect<A, E, R>): Effect<A, E, R>E, function (type parameter) R in <A, E, R>(self: Effect<A, E, R>): Effect<A, E, R>R> = import InternalEffectInternalEffect.const provideService: {
<I, S>(service: Context.Key<I, S>): {
(implementation: S): <A, E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<A, E, Exclude<R, I>>
<A, E, R>(
self: Effect.Effect<A, E, R>,
implementation: S
): Effect.Effect<A, E, Exclude<R, I>>
}
<I, S>(
key: Context.Key<I, S>,
implementation: S
): <A, E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<A, E, Exclude<R, I>>
<A, E, R, I, S>(
self: Effect.Effect<A, E, R>,
service: Context.Key<I, S>,
implementation: S
): Effect.Effect<A, E, Exclude<R, I>>
}
provideService(
const FiberRuntimeMetrics: Context.Reference<
FiberRuntimeMetricsService | undefined
>
const FiberRuntimeMetrics: {
defaultValue: () => Shape;
of: (this: void, self: FiberRuntimeMetricsService | undefined) => FiberRuntimeMetricsService | undefined;
context: (self: FiberRuntimeMetricsService | undefined) => Context.Context<never>;
use: (f: (service: FiberRuntimeMetricsService | undefined) => Effect<A, E, R>) => Effect<A, E, R>;
useSync: (f: (service: FiberRuntimeMetricsService | undefined) => A) => Effect<A, never, never>;
Identifier: Identifier;
Service: Shape;
key: string;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
Context reference for the optional service that records fiber runtime
metrics.
When to use
Use to provide or inspect the service that receives fiber start and end
notifications for automatic runtime metrics.
Details
When provided, the runtime can notify the service about child-fiber start and
end events. When the reference is undefined, automatic fiber runtime metric
collection is disabled.
Example (Accessing the fiber runtime metrics service)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Access the fiber runtime metrics service
const metricsService = yield* Metric.FiberRuntimeMetrics
if (metricsService) {
console.log("Runtime metrics are enabled")
} else {
console.log("Runtime metrics are disabled")
}
// Enable runtime metrics for the application
const enabledLayer = Metric.enableRuntimeMetricsLayer
return yield* Effect.gen(function*() {
// Create some concurrent fibers to see metrics in action
yield* Effect.all([
Effect.sleep("100 millis"),
Effect.sleep("200 millis"),
Effect.sleep("300 millis")
], { concurrency: "unbounded" })
// Create test metrics to demonstrate the service
const testCounter = Metric.counter("test_counter")
yield* Metric.update(testCounter, 5)
const counterValue = yield* Metric.value(testCounter)
return { counterValue, metricsEnabled: true }
}).pipe(Effect.provide(enabledLayer))
})
FiberRuntimeMetrics,
const FiberRuntimeMetricsImpl: FiberRuntimeMetricsServiceconst FiberRuntimeMetricsImpl: {
recordFiberStart: (context: Context.Context<never>) => void;
recordFiberEnd: (context: Context.Context<never>, exit: Exit<unknown, unknown>) => void;
}
Default implementation of the fiber runtime metrics service.
Example (Accessing the default fiber metrics implementation)
import { Data, Effect, Layer, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Use the default metrics implementation
const metrics = Metric.FiberRuntimeMetricsImpl
console.log("Metrics implementation:", metrics)
// Enable runtime metrics using the default implementation
const layer = Layer.succeed(Metric.FiberRuntimeMetrics)(metrics)
return yield* Effect.gen(function*() {
// Run some Effects to trigger metric collection
yield* Effect.forkChild(Effect.sleep("50 millis"))
yield* Effect.forkChild(Effect.sleep("100 millis"))
// Wait a bit and check the metrics
yield* Effect.sleep("200 millis")
// Create test metrics to demonstrate the implementation
const testCounter = Metric.counter("test_counter")
const testGauge = Metric.gauge("test_gauge")
yield* Metric.update(testCounter, 3)
yield* Metric.update(testGauge, 42)
const counterValue = yield* Metric.value(testCounter)
const gaugeValue = yield* Metric.value(testGauge)
return { counter: counterValue, gauge: gaugeValue }
}).pipe(Effect.provide(layer))
})
FiberRuntimeMetricsImpl
)