Layer.Layer<never, never, never>Layer that enables automatic collection of fiber runtime metrics across an entire Effect application.
When to use
Use when you need runtime metrics collection for all Effects in the application context rather than wrapping individual Effects.
Example (Enabling runtime metrics with a layer)
import { Console, Data, Effect, Layer, Metric } from "effect"
class AppError extends Data.TaggedError("AppError")<{
readonly operation: string
}> {}
// Define your application logic
const userService = Effect.gen(function*() {
// Simulate user operations with concurrent processing
const fetchUser = (id: number) =>
Effect.gen(function*() {
yield* Effect.sleep(`${50 + id * 10} millis`)
if (id % 7 === 0) {
return yield* new AppError({ operation: `fetch-user-${id}` })
}
return { id, name: `User ${id}`, email: `user${id}@example.com` }
})
// Process multiple users concurrently (ignoring failures for demo)
const userIds = Array.from({ length: 10 }, (_, i) => i + 1)
const userTasks = userIds.map((id) =>
fetchUser(id).pipe(Effect.catchTag("AppError", () => Effect.succeed(null)))
)
const allUsers = yield* Effect.all(userTasks, { concurrency: 4 })
const successfulUsers = allUsers.filter((user) => user !== null)
return successfulUsers
})
const analyticsService = Effect.gen(function*() {
// Simulate analytics processing
const tasks = Array.from({ length: 8 }, (_, i) =>
Effect.gen(function*() {
yield* Effect.sleep(`${100 + i * 25} millis`)
return `Analytics task ${i} completed`
}))
return yield* Effect.all(tasks, { concurrency: 3 })
})
// Main application that uses multiple services
const application = Effect.gen(function*() {
yield* Console.log("Starting application with runtime metrics...")
// Run services concurrently
const [users, analytics] = yield* Effect.all([
userService,
analyticsService
], { concurrency: 2 })
yield* Console.log(
`Processed ${users.length} users and ${analytics.length} analytics tasks`
)
// Inspect the automatically collected runtime metrics
const metrics = yield* Metric.snapshot
const runtimeMetrics = metrics.filter((m) => m.id.startsWith("child_fiber"))
yield* Console.log("Runtime Metrics Collected:")
for (const metric of runtimeMetrics) {
yield* Console.log(` ${metric.id}: ${JSON.stringify(metric.state)}`)
}
return { users, analytics, metricsCount: runtimeMetrics.length }
})
// Create the base application layer
const AppLayer = Layer.empty // Add your application layers here (database, HTTP, etc.)
// Add runtime metrics layer at the end
const AppLayerWithMetrics = AppLayer.pipe(
Layer.provide(Metric.enableRuntimeMetricsLayer)
)
// Run the application with runtime metrics enabled
const program = application.pipe(
Effect.provide(AppLayerWithMetrics)
)
// Alternative: Provide runtime metrics directly to the application
const programWithDirectMetrics = application.pipe(
Effect.provide(Metric.enableRuntimeMetricsLayer)
)export const const enableRuntimeMetricsLayer: Layer.Layer<
never,
never,
never
>
const enableRuntimeMetricsLayer: {
build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<never>, never, never>;
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; <…;
}
Layer that enables automatic collection of fiber runtime metrics across
an entire Effect application.
When to use
Use when you need runtime metrics collection for all Effects in the
application context rather than wrapping individual Effects.
Example (Enabling runtime metrics with a layer)
import { Console, Data, Effect, Layer, Metric } from "effect"
class AppError extends Data.TaggedError("AppError")<{
readonly operation: string
}> {}
// Define your application logic
const userService = Effect.gen(function*() {
// Simulate user operations with concurrent processing
const fetchUser = (id: number) =>
Effect.gen(function*() {
yield* Effect.sleep(`${50 + id * 10} millis`)
if (id % 7 === 0) {
return yield* new AppError({ operation: `fetch-user-${id}` })
}
return { id, name: `User ${id}`, email: `user${id}@example.com` }
})
// Process multiple users concurrently (ignoring failures for demo)
const userIds = Array.from({ length: 10 }, (_, i) => i + 1)
const userTasks = userIds.map((id) =>
fetchUser(id).pipe(Effect.catchTag("AppError", () => Effect.succeed(null)))
)
const allUsers = yield* Effect.all(userTasks, { concurrency: 4 })
const successfulUsers = allUsers.filter((user) => user !== null)
return successfulUsers
})
const analyticsService = Effect.gen(function*() {
// Simulate analytics processing
const tasks = Array.from({ length: 8 }, (_, i) =>
Effect.gen(function*() {
yield* Effect.sleep(`${100 + i * 25} millis`)
return `Analytics task ${i} completed`
}))
return yield* Effect.all(tasks, { concurrency: 3 })
})
// Main application that uses multiple services
const application = Effect.gen(function*() {
yield* Console.log("Starting application with runtime metrics...")
// Run services concurrently
const [users, analytics] = yield* Effect.all([
userService,
analyticsService
], { concurrency: 2 })
yield* Console.log(
`Processed ${users.length} users and ${analytics.length} analytics tasks`
)
// Inspect the automatically collected runtime metrics
const metrics = yield* Metric.snapshot
const runtimeMetrics = metrics.filter((m) => m.id.startsWith("child_fiber"))
yield* Console.log("Runtime Metrics Collected:")
for (const metric of runtimeMetrics) {
yield* Console.log(` ${metric.id}: ${JSON.stringify(metric.state)}`)
}
return { users, analytics, metricsCount: runtimeMetrics.length }
})
// Create the base application layer
const AppLayer = Layer.empty // Add your application layers here (database, HTTP, etc.)
// Add runtime metrics layer at the end
const AppLayerWithMetrics = AppLayer.pipe(
Layer.provide(Metric.enableRuntimeMetricsLayer)
)
// Run the application with runtime metrics enabled
const program = application.pipe(
Effect.provide(AppLayerWithMetrics)
)
// Alternative: Provide runtime metrics directly to the application
const programWithDirectMetrics = application.pipe(
Effect.provide(Metric.enableRuntimeMetricsLayer)
)
enableRuntimeMetricsLayer = import LayerLayer.succeed(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)