<Input, State, A>(
metric: Metric.Metric<Input, State>,
f: (value: A) => Input
): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>
<State, A>(metric: Metric.Metric<NoInfer<A>, State>): <E, R>(
self: Effect<A, E, R>
) => Effect<A, E, R>
<A, E, R, Input, State>(
self: Effect<A, E, R>,
metric: Metric.Metric<Input, State>,
f: (value: A) => Input
): Effect<A, E, R>
<A, E, R, State>(
self: Effect<A, E, R>,
metric: Metric.Metric<NoInfer<A>, State>
): Effect<A, E, R>Updates the provided Metric every time the wrapped Effect succeeds with
a value.
Details
Also accepts an optional function which can be used to map the success value
of the Effect into a valid Input for the Metric.
Example (Counting successful results)
import { Effect, Metric } from "effect"
const successCounter = Metric.counter("successes").pipe(
Metric.withConstantInput(1)
)
const program = Effect.succeed(42).pipe(
Effect.trackSuccesses(successCounter)
)
Effect.runPromise(program).then(() =>
Effect.runPromise(Metric.value(successCounter)).then(console.log)
// Output: { count: 1, incremental: false }
)Example (Mapping successes before tracking)
import { Effect, Metric } from "effect"
// Track successful request sizes
const requestSizeGauge = Metric.gauge("request_size_bytes")
const program = Effect.succeed("Hello World!").pipe(
Effect.trackSuccesses(requestSizeGauge, (value: string) => value.length)
)
Effect.runPromise(program).then(() =>
Effect.runPromise(Metric.value(requestSizeGauge)).then(console.log)
// Output: { value: 12 }
)export const const trackSuccesses: {
<Input, State, A>(
metric: Metric.Metric<Input, State>,
f: (value: A) => Input
): <E, R>(
self: Effect<A, E, R>
) => Effect<A, E, R>
<State, A>(
metric: Metric.Metric<NoInfer<A>, State>
): <E, R>(
self: Effect<A, E, R>
) => Effect<A, E, R>
<A, E, R, Input, State>(
self: Effect<A, E, R>,
metric: Metric.Metric<Input, State>,
f: (value: A) => Input
): Effect<A, E, R>
<A, E, R, State>(
self: Effect<A, E, R>,
metric: Metric.Metric<NoInfer<A>, State>
): Effect<A, E, R>
}
Updates the provided Metric every time the wrapped Effect succeeds with
a value.
Details
Also accepts an optional function which can be used to map the success value
of the Effect into a valid Input for the Metric.
Example (Counting successful results)
import { Effect, Metric } from "effect"
const successCounter = Metric.counter("successes").pipe(
Metric.withConstantInput(1)
)
const program = Effect.succeed(42).pipe(
Effect.trackSuccesses(successCounter)
)
Effect.runPromise(program).then(() =>
Effect.runPromise(Metric.value(successCounter)).then(console.log)
// Output: { count: 1, incremental: false }
)
Example (Mapping successes before tracking)
import { Effect, Metric } from "effect"
// Track successful request sizes
const requestSizeGauge = Metric.gauge("request_size_bytes")
const program = Effect.succeed("Hello World!").pipe(
Effect.trackSuccesses(requestSizeGauge, (value: string) => value.length)
)
Effect.runPromise(program).then(() =>
Effect.runPromise(Metric.value(requestSizeGauge)).then(console.log)
// Output: { value: 12 }
)
trackSuccesses: {
<function (type parameter) Input in <Input, State, A>(metric: Metric.Metric<Input, State>, f: (value: A) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>Input, function (type parameter) State in <Input, State, A>(metric: Metric.Metric<Input, State>, f: (value: A) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>State, function (type parameter) A in <Input, State, A>(metric: Metric.Metric<Input, State>, f: (value: A) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>A>(
metric: Metric.Metric<Input, State>(parameter) metric: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
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; <…;
}
metric: import MetricMetric.interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <Input, State, A>(metric: Metric.Metric<Input, State>, f: (value: A) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>Input, function (type parameter) State in <Input, State, A>(metric: Metric.Metric<Input, State>, f: (value: A) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>State>,
f: (value: A) => Inputf: (value: Avalue: function (type parameter) A in <Input, State, A>(metric: Metric.Metric<Input, State>, f: (value: A) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>A) => function (type parameter) Input in <Input, State, A>(metric: Metric.Metric<Input, State>, f: (value: A) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>Input
): <function (type parameter) E in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>E, function (type parameter) R in <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: interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <Input, State, A>(metric: Metric.Metric<Input, State>, f: (value: A) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>A, function (type parameter) E in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>E, function (type parameter) R in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>R>) => interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <Input, State, A>(metric: Metric.Metric<Input, State>, f: (value: A) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>A, function (type parameter) E in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>E, function (type parameter) R in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>R>
<function (type parameter) State in <State, A>(metric: Metric.Metric<NoInfer<A>, State>): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>State, function (type parameter) A in <State, A>(metric: Metric.Metric<NoInfer<A>, State>): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>A>(
metric: Metric.Metric<NoInfer<A>, State>(parameter) metric: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
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; <…;
}
metric: import MetricMetric.interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<type NoInfer<A> = [A][A extends any ? 0 : never]Prevents TypeScript from inferring a type parameter from a specific
position.
When to use
Use when a function parameter must match an inferred type without becoming
an inference source.
Details
The parameter using NoInfer must still match the inferred type.
Example (Controlling inference)
import type { Types } from "effect"
declare function withDefault<T>(value: T, fallback: Types.NoInfer<T>): T
// T is inferred as "a" | "b" from the first argument only
const result = withDefault<"a" | "b">("a", "b")
NoInfer<function (type parameter) A in <State, A>(metric: Metric.Metric<NoInfer<A>, State>): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>A>, function (type parameter) State in <State, A>(metric: Metric.Metric<NoInfer<A>, State>): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>State>
): <function (type parameter) E in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>E, function (type parameter) R in <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: interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <State, A>(metric: Metric.Metric<NoInfer<A>, State>): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>A, function (type parameter) E in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>E, function (type parameter) R in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>R>) => interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <State, A>(metric: Metric.Metric<NoInfer<A>, State>): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>A, function (type parameter) E in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>E, function (type parameter) R in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>R>
<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>E, function (type parameter) R in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>R, function (type parameter) Input in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>Input, function (type parameter) State in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>State>(
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: interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>E, function (type parameter) R in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>R>,
metric: Metric.Metric<Input, State>(parameter) metric: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
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; <…;
}
metric: import MetricMetric.interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>Input, function (type parameter) State in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>State>,
f: (value: A) => Inputf: (value: Avalue: function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>A) => function (type parameter) Input in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>Input
): interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>E, function (type parameter) R in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (value: A) => Input): Effect<A, E, R>R>
<function (type parameter) A in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<NoInfer<A>, State>): Effect<A, E, R>A, function (type parameter) E in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<NoInfer<A>, State>): Effect<A, E, R>E, function (type parameter) R in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<NoInfer<A>, State>): Effect<A, E, R>R, function (type parameter) State in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<NoInfer<A>, State>): Effect<A, E, R>State>(
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: interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<NoInfer<A>, State>): Effect<A, E, R>A, function (type parameter) E in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<NoInfer<A>, State>): Effect<A, E, R>E, function (type parameter) R in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<NoInfer<A>, State>): Effect<A, E, R>R>,
metric: Metric.Metric<NoInfer<A>, State>(parameter) metric: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
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; <…;
}
metric: import MetricMetric.interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<type NoInfer<A> = [A][A extends any ? 0 : never]Prevents TypeScript from inferring a type parameter from a specific
position.
When to use
Use when a function parameter must match an inferred type without becoming
an inference source.
Details
The parameter using NoInfer must still match the inferred type.
Example (Controlling inference)
import type { Types } from "effect"
declare function withDefault<T>(value: T, fallback: Types.NoInfer<T>): T
// T is inferred as "a" | "b" from the first argument only
const result = withDefault<"a" | "b">("a", "b")
NoInfer<function (type parameter) A in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<NoInfer<A>, State>): Effect<A, E, R>A>, function (type parameter) State in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<NoInfer<A>, State>): Effect<A, E, R>State>
): interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<NoInfer<A>, State>): Effect<A, E, R>A, function (type parameter) E in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<NoInfer<A>, State>): Effect<A, E, R>E, function (type parameter) R in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<NoInfer<A>, State>): Effect<A, E, R>R>
} = dual<(...args: Array<any>) => any, <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined) => Effect<A, E, R>>(isDataFirst: (args: IArguments) => boolean, body: <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined) => Effect<A, E, R>): ((...args: Array<any>) => any) & (<A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined) => Effect<A, E, R>) (+1 overload)Creates a function that can be called in data-first style or data-last
(pipe-friendly) style.
When to use
Use to expose one implementation through both direct and pipe-friendly
call styles.
Details
Pass either the arity of the uncurried function or a predicate that decides
whether the current call is data-first. Arity is the common case. Use a
predicate when optional arguments make arity ambiguous.
Example (Selecting data-first or data-last style by arity)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(2, (self, that) => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Defining overloads with call signatures)
import { Function, pipe } from "effect"
const sum: {
(that: number): (self: number) => number
(self: number, that: number): number
} = Function.dual(2, (self: number, that: number): number => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Selecting data-first or data-last style with a predicate)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(
(args) => args.length === 2,
(self, that) => self + that
)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
dual(
(args: IArgumentsargs) => const isEffect: (
u: unknown
) => u is Effect<any, any, any>
Checks whether a value is an Effect.
Example (Checking whether a value is an Effect)
import { Effect } from "effect"
console.log(Effect.isEffect(Effect.succeed(1))) // true
console.log(Effect.isEffect("hello")) // false
isEffect(args: IArgumentsargs[0]),
<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>E, function (type parameter) R in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>R, function (type parameter) Input in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>Input, function (type parameter) State in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>State>(
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: interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>E, function (type parameter) R in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>R>,
metric: Metric.Metric<Input, State>(parameter) metric: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
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; <…;
}
metric: import MetricMetric.interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>Input, function (type parameter) State in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>State>,
f: ((value: A) => Input) | undefinedf: ((value: Avalue: function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>A) => function (type parameter) Input in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>Input) | undefined
): interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>E, function (type parameter) R in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: ((value: A) => Input) | undefined): Effect<A, E, R>R> =>
const tap: {
<A, B, E2, R2>(
f: (a: NoInfer<A>) => Effect<B, E2, R2>
): <E, R>(
self: Effect<A, E, R>
) => Effect<A, E | E2, R | R2>
<B, E2, R2>(f: Effect<B, E2, R2>): <A, E, R>(
self: Effect<A, E, R>
) => Effect<A, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect<A, E, R>,
f: (a: NoInfer<A>) => Effect<B, E2, R2>
): Effect<A, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect<A, E, R>,
f: Effect<B, E2, R2>
): Effect<A, E | E2, R | R2>
}
tap(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, (value: NoInfer<A>value) => {
const const input: Input | NoInfer<A>input = f: ((value: A) => Input) | undefinedf === var undefinedundefined ? value: NoInfer<A>value : f: (value: A) => Inputf(value: NoInfer<A>value)
return import MetricMetric.const update: {
<Input>(input: Input): <State>(
self: Metric<Input, State>
) => Effect<void>
<Input, State>(
self: Metric<Input, State>,
input: Input
): Effect<void>
}
update(metric: Metric.Metric<Input, State>(parameter) metric: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
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; <…;
}
metric, const input: Input | NoInfer<A>input as any)
})
)