Skip to content

Metrics in Effect

In complex and highly concurrent applications, managing various interconnected components can be quite challenging. Ensuring that everything runs smoothly and avoiding application downtime becomes crucial in such setups.

Now, let’s imagine we have a sophisticated infrastructure with numerous services. These services are replicated and distributed across our servers. However, we often lack insight into what’s happening across these services, including error rates, response times, and service uptime. This lack of visibility can make it challenging to identify and address issues effectively. This is where Effect Metrics comes into play; it allows us to capture and analyze various metrics, providing valuable data for later investigation.

Effect Metrics offers support for five different types of metrics:

MetricDescription
CounterCounters are used to track values that increase over time, such as request counts. They help us keep tabs on how many times a specific event or action has occurred.
GaugeGauges represent a single numerical value that can fluctuate up and down over time. They are often used to monitor metrics like memory usage, which can vary continuously.
HistogramHistograms are useful for tracking the distribution of observed values across different buckets. They are commonly used for metrics like request latencies, allowing us to understand how response times are distributed.
SummarySummaries provide insight into a sliding window of a time series and offer metrics for specific percentiles of the time series, often referred to as quantiles. This is particularly helpful for understanding latency-related metrics, such as request response times.
FrequencyFrequency metrics count the occurrences of distinct string values. They are useful when you want to keep track of how often different events or conditions are happening in your application.

In the world of metrics, a Counter is a metric that represents a single numerical value that can be both incremented and decremented over time. Think of it like a tally that keeps track of changes, such as the number of a particular type of request received by your application, whether it’s increasing or decreasing.

Unlike some other types of metrics (like gauges), where we’re interested in the value at a specific moment, with counters, we care about the cumulative value over time. This means it provides a running total of changes, which can go up and down, reflecting the dynamic nature of certain metrics.

Some typical use cases for counters include:

  • Request Counts: Monitoring the number of incoming requests to your server.
  • Completed Tasks: Keeping track of how many tasks or processes have been successfully completed.
  • Error Counts: Counting the occurrences of errors in your application.

To create a counter, you can use the Metric.counter constructor.

Example (Creating a Counter)

import {
import Metric
Metric
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const requestCount: Metric.Metric.Counter<number>
requestCount
=
import Metric
Metric
.
const counter: (name: string, options?: {
readonly description?: string | undefined;
readonly bigint?: false | undefined;
readonly incremental?: boolean | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Counter<number> (+1 overload)

Represents a Counter metric that tracks cumulative numerical values over time. Counters can be incremented and decremented and provide a running total of changes.

@paramname - The name of the counter metric.

@param

options - An optional configuration for the counter:

  • description - A description of the counter.
  • bigint - Indicates if the counter uses 'bigint' data type.
  • incremental - Set to 'true' for a counter that only increases. With this configuration, Effect ensures that non-incremental updates have no impact on the counter, making it exclusively suitable for counting upwards.

@example

import { Metric } from "effect"
const numberCounter = Metric.counter("count", {
description: "A number counter"
});
const bigintCounter = Metric.counter("count", {
description: "A bigint counter",
bigint: true
});

@since2.0.0

counter
("request_count", {
// Optional
description?: string | undefined
description
: "A counter for tracking requests"
})

Once created, the counter can accept an effect that returns a number, which will increment or decrement the counter.

Example (Using a Counter)

import {
import Metric
Metric
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const requestCount: Metric.Metric.Counter<number>
requestCount
=
import Metric
Metric
.
const counter: (name: string, options?: {
readonly description?: string | undefined;
readonly bigint?: false | undefined;
readonly incremental?: boolean | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Counter<number> (+1 overload)

Represents a Counter metric that tracks cumulative numerical values over time. Counters can be incremented and decremented and provide a running total of changes.

@paramname - The name of the counter metric.

@param

options - An optional configuration for the counter:

  • description - A description of the counter.
  • bigint - Indicates if the counter uses 'bigint' data type.
  • incremental - Set to 'true' for a counter that only increases. With this configuration, Effect ensures that non-incremental updates have no impact on the counter, making it exclusively suitable for counting upwards.

@example

import { Metric } from "effect"
const numberCounter = Metric.counter("count", {
description: "A number counter"
});
const bigintCounter = Metric.counter("count", {
description: "A bigint counter",
bigint: true
});

@since2.0.0

counter
("request_count")
const
const program: Effect.Effect<number, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<1, never, never>> | YieldWrap<Effect.Effect<2, never, never>> | YieldWrap<Effect.Effect<-4, never, never>> | YieldWrap<...>, number>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
// Increment the counter by 1
const
const a: 1
a
= yield*
const requestCount: Metric.Metric<in out Type, in In, out Out>.Counter
<1, never, never>(effect: Effect.Effect<1, never, never>) => Effect.Effect<1, never, never>
requestCount
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <1>(value: 1) => Effect.Effect<1, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(1))
// Increment the counter by 2
const
const b: 2
b
= yield*
const requestCount: Metric.Metric<in out Type, in In, out Out>.Counter
<2, never, never>(effect: Effect.Effect<2, never, never>) => Effect.Effect<2, never, never>
requestCount
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <2>(value: 2) => Effect.Effect<2, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(2))
// Decrement the counter by 4
const
const c: -4
c
= yield*
const requestCount: Metric.Metric<in out Type, in In, out Out>.Counter
<-4, never, never>(effect: Effect.Effect<-4, never, never>) => Effect.Effect<-4, never, never>
requestCount
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <-4>(value: -4) => Effect.Effect<-4, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(-4))
// Get the current state of the counter
const
const state: MetricState.Counter<number>
state
= yield*
import Metric
Metric
.
const value: <MetricKeyType<in In, out Out>.Counter<number>, number, MetricState<in A>.Counter<number>>(self: Metric.Metric<MetricKeyType.Counter<number>, number, MetricState.Counter<number>>) => Effect.Effect<...>

Retrieves a snapshot of the value of the metric at this moment in time.

@since2.0.0

value
(
const requestCount: Metric.Metric.Counter<number>
requestCount
)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
const state: MetricState.Counter<number>
state
)
return
const a: 1
a
*
const b: 2
b
*
const c: -4
c
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <number, never>(effect: Effect.Effect<number, never, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<number>

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
(
const program: Effect.Effect<number, never, never>
program
).
Promise<number>.then<void, never>(onfulfilled?: ((value: number) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<...>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
)
/*
Output:
CounterState {
count: -1,
...
}
-8
*/

You can specify whether the counter tracks a number or bigint.

import {
import Metric
Metric
} from "effect"
const
const numberCounter: Metric.Metric.Counter<number>
numberCounter
=
import Metric
Metric
.
const counter: (name: string, options?: {
readonly description?: string | undefined;
readonly bigint?: false | undefined;
readonly incremental?: boolean | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Counter<number> (+1 overload)

Represents a Counter metric that tracks cumulative numerical values over time. Counters can be incremented and decremented and provide a running total of changes.

@paramname - The name of the counter metric.

@param

options - An optional configuration for the counter:

  • description - A description of the counter.
  • bigint - Indicates if the counter uses 'bigint' data type.
  • incremental - Set to 'true' for a counter that only increases. With this configuration, Effect ensures that non-incremental updates have no impact on the counter, making it exclusively suitable for counting upwards.

@example

import { Metric } from "effect"
const numberCounter = Metric.counter("count", {
description: "A number counter"
});
const bigintCounter = Metric.counter("count", {
description: "A bigint counter",
bigint: true
});

@since2.0.0

counter
("request_count", {
description?: string | undefined
description
: "A counter for tracking requests"
// bigint: false // default
})
const
const bigintCounter: Metric.Metric.Counter<bigint>
bigintCounter
=
import Metric
Metric
.
const counter: (name: string, options: {
readonly description?: string | undefined;
readonly bigint: true;
readonly incremental?: boolean | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Counter<bigint> (+1 overload)

Represents a Counter metric that tracks cumulative numerical values over time. Counters can be incremented and decremented and provide a running total of changes.

@paramname - The name of the counter metric.

@param

options - An optional configuration for the counter:

  • description - A description of the counter.
  • bigint - Indicates if the counter uses 'bigint' data type.
  • incremental - Set to 'true' for a counter that only increases. With this configuration, Effect ensures that non-incremental updates have no impact on the counter, making it exclusively suitable for counting upwards.

@example

import { Metric } from "effect"
const numberCounter = Metric.counter("count", {
description: "A number counter"
});
const bigintCounter = Metric.counter("count", {
description: "A bigint counter",
bigint: true
});

@since2.0.0

counter
("error_count", {
description?: string | undefined
description
: "A counter for tracking errors",
bigint: true
bigint
: true
})

If you need a counter that only increments, you can use the incremental: true option.

Example (Using an Increment-Only Counter)

import {
import Metric
Metric
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const incrementalCounter: Metric.Metric.Counter<number>
incrementalCounter
=
import Metric
Metric
.
const counter: (name: string, options?: {
readonly description?: string | undefined;
readonly bigint?: false | undefined;
readonly incremental?: boolean | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Counter<number> (+1 overload)

Represents a Counter metric that tracks cumulative numerical values over time. Counters can be incremented and decremented and provide a running total of changes.

@paramname - The name of the counter metric.

@param

options - An optional configuration for the counter:

  • description - A description of the counter.
  • bigint - Indicates if the counter uses 'bigint' data type.
  • incremental - Set to 'true' for a counter that only increases. With this configuration, Effect ensures that non-incremental updates have no impact on the counter, making it exclusively suitable for counting upwards.

@example

import { Metric } from "effect"
const numberCounter = Metric.counter("count", {
description: "A number counter"
});
const bigintCounter = Metric.counter("count", {
description: "A bigint counter",
bigint: true
});

@since2.0.0

counter
("count", {
description?: string | undefined
description
: "a counter that only increases its value",
incremental?: boolean | undefined
incremental
: true
})
const
const program: Effect.Effect<number, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<1, never, never>> | YieldWrap<Effect.Effect<2, never, never>> | YieldWrap<Effect.Effect<-4, never, never>> | YieldWrap<...>, number>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const a: 1
a
= yield*
const incrementalCounter: Metric.Metric<in out Type, in In, out Out>.Counter
<1, never, never>(effect: Effect.Effect<1, never, never>) => Effect.Effect<1, never, never>
incrementalCounter
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <1>(value: 1) => Effect.Effect<1, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(1))
const
const b: 2
b
= yield*
const incrementalCounter: Metric.Metric<in out Type, in In, out Out>.Counter
<2, never, never>(effect: Effect.Effect<2, never, never>) => Effect.Effect<2, never, never>
incrementalCounter
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <2>(value: 2) => Effect.Effect<2, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(2))
// This will have no effect on the counter
const
const c: -4
c
= yield*
const incrementalCounter: Metric.Metric<in out Type, in In, out Out>.Counter
<-4, never, never>(effect: Effect.Effect<-4, never, never>) => Effect.Effect<-4, never, never>
incrementalCounter
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <-4>(value: -4) => Effect.Effect<-4, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(-4))
const
const state: MetricState.Counter<number>
state
= yield*
import Metric
Metric
.
const value: <MetricKeyType<in In, out Out>.Counter<number>, number, MetricState<in A>.Counter<number>>(self: Metric.Metric<MetricKeyType.Counter<number>, number, MetricState.Counter<number>>) => Effect.Effect<...>

Retrieves a snapshot of the value of the metric at this moment in time.

@since2.0.0

value
(
const incrementalCounter: Metric.Metric.Counter<number>
incrementalCounter
)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
const state: MetricState.Counter<number>
state
)
return
const a: 1
a
*
const b: 2
b
*
const c: -4
c
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <number, never>(effect: Effect.Effect<number, never, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<number>

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
(
const program: Effect.Effect<number, never, never>
program
).
Promise<number>.then<void, never>(onfulfilled?: ((value: number) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<...>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
)
/*
Output:
CounterState {
count: 3,
...
}
-8
*/

In this configuration, the counter only accepts positive values. Any attempts to decrement will have no effect, ensuring the counter strictly counts upwards.

You can configure a counter to always increment by a fixed value each time it is invoked.

Example (Constant Input)

import {
import Metric
Metric
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const taskCount: Metric.Metric<MetricKeyType.Counter<number>, unknown, MetricState.Counter<number>>
taskCount
=
import Metric
Metric
.
const counter: (name: string, options?: {
readonly description?: string | undefined;
readonly bigint?: false | undefined;
readonly incremental?: boolean | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Counter<number> (+1 overload)

Represents a Counter metric that tracks cumulative numerical values over time. Counters can be incremented and decremented and provide a running total of changes.

@paramname - The name of the counter metric.

@param

options - An optional configuration for the counter:

  • description - A description of the counter.
  • bigint - Indicates if the counter uses 'bigint' data type.
  • incremental - Set to 'true' for a counter that only increases. With this configuration, Effect ensures that non-incremental updates have no impact on the counter, making it exclusively suitable for counting upwards.

@example

import { Metric } from "effect"
const numberCounter = Metric.counter("count", {
description: "A number counter"
});
const bigintCounter = Metric.counter("count", {
description: "A bigint counter",
bigint: true
});

@since2.0.0

counter
("task_count").
Pipeable.pipe<Metric.Metric<in out Type, in In, out Out>.Counter<number>, Metric.Metric<MetricKeyType<in In, out Out>.Counter<number>, unknown, MetricState<in A>.Counter<number>>>(this: Metric.Metric.Counter<...>, ab: (_: Metric.Metric.Counter<number>) => Metric.Metric<...>): Metric.Metric<...> (+21 overloads)
pipe
(
import Metric
Metric
.
const withConstantInput: <number>(input: number) => <Type, Out>(self: Metric.Metric<Type, number, Out>) => Metric.Metric<Type, unknown, Out> (+1 overload)

Returns a new metric that is powered by this one, but which accepts updates of any type, and translates them to updates with the specified constant update value.

@since2.0.0

withConstantInput
(1) // Automatically increments by 1
)
const
const task1: Effect.Effect<number, never, never>
task1
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(1).
Pipeable.pipe<Effect.Effect<number, never, never>, Effect.Effect<number, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const delay: (duration: DurationInput) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Returns an effect that is delayed from this effect by the specified Duration.

@since2.0.0

delay
("100 millis"))
const
const task2: Effect.Effect<number, never, never>
task2
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(2).
Pipeable.pipe<Effect.Effect<number, never, never>, Effect.Effect<number, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const delay: (duration: DurationInput) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Returns an effect that is delayed from this effect by the specified Duration.

@since2.0.0

delay
("200 millis"))
const
const task3: Effect.Effect<number, never, never>
task3
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(-4).
Pipeable.pipe<Effect.Effect<number, never, never>, Effect.Effect<number, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const delay: (duration: DurationInput) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Returns an effect that is delayed from this effect by the specified Duration.

@since2.0.0

delay
("300 millis"))
const
const program: Effect.Effect<number, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<MetricState<in A>.Counter<number>, never, never>>, number>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const a: number
a
= yield*
const taskCount: Metric.Metric
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
taskCount
(
const task1: Effect.Effect<number, never, never>
task1
)
const
const b: number
b
= yield*
const taskCount: Metric.Metric
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
taskCount
(
const task2: Effect.Effect<number, never, never>
task2
)
const
const c: number
c
= yield*
const taskCount: Metric.Metric
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
taskCount
(
const task3: Effect.Effect<number, never, never>
task3
)
const
const state: MetricState.Counter<number>
state
= yield*
import Metric
Metric
.
const value: <MetricKeyType<in In, out Out>.Counter<number>, unknown, MetricState<in A>.Counter<number>>(self: Metric.Metric<MetricKeyType.Counter<number>, unknown, MetricState.Counter<number>>) => Effect.Effect<...>

Retrieves a snapshot of the value of the metric at this moment in time.

@since2.0.0

value
(
const taskCount: Metric.Metric<MetricKeyType.Counter<number>, unknown, MetricState.Counter<number>>
taskCount
)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
const state: MetricState.Counter<number>
state
)
return
const a: number
a
*
const b: number
b
*
const c: number
c
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <number, never>(effect: Effect.Effect<number, never, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<number>

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
(
const program: Effect.Effect<number, never, never>
program
).
Promise<number>.then<void, never>(onfulfilled?: ((value: number) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<...>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
)
/*
Output:
CounterState {
count: 3,
...
}
-8
*/

In the world of metrics, a Gauge is a metric that represents a single numerical value that can be set or adjusted. Think of it as a dynamic variable that can change over time. One common use case for a gauge is to monitor something like the current memory usage of your application.

Unlike counters, where we’re interested in cumulative values over time, with gauges, our focus is on the current value at a specific point in time.

Gauges are the best choice when you want to monitor values that can both increase and decrease, and you’re not interested in tracking their rates of change. In other words, gauges help us measure things that have a specific value at a particular moment.

Some typical use cases for gauges include:

  • Memory Usage: Keeping an eye on how much memory your application is using right now.
  • Queue Size: Monitoring the current size of a queue where tasks are waiting to be processed.
  • In-Progress Request Counts: Tracking the number of requests currently being handled by your server.
  • Temperature: Measuring the current temperature, which can fluctuate up and down.

To create a gauge, you can use the Metric.gauge constructor.

Example (Creating a Gauge)

import {
import Metric
Metric
} from "effect"
const
const memory: Metric.Metric.Gauge<number>
memory
=
import Metric
Metric
.
const gauge: (name: string, options?: {
readonly description?: string | undefined;
readonly bigint?: false | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Gauge<number> (+1 overload)

Represents a Gauge metric that tracks and reports a single numerical value at a specific moment. Gauges are suitable for metrics that represent instantaneous values, such as memory usage or CPU load.

@paramname - The name of the gauge metric.

@param

options - An optional configuration for the gauge:

  • description - A description of the gauge metric.
  • bigint - Indicates if the counter uses 'bigint' data type.

@example

import { Metric } from "effect"
const numberGauge = Metric.gauge("memory_usage", {
description: "A gauge for memory usage"
});
const bigintGauge = Metric.gauge("cpu_load", {
description: "A gauge for CPU load",
bigint: true
});

@since2.0.0

gauge
("memory_usage", {
// Optional
description?: string | undefined
description
: "A gauge for memory usage"
})

Once created, a gauge can be updated by passing an effect that produces the value you want to set for the gauge.

Example (Using a Gauge)

import {
import Metric
Metric
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Random
Random
} from "effect"
// Create a gauge to track temperature
const
const temperature: Metric.Metric.Gauge<number>
temperature
=
import Metric
Metric
.
const gauge: (name: string, options?: {
readonly description?: string | undefined;
readonly bigint?: false | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Gauge<number> (+1 overload)

Represents a Gauge metric that tracks and reports a single numerical value at a specific moment. Gauges are suitable for metrics that represent instantaneous values, such as memory usage or CPU load.

@paramname - The name of the gauge metric.

@param

options - An optional configuration for the gauge:

  • description - A description of the gauge metric.
  • bigint - Indicates if the counter uses 'bigint' data type.

@example

import { Metric } from "effect"
const numberGauge = Metric.gauge("memory_usage", {
description: "A gauge for memory usage"
});
const bigintGauge = Metric.gauge("cpu_load", {
description: "A gauge for CPU load",
bigint: true
});

@since2.0.0

gauge
("temperature")
// Simulate fetching a random temperature
const
const getTemperature: Effect.Effect<number, never, never>
getTemperature
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<number, never, never>>, number>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<number, never, never>>, number, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
// Get a random temperature between -10 and 10
const
const t: number
t
= yield*
import Random
Random
.
const nextIntBetween: (min: number, max: number) => Effect.Effect<number>

Returns the next integer value in the specified range from the pseudo-random number generator.

@since2.0.0

nextIntBetween
(-10, 10)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(`new temperature: ${
const t: number
t
}`)
return
const t: number
t
})
// Program that updates the gauge multiple times
const
const program: Effect.Effect<number[], never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<MetricState<in A>.Gauge<number>, never, never>>, number[]>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const series: number[]
series
:
interface Array<T>
Array
<number> = []
// Update the gauge with new temperature readings
const series: number[]
series
.
Array<number>.push(...items: number[]): number

Appends new elements to the end of an array, and returns the new length of the array.

@paramitems New elements to add to the array.

push
(yield*
const temperature: Metric.Metric<in out Type, in In, out Out>.Gauge
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
temperature
(
const getTemperature: Effect.Effect<number, never, never>
getTemperature
))
const series: number[]
series
.
Array<number>.push(...items: number[]): number

Appends new elements to the end of an array, and returns the new length of the array.

@paramitems New elements to add to the array.

push
(yield*
const temperature: Metric.Metric<in out Type, in In, out Out>.Gauge
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
temperature
(
const getTemperature: Effect.Effect<number, never, never>
getTemperature
))
const series: number[]
series
.
Array<number>.push(...items: number[]): number

Appends new elements to the end of an array, and returns the new length of the array.

@paramitems New elements to add to the array.

push
(yield*
const temperature: Metric.Metric<in out Type, in In, out Out>.Gauge
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
temperature
(
const getTemperature: Effect.Effect<number, never, never>
getTemperature
))
// Retrieve the current state of the gauge
const
const state: MetricState.Gauge<number>
state
= yield*
import Metric
Metric
.
const value: <MetricKeyType<in In, out Out>.Gauge<number>, number, MetricState<in A>.Gauge<number>>(self: Metric.Metric<MetricKeyType.Gauge<number>, number, MetricState.Gauge<number>>) => Effect.Effect<...>

Retrieves a snapshot of the value of the metric at this moment in time.

@since2.0.0

value
(
const temperature: Metric.Metric.Gauge<number>
temperature
)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
const state: MetricState.Gauge<number>
state
)
return
const series: number[]
series
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <number[], never>(effect: Effect.Effect<number[], never, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<number[]>

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
(
const program: Effect.Effect<number[], never, never>
program
).
Promise<number[]>.then<void, never>(onfulfilled?: ((value: number[]) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<...>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
)
/*
Example Output:
new temperature: 9
new temperature: -9
new temperature: 2
GaugeState {
value: 2, // the most recent value set in the gauge
...
}
[ 9, -9, 2 ]
*/

You can specify whether the gauge tracks a number or bigint.

import {
import Metric
Metric
} from "effect"
const
const numberGauge: Metric.Metric.Gauge<number>
numberGauge
=
import Metric
Metric
.
const gauge: (name: string, options?: {
readonly description?: string | undefined;
readonly bigint?: false | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Gauge<number> (+1 overload)

Represents a Gauge metric that tracks and reports a single numerical value at a specific moment. Gauges are suitable for metrics that represent instantaneous values, such as memory usage or CPU load.

@paramname - The name of the gauge metric.

@param

options - An optional configuration for the gauge:

  • description - A description of the gauge metric.
  • bigint - Indicates if the counter uses 'bigint' data type.

@example

import { Metric } from "effect"
const numberGauge = Metric.gauge("memory_usage", {
description: "A gauge for memory usage"
});
const bigintGauge = Metric.gauge("cpu_load", {
description: "A gauge for CPU load",
bigint: true
});

@since2.0.0

gauge
("memory_usage", {
description?: string | undefined
description
: "A gauge for memory usage"
// bigint: false // default
})
const
const bigintGauge: Metric.Metric.Gauge<bigint>
bigintGauge
=
import Metric
Metric
.
const gauge: (name: string, options: {
readonly description?: string | undefined;
readonly bigint: true;
}) => Metric.Metric<in out Type, in In, out Out>.Gauge<bigint> (+1 overload)

Represents a Gauge metric that tracks and reports a single numerical value at a specific moment. Gauges are suitable for metrics that represent instantaneous values, such as memory usage or CPU load.

@paramname - The name of the gauge metric.

@param

options - An optional configuration for the gauge:

  • description - A description of the gauge metric.
  • bigint - Indicates if the counter uses 'bigint' data type.

@example

import { Metric } from "effect"
const numberGauge = Metric.gauge("memory_usage", {
description: "A gauge for memory usage"
});
const bigintGauge = Metric.gauge("cpu_load", {
description: "A gauge for CPU load",
bigint: true
});

@since2.0.0

gauge
("cpu_load", {
description?: string | undefined
description
: "A gauge for CPU load",
bigint: true
bigint
: true
})

A Histogram is a metric used to analyze how numerical values are distributed over time. Instead of focusing on individual data points, a histogram groups values into predefined ranges, called buckets, and tracks how many values fall into each range.

When a value is recorded, it gets assigned to one of the histogram’s buckets based on its range. Each bucket has an upper boundary, and the count for that bucket is increased if the value is less than or equal to its boundary. Once recorded, the individual value is discarded, and the focus shifts to how many values have fallen into each bucket.

Histograms also track:

  • Total Count: The number of values that have been observed.
  • Sum: The sum of all the observed values.
  • Min: The smallest observed value.
  • Max: The largest observed value.

Histograms are especially useful for calculating percentiles, which can help you estimate specific points in a dataset by analyzing how many values are in each bucket.

This concept is inspired by Prometheus, a well-known monitoring and alerting toolkit.

Histograms are particularly useful in performance analysis and system monitoring. By examining how response times, latencies, or other metrics are distributed, you can gain valuable insights into your system’s behavior. This data helps you identify outliers, performance bottlenecks, or trends that may require optimization.

Common use cases for histograms include:

  • Percentile Estimation: Histograms allow you to approximate percentiles of observed values, like the 95th percentile of response times.
  • Known Ranges: If you can estimate the range of values in advance, histograms can organize the data into predefined buckets for better analysis.
  • Performance Metrics: Use histograms to track metrics like request latencies, memory usage, or throughput over time.
  • Aggregation: Histograms can be aggregated across multiple instances, making them ideal for distributed systems where you need to collect data from different sources.

Example (Histogram With Linear Buckets)

In this example, we define a histogram with linear buckets, where the values range from 0 to 100 in increments of 10. Additionally, we include a final bucket for values greater than 100, referred to as the “Infinity” bucket. This configuration is useful for tracking numeric values, like request latencies, within specific ranges.

The program generates random numbers between 1 and 120, records them in the histogram, and then prints the histogram’s state, showing the count of values that fall into each bucket.

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Metric
Metric
,
import MetricBoundaries
MetricBoundaries
,
import Random
Random
} from "effect"
// Define a histogram to track request latencies, with linear buckets
const
const latency: Metric.Metric<MetricKeyType.Histogram, number, MetricState.Histogram>
latency
=
import Metric
Metric
.
const histogram: (name: string, boundaries: MetricBoundaries.MetricBoundaries, description?: string) => Metric.Metric<MetricKeyType<in In, out Out>.Histogram, number, MetricState<in A>.Histogram>

Represents a Histogram metric that records observations in specified value boundaries. Histogram metrics are useful for measuring the distribution of values within a range.

@paramname - The name of the histogram metric.

@paramboundaries - The boundaries for defining the histogram's value ranges.

@paramdescription - A description of the histogram metric.

@example

import { Metric, MetricBoundaries } from "effect"
const latencyHistogram = Metric.histogram("latency_histogram",
MetricBoundaries.linear({ start: 0, width: 10, count: 11 }),
"Measures the distribution of request latency."
);

@since2.0.0

histogram
(
"request_latency",
// Buckets from 0-100, with an extra Infinity bucket
import MetricBoundaries
MetricBoundaries
.
const linear: (options: {
readonly start: number;
readonly width: number;
readonly count: number;
}) => MetricBoundaries.MetricBoundaries

A helper method to create histogram bucket boundaries for a histogram with linear increasing values.

@since2.0.0

linear
({
start: number
start
: 0,
width: number
width
: 10,
count: number
count
: 11 }),
// Optional
"Measures the distribution of request latency."
)
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<MetricState<in A>.Histogram, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
// Generate 100 random values and record them in the histogram
yield*
const latency: Metric.Metric
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
latency
(
import Random
Random
.
const nextIntBetween: (min: number, max: number) => Effect.Effect<number>

Returns the next integer value in the specified range from the pseudo-random number generator.

@since2.0.0

nextIntBetween
(1, 120)).
Pipeable.pipe<Effect.Effect<number, never, never>, Effect.Effect<number, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const repeatN: (n: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

The repeatN function returns a new effect that repeats the specified effect a given number of times or until the first failure. The repeats are in addition to the initial execution, so repeatN(action, 1) executes action once initially and then repeats it one additional time if it succeeds.

@example

import { Effect, Console } from "effect"
const action = Console.log("success")
const program = Effect.repeatN(action, 2)
Effect.runPromise(program)

@since2.0.0

repeatN
(99))
// Fetch and display the histogram's state
const
const state: MetricState.Histogram
state
= yield*
import Metric
Metric
.
const value: <MetricKeyType<in In, out Out>.Histogram, number, MetricState<in A>.Histogram>(self: Metric.Metric<MetricKeyType.Histogram, number, MetricState.Histogram>) => Effect.Effect<...>

Retrieves a snapshot of the value of the metric at this moment in time.

@since2.0.0

value
(
const latency: Metric.Metric<MetricKeyType.Histogram, number, MetricState.Histogram>
latency
)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
const state: MetricState.Histogram
state
)
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<void>

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
/*
Example Output:
HistogramState {
buckets: [
[ 0, 0 ], // No values in the 0-10 range
[ 10, 7 ], // 7 values in the 10-20 range
[ 20, 11 ], // 11 values in the 20-30 range
[ 30, 20 ], // 20 values in the 30-40 range
[ 40, 27 ], // and so on...
[ 50, 38 ],
[ 60, 53 ],
[ 70, 64 ],
[ 80, 73 ],
[ 90, 84 ],
[ Infinity, 100 ] // All 100 values have been recorded
],
count: 100, // Total count of observed values
min: 1, // Smallest observed value
max: 119, // Largest observed value
sum: 5980, // Sum of all observed values
...
}
*/

In this example, we demonstrate how to use a timer metric to track the duration of specific workflows. The timer captures how long certain tasks take to execute, storing this information in a histogram, which provides insights into the distribution of these durations.

We generate random values to simulate varying wait times, record the durations in the timer, and then print out the histogram’s state.

Example (Tracking Workflow Durations with a Timer Metric)

import {
import Metric
Metric
,
import Array
Array
,
import Random
Random
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// Create a timer metric with predefined boundaries from 1 to 10
const
const timer: Metric.Metric<MetricKeyType.Histogram, Duration, MetricState.Histogram>
timer
=
import Metric
Metric
.
const timerWithBoundaries: (name: string, boundaries: ReadonlyArray<number>, description?: string) => Metric.Metric<MetricKeyType<in In, out Out>.Histogram, Duration, MetricState<in A>.Histogram>

Creates a timer metric, based on a histogram created from the provided boundaries, which keeps track of durations in milliseconds. The unit of time will automatically be added to the metric as a tag (i.e. "time_unit: milliseconds").

@since2.0.0

timerWithBoundaries
("timer",
import Array
Array
.
const range: (start: number, end: number) => Array.NonEmptyArray<number>

Return a NonEmptyArray containing a range of integers, including both endpoints.

@example

import { range } from "effect/Array"
assert.deepStrictEqual(range(1, 3), [1, 2, 3])

@since2.0.0

range
(1, 10))
// Define a task that simulates random wait times
const
const task: Effect.Effect<void, never, never>
task
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* (
_: Effect.Adapter
_
) {
// Generate a random value between 1 and 10
const
const n: number
n
= yield*
import Random
Random
.
const nextIntBetween: (min: number, max: number) => Effect.Effect<number>

Returns the next integer value in the specified range from the pseudo-random number generator.

@since2.0.0

nextIntBetween
(1, 10)
// Simulate a delay based on the random value
yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

@since2.0.0

sleep
(`${
const n: number
n
} millis`)
})
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* (
_: Effect.Adapter
_
) {
// Track the duration of the task and repeat it 100 times
yield*
import Metric
Metric
.
const trackDuration: <void, never, never, MetricKeyType<in In, out Out>.Histogram, MetricState<in A>.Histogram>(self: Effect.Effect<void, never, never>, metric: Metric.Metric<MetricKeyType.Histogram, Duration, MetricState.Histogram>) => Effect.Effect<...> (+1 overload)

Returns an aspect that will update this metric with the duration that the effect takes to execute. To call this method, the input type of the metric must be Duration.

@since2.0.0

trackDuration
(
const task: Effect.Effect<void, never, never>
task
,
const timer: Metric.Metric<MetricKeyType.Histogram, Duration, MetricState.Histogram>
timer
).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const repeatN: (n: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

The repeatN function returns a new effect that repeats the specified effect a given number of times or until the first failure. The repeats are in addition to the initial execution, so repeatN(action, 1) executes action once initially and then repeats it one additional time if it succeeds.

@example

import { Effect, Console } from "effect"
const action = Console.log("success")
const program = Effect.repeatN(action, 2)
Effect.runPromise(program)

@since2.0.0

repeatN
(99))
// Retrieve and print the current state of the timer histogram
const
const state: MetricState.Histogram
state
= yield*
import Metric
Metric
.
const value: <MetricKeyType<in In, out Out>.Histogram, Duration, MetricState<in A>.Histogram>(self: Metric.Metric<MetricKeyType.Histogram, Duration, MetricState.Histogram>) => Effect.Effect<...>

Retrieves a snapshot of the value of the metric at this moment in time.

@since2.0.0

value
(
const timer: Metric.Metric<MetricKeyType.Histogram, Duration, MetricState.Histogram>
timer
)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
const state: MetricState.Histogram
state
)
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<void>

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
/*
Example Output:
HistogramState {
buckets: [
[ 1, 3 ], // 3 tasks completed in <= 1 ms
[ 2, 13 ], // 13 tasks completed in <= 2 ms
[ 3, 17 ], // and so on...
[ 4, 26 ],
[ 5, 35 ],
[ 6, 43 ],
[ 7, 53 ],
[ 8, 56 ],
[ 9, 65 ],
[ 10, 72 ],
[ Infinity, 100 ] // All 100 tasks have completed
],
count: 100, // Total number of tasks observed
min: 0.25797, // Shortest task duration in milliseconds
max: 12.25421, // Longest task duration in milliseconds
sum: 683.0266810000002, // Total time spent across all tasks
...
}
*/

A Summary is a metric that gives insights into a series of data points by calculating specific percentiles. Percentiles help us understand how data is distributed. For instance, if you’re tracking response times for requests over the past hour, you may want to examine key percentiles such as the 50th, 90th, 95th, or 99th to better understand your system’s performance.

Summaries are similar to histograms in that they observe number values, but with a different approach. Instead of immediately sorting values into buckets and discarding them, a summary holds onto the observed values in memory. However, to avoid storing too much data, summaries use two parameters:

  • maxAge: The maximum age a value can have before it’s discarded.
  • maxSize: The maximum number of values stored in the summary.

This creates a sliding window of recent values, so the summary always represents a fixed number of the most recent observations.

Summaries are commonly used to calculate quantiles over this sliding window. A quantile is a number between 0 and 1 that represents the percentage of values less than or equal to a certain threshold. For example, a quantile of 0.5 (or 50th percentile) is the median value, while 0.95 (or 95th percentile) would represent the value below which 95% of the observed data falls.

Quantiles are helpful for monitoring important performance metrics, such as latency, and for ensuring that your system meets performance goals (like Service Level Agreements, or SLAs).

The Effect Metrics API also allows you to configure summaries with an error margin. This margin introduces a range of acceptable values for quantiles, improving the accuracy of the result.

Summaries are particularly useful in cases where:

  • The range of values you’re observing is not known or estimated in advance, making histograms less practical.
  • You don’t need to aggregate data across multiple instances or average results. Summaries calculate their results on the application side, meaning they focus on the specific instance where they are used.

Example (Creating and Using a Summary)

In this example, we will create a summary to track response times. The summary will:

  • Hold up to 100 samples.
  • Discard samples older than 1 day.
  • Have a 3% error margin when calculating quantiles.
  • Report the 10%, 50%, and 90% quantiles, which help track response time distributions.

We’ll apply the summary to an effect that generates random integers, simulating response times.

import {
import Metric
Metric
,
import Random
Random
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// Define the summary for response times
const
const responseTimeSummary: Metric.Metric.Summary<number>
responseTimeSummary
=
import Metric
Metric
.
const summary: (options: {
readonly name: string;
readonly maxAge: DurationInput;
readonly maxSize: number;
readonly error: number;
readonly quantiles: ReadonlyArray<number>;
readonly description?: string | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Summary<number>

Creates a Summary metric that records observations and calculates quantiles. Summary metrics provide statistical information about a set of values, including quantiles.

@param

options - An object with configuration options for the Summary metric:

  • name - The name of the Summary metric.
  • maxAge - The maximum age of observations to retain.
  • maxSize - The maximum number of observations to keep.
  • error - The error percentage when calculating quantiles.
  • quantiles - An Chunk of quantiles to calculate (e.g., [0.5, 0.9]).
  • description - An optional description of the Summary metric.

@example

import { Metric, Chunk } from "effect"
const responseTimesSummary = Metric.summary({
name: "response_times_summary",
maxAge: "60 seconds", // Retain observations for 60 seconds.
maxSize: 1000, // Keep a maximum of 1000 observations.
error: 0.01, // Allow a 1% error when calculating quantiles.
quantiles: [0.5, 0.9, 0.99], // Calculate 50th, 90th, and 99th percentiles.
description: "Measures the distribution of response times."
});

@since2.0.0

summary
({
name: string
name
: "response_time_summary", // Name of the summary metric
maxAge: DurationInput
maxAge
: "1 day", // Maximum sample age
maxSize: number
maxSize
: 100, // Maximum number of samples to retain
error: number
error
: 0.03, // Error margin for quantile calculation
quantiles: readonly number[]
quantiles
: [0.1, 0.5, 0.9], // Quantiles to observe (10%, 50%, 90%)
// Optional
description?: string | undefined
description
: "Measures the distribution of response times"
})
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<MetricState<in A>.Summary, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* (
_: Effect.Adapter
_
) {
// Record 100 random response times between 1 and 120 ms
yield*
const responseTimeSummary: Metric.Metric<in out Type, in In, out Out>.Summary
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
responseTimeSummary
(
import Random
Random
.
const nextIntBetween: (min: number, max: number) => Effect.Effect<number>

Returns the next integer value in the specified range from the pseudo-random number generator.

@since2.0.0

nextIntBetween
(1, 120)).
Pipeable.pipe<Effect.Effect<number, never, never>, Effect.Effect<number, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const repeatN: (n: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

The repeatN function returns a new effect that repeats the specified effect a given number of times or until the first failure. The repeats are in addition to the initial execution, so repeatN(action, 1) executes action once initially and then repeats it one additional time if it succeeds.

@example

import { Effect, Console } from "effect"
const action = Console.log("success")
const program = Effect.repeatN(action, 2)
Effect.runPromise(program)

@since2.0.0

repeatN
(99)
)
// Retrieve and log the current state of the summary
const
const state: MetricState.Summary
state
= yield*
import Metric
Metric
.
const value: <MetricKeyType<in In, out Out>.Summary, number, MetricState<in A>.Summary>(self: Metric.Metric<MetricKeyType.Summary, number, MetricState.Summary>) => Effect.Effect<...>

Retrieves a snapshot of the value of the metric at this moment in time.

@since2.0.0

value
(
const responseTimeSummary: Metric.Metric.Summary<number>
responseTimeSummary
)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
("%o",
const state: MetricState.Summary
state
)
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<void>

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
/*
Example Output:
SummaryState {
error: 0.03, // Error margin used for quantile calculation
quantiles: [
[ 0.1, { _id: 'Option', _tag: 'Some', value: 17 } ], // 10th percentile: 17 ms
[ 0.5, { _id: 'Option', _tag: 'Some', value: 62 } ], // 50th percentile (median): 62 ms
[ 0.9, { _id: 'Option', _tag: 'Some', value: 109 } ] // 90th percentile: 109 ms
],
count: 100, // Total number of samples recorded
min: 4, // Minimum observed value
max: 119, // Maximum observed value
sum: 6058, // Sum of all recorded values
...
}
*/

Frequencies are metrics that help count the occurrences of specific values. Think of them as a set of counters, each associated with a unique value. When new values are observed, the frequency metric automatically creates new counters for those values.

Frequencies are particularly useful for tracking how often distinct string values occur. Some example use cases include:

  • Counting the number of invocations for each service in an application, where each service has a logical name.
  • Monitoring how frequently different types of failures occur.

Example (Tracking Error Occurrences)

In this example, we’ll create a Frequency to observe how often different error codes occur. This can be applied to effects that return a string value:

import {
import Metric
Metric
,
import Random
Random
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// Define a frequency metric to track errors
const
const errorFrequency: Metric.Metric.Frequency<string>
errorFrequency
=
import Metric
Metric
.
const frequency: (name: string, options?: {
readonly description?: string | undefined;
readonly preregisteredWords?: ReadonlyArray<string> | undefined;
} | undefined) => Metric.Metric<in out Type, in In, out Out>.Frequency<string>

Creates a Frequency metric to count occurrences of events. Frequency metrics are used to count the number of times specific events or incidents occur.

@paramname - The name of the Frequency metric.

@paramdescription - An optional description of the Frequency metric.

@example

import { Metric } from "effect"
const errorFrequency = Metric.frequency("error_frequency", {
description: "Counts the occurrences of errors."
});

@since2.0.0

frequency
("error_frequency", {
// Optional
description?: string | undefined
description
: "Counts the occurrences of errors."
})
const
const task: Effect.Effect<string, never, never>
task
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<number, never, never>>, string>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<number, never, never>>, string, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const n: number
n
= yield*
import Random
Random
.
const nextIntBetween: (min: number, max: number) => Effect.Effect<number>

Returns the next integer value in the specified range from the pseudo-random number generator.

@since2.0.0

nextIntBetween
(1, 10)
return `Error-${
const n: number
n
}`
})
// Program that simulates random errors and tracks their occurrences
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<string, never, never>> | YieldWrap<Effect.Effect<MetricState<in A>.Frequency, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* (
_: Effect.Adapter
_
) {
yield*
const errorFrequency: Metric.Metric<in out Type, in In, out Out>.Frequency
<string, never, never>(effect: Effect.Effect<string, never, never>) => Effect.Effect<string, never, never>
errorFrequency
(
const task: Effect.Effect<string, never, never>
task
).
Pipeable.pipe<Effect.Effect<string, never, never>, Effect.Effect<string, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<string, never, never>) => Effect.Effect<string, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const repeatN: (n: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

The repeatN function returns a new effect that repeats the specified effect a given number of times or until the first failure. The repeats are in addition to the initial execution, so repeatN(action, 1) executes action once initially and then repeats it one additional time if it succeeds.

@example

import { Effect, Console } from "effect"
const action = Console.log("success")
const program = Effect.repeatN(action, 2)
Effect.runPromise(program)

@since2.0.0

repeatN
(99))
// Retrieve and log the current state of the summary
const
const state: MetricState.Frequency
state
= yield*
import Metric
Metric
.
const value: <MetricKeyType<in In, out Out>.Frequency, string, MetricState<in A>.Frequency>(self: Metric.Metric<MetricKeyType.Frequency, string, MetricState.Frequency>) => Effect.Effect<...>

Retrieves a snapshot of the value of the metric at this moment in time.

@since2.0.0

value
(
const errorFrequency: Metric.Metric.Frequency<string>
errorFrequency
)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
("%o",
const state: MetricState.Frequency
state
)
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<void>

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
/*
Example Output:
FrequencyState {
occurrences: Map(9) {
'Error-7' => 12,
'Error-2' => 12,
'Error-4' => 14,
'Error-1' => 14,
'Error-9' => 8,
'Error-6' => 11,
'Error-5' => 9,
'Error-3' => 14,
'Error-8' => 6
},
...
}
*/

Tags are key-value pairs you can add to metrics to provide additional context. They help categorize and filter metrics, making it easier to analyze specific aspects of your application’s performance or behavior.

When creating metrics, you can add tags to them. Tags are key-value pairs that provide additional context, helping in categorizing and filtering metrics. This makes it easier to analyze and monitor specific aspects of your application.

You can tag individual metrics using the Metric.tagged function. This allows you to add specific tags to a single metric, providing detailed context without applying tags globally.

Example (Tagging an Individual Metric)

import {
import Metric
Metric
} from "effect"
// Create a counter metric for request count
// and tag it with "environment: production"
const
const counter: Metric.Metric<MetricKeyType<number, MetricState.Counter<number>> & {
readonly incremental: boolean;
readonly bigint: boolean;
readonly [CounterKeyTypeTypeId]: CounterKeyTypeTypeId;
}, number, MetricState.Counter<...>>
counter
=
import Metric
Metric
.
const counter: (name: string, options?: {
readonly description?: string | undefined;
readonly bigint?: false | undefined;
readonly incremental?: boolean | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Counter<number> (+1 overload)

Represents a Counter metric that tracks cumulative numerical values over time. Counters can be incremented and decremented and provide a running total of changes.

@paramname - The name of the counter metric.

@param

options - An optional configuration for the counter:

  • description - A description of the counter.
  • bigint - Indicates if the counter uses 'bigint' data type.
  • incremental - Set to 'true' for a counter that only increases. With this configuration, Effect ensures that non-incremental updates have no impact on the counter, making it exclusively suitable for counting upwards.

@example

import { Metric } from "effect"
const numberCounter = Metric.counter("count", {
description: "A number counter"
});
const bigintCounter = Metric.counter("count", {
description: "A bigint counter",
bigint: true
});

@since2.0.0

counter
("request_count").
Pipeable.pipe<Metric.Metric<in out Type, in In, out Out>.Counter<number>, Metric.Metric<MetricKeyType<number, MetricState<in A>.Counter<number>> & {
readonly incremental: boolean;
readonly bigint: boolean;
readonly [CounterKeyTypeTypeId]: CounterKeyTypeTypeId;
}, number, MetricState.Counter<...>>>(this: Metric.Metric.Counter<...>, ab: (_: Metric.Metric.Counter<...>) => Metric.Metric<...>): Metric.Metric<...> (+21 overloads)
pipe
(
import Metric
Metric
.
const tagged: <MetricKeyType<number, MetricState<in A>.Counter<number>> & {
readonly incremental: boolean;
readonly bigint: boolean;
readonly [CounterKeyTypeTypeId]: CounterKeyTypeTypeId;
}, number, MetricState.Counter<...>>(key: string, value: string) => (self: Metric.Metric<...>) => Metric.Metric<...> (+1 overload)

Returns a new metric, which is identical in every way to this one, except the specified tags have been added to the tags of this metric.

@since2.0.0

tagged
("environment", "production")
)

Here, the request_count metric is tagged with "environment": "production", allowing you to filter or analyze metrics by this tag later.

You can use Effect.tagMetrics to apply tags to all metrics within the same context. This is useful when you want to apply common tags, like the environment (e.g., “production” or “development”), across multiple metrics.

Example (Tagging Multiple Metrics)

import {
import Metric
Metric
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// Create two separate counters
const
const counter1: Metric.Metric.Counter<number>
counter1
=
import Metric
Metric
.
const counter: (name: string, options?: {
readonly description?: string | undefined;
readonly bigint?: false | undefined;
readonly incremental?: boolean | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Counter<number> (+1 overload)

Represents a Counter metric that tracks cumulative numerical values over time. Counters can be incremented and decremented and provide a running total of changes.

@paramname - The name of the counter metric.

@param

options - An optional configuration for the counter:

  • description - A description of the counter.
  • bigint - Indicates if the counter uses 'bigint' data type.
  • incremental - Set to 'true' for a counter that only increases. With this configuration, Effect ensures that non-incremental updates have no impact on the counter, making it exclusively suitable for counting upwards.

@example

import { Metric } from "effect"
const numberCounter = Metric.counter("count", {
description: "A number counter"
});
const bigintCounter = Metric.counter("count", {
description: "A bigint counter",
bigint: true
});

@since2.0.0

counter
("counter1")
const
const counter2: Metric.Metric.Counter<number>
counter2
=
import Metric
Metric
.
const counter: (name: string, options?: {
readonly description?: string | undefined;
readonly bigint?: false | undefined;
readonly incremental?: boolean | undefined;
}) => Metric.Metric<in out Type, in In, out Out>.Counter<number> (+1 overload)

Represents a Counter metric that tracks cumulative numerical values over time. Counters can be incremented and decremented and provide a running total of changes.

@paramname - The name of the counter metric.

@param

options - An optional configuration for the counter:

  • description - A description of the counter.
  • bigint - Indicates if the counter uses 'bigint' data type.
  • incremental - Set to 'true' for a counter that only increases. With this configuration, Effect ensures that non-incremental updates have no impact on the counter, making it exclusively suitable for counting upwards.

@example

import { Metric } from "effect"
const numberCounter = Metric.counter("count", {
description: "A number counter"
});
const bigintCounter = Metric.counter("count", {
description: "A bigint counter",
bigint: true
});

@since2.0.0

counter
("counter2")
// Define a task that simulates some work with a slight delay
const
const task: Effect.Effect<number, never, never>
task
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(1).
Pipeable.pipe<Effect.Effect<number, never, never>, Effect.Effect<number, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const delay: (duration: DurationInput) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Returns an effect that is delayed from this effect by the specified Duration.

@since2.0.0

delay
("100 millis"))
// Apply the environment tag to both counters in the same context
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<number, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<number, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
yield*
const counter1: Metric.Metric<in out Type, in In, out Out>.Counter
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
counter1
(
const task: Effect.Effect<number, never, never>
task
)
yield*
const counter2: Metric.Metric<in out Type, in In, out Out>.Counter
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
counter2
(
const task: Effect.Effect<number, never, never>
task
)
}).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const tagMetrics: (key: string, value: string) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+3 overloads)

Tags each metric in this effect with the specific tag.

@since2.0.0

tagMetrics
("environment", "production"))

If you only want to apply tags within a specific scope, you can use Effect.tagMetricsScoped. This limits the tag application to metrics within that scope, allowing for more precise tagging control.