Skip to content

Effect 中的指标

在复杂且高度并发的应用程序中,管理各种相互关联的组件可能相当具有挑战性。确保一切运行顺利并避免应用程序停机在这种设置中变得至关重要。

现在,让我们想象一下我们有一个复杂的基础设施,包含众多服务。这些服务在我们的服务器上被复制和分布。然而,我们通常缺乏对这些服务中发生的事情的洞察,包括错误率、响应时间和服务正常运行时间。这种可见性的缺乏可能使有效识别和解决问题变得困难。这就是 Effect Metrics 发挥作用的地方;它允许我们捕获和分析各种指标,为后续调查提供有价值的数据。

Effect Metrics 支持五种不同类型的指标:

指标描述
Counter计数器用于跟踪随时间增长的值,例如请求计数。它们帮助我们跟踪特定事件或操作发生的次数。
Gauge仪表表示可以随时间上下波动的单个数值。它们通常用于监控像内存使用量这样可以持续变化的指标。
Histogram直方图用于跟踪观察值在不同桶中的分布。它们通常用于像请求延迟这样的指标,让我们了解响应时间是如何分布的。
Summary摘要提供对时间序列滑动窗口的洞察,并为时间序列的特定百分位数(通常称为分位数)提供指标。这对于理解延迟相关指标(如请求响应时间)特别有用。
Frequency频率指标计算不同字符串值的出现次数。当您想要跟踪应用程序中不同事件或条件发生的频率时,它们很有用。

在指标的世界中,Counter 是一个表示单个数值的指标,该数值可以随时间递增和递减。可以将其视为跟踪变化的计数器,例如应用程序接收到的特定类型请求的数量,无论是增加还是减少。

与其他一些类型的指标(如 gauges)不同,我们关心的是特定时刻的值,而对于计数器,我们关心的是随时间累积的值。这意味着它提供了变化的运行总计,可以上升和下降,反映了某些指标的动态性质。

计数器的一些典型用例包括:

  • 请求计数:监控服务器接收到的传入请求数量。
  • 已完成任务:跟踪已成功完成的任务或进程数量。
  • 错误计数:计算应用程序中错误的发生次数。

要创建计数器,您可以使用 Metric.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.

Options

  • 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
: "用于跟踪请求的计数器"
})

创建后,计数器可以接受返回 number 的 effect,这将增加或减少计数器。

示例(使用计数器)

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.

Options

  • 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<number, never, never>> | YieldWrap<Effect.Effect<MetricState<in A>.Counter<number>, never, never>>, number>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<MetricState.Counter<number>, never, never>>, number, never>) => Effect.Effect<number, never, never> (+1 overload)

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

When to Use

Effect.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* () {
// 将计数器增加 1
const
const a: number
a
= yield*
const requestCount: Metric.Metric<in out Type, in In, out Out>.Counter
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
requestCount
(
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.

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

succeed
(1))
// 将计数器增加 2
const
const b: number
b
= yield*
const requestCount: Metric.Metric<in out Type, in In, out Out>.Counter
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
requestCount
(
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.

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

succeed
(2))
// 将计数器减少 4
const
const c: number
c
= yield*
const requestCount: Metric.Metric<in out Type, in In, out Out>.Counter
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
requestCount
(
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.

Example (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)

@seefail to create an effect that represents a failure.

@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<MetricState.Counter<number>, never, never>

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: 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;
} | undefined) => Promise<number>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

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

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

@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<void>

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
)
/*
输出:
CounterState {
count: -1,
...
}
-8
*/

您可以指定计数器跟踪 number 还是 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.

Options

  • 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
: "用于跟踪请求的计数器"
// bigint: false // 默认值
})
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.

Options

  • 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
: "用于跟踪错误的计数器",
bigint: true
bigint
: true
})

如果您需要一个只递增的计数器,可以使用 incremental: true 选项。

示例(使用仅递增计数器)

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.

Options

  • 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
: "只增加其值的计数器",
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<number, never, never>> | YieldWrap<Effect.Effect<MetricState<in A>.Counter<number>, never, never>>, number>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<MetricState.Counter<number>, never, never>>, number, never>) => Effect.Effect<number, never, never> (+1 overload)

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

When to Use

Effect.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 incrementalCounter: Metric.Metric<in out Type, in In, out Out>.Counter
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
incrementalCounter
(
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.

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

succeed
(1))
const
const b: number
b
= yield*
const incrementalCounter: Metric.Metric<in out Type, in In, out Out>.Counter
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
incrementalCounter
(
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.

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

succeed
(2))
// 这对计数器没有影响
const
const c: number
c
= yield*
const incrementalCounter: Metric.Metric<in out Type, in In, out Out>.Counter
<number, never, never>(effect: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>
incrementalCounter
(
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.

Example (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)

@seefail to create an effect that represents a failure.

@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<MetricState.Counter<number>, never, never>

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: 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;
} | undefined) => Promise<number>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

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

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

@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<void>

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
)
/*
输出:
CounterState {
count: 3,
...
}
-8
*/

在此配置中,计数器只接受正值。任何递减尝试都不会产生影响,确保计数器严格向上计数。

您可以配置计数器在每次调用时始终按固定值递增。

示例(常量输入)

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.

Options

  • 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<number>, ab: (_: Metric.Metric.Counter<number>) => Metric.Metric<MetricKeyType.Counter<number>, unknown, MetricState.Counter<number>>): Metric.Metric<MetricKeyType.Counter<number>, unknown, MetricState.Counter<number>> (+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) // 自动递增 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.

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

succeed
(1).
Pipeable.pipe<Effect.Effect<number, never, never>, Effect.Effect<number, never, never>>(this: Effect.Effect<number, never, never>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<number, never, never> (+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)

Delays the execution of an effect by a specified Duration.

**Details

This function postpones the execution of the provided effect by the specified duration. The duration can be provided in various formats supported by the Duration module.

Internally, this function does not block the thread; instead, it uses an efficient, non-blocking mechanism to introduce the delay.

Example

import { Console, Effect } from "effect"
const task = Console.log("Task executed")
const program = Console.log("start").pipe(
Effect.andThen(
// Delays the log message by 2 seconds
task.pipe(Effect.delay("2 seconds"))
)
)
Effect.runFork(program)
// Output:
// start
// Task executed

@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.

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

succeed
(2).
Pipeable.pipe<Effect.Effect<number, never, never>, Effect.Effect<number, never, never>>(this: Effect.Effect<number, never, never>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<number, never, never> (+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)

Delays the execution of an effect by a specified Duration.

**Details

This function postpones the execution of the provided effect by the specified duration. The duration can be provided in various formats supported by the Duration module.

Internally, this function does not block the thread; instead, it uses an efficient, non-blocking mechanism to introduce the delay.

Example

import { Console, Effect } from "effect"
const task = Console.log("Task executed")
const program = Console.log("start").pipe(
Effect.andThen(
// Delays the log message by 2 seconds
task.pipe(Effect.delay("2 seconds"))
)
)
Effect.runFork(program)
// Output:
// start
// Task executed

@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.

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

succeed
(-4).
Pipeable.pipe<Effect.Effect<number, never, never>, Effect.Effect<number, never, never>>(this: Effect.Effect<number, never, never>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<number, never, never> (+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)

Delays the execution of an effect by a specified Duration.

**Details

This function postpones the execution of the provided effect by the specified duration. The duration can be provided in various formats supported by the Duration module.

Internally, this function does not block the thread; instead, it uses an efficient, non-blocking mechanism to introduce the delay.

Example

import { Console, Effect } from "effect"
const task = Console.log("Task executed")
const program = Console.log("start").pipe(
Effect.andThen(
// Delays the log message by 2 seconds
task.pipe(Effect.delay("2 seconds"))
)
)
Effect.runFork(program)
// Output:
// start
// Task executed

@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<YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<MetricState.Counter<number>, never, never>>, number, never>) => Effect.Effect<number, never, never> (+1 overload)

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

When to Use

Effect.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<MetricState.Counter<number>, never, never>

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;
} | undefined) => Promise<number>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

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

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

@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<void>

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
)
/*
输出:
CounterState {
count: 3,
...
}
-8
*/

在指标的世界中,Gauge 是一个表示可以设置或调整的单个数值的指标。可以将其视为可以随时间变化的动态变量。仪表的一个常见用例是监控应用程序的当前内存使用情况。

与计数器不同,我们关心的是随时间累积的值,而对于仪表,我们关注的是特定时间点的当前值。

当您想要监控可以增加和减少的值,并且不关心跟踪其变化率时,仪表是最佳选择。换句话说,仪表帮助我们测量在特定时刻具有特定值的事物。

仪表的一些典型用例包括:

  • 内存使用量:关注应用程序当前使用的内存量。
  • 队列大小:监控等待处理任务的队列的当前大小。
  • 进行中的请求计数:跟踪服务器当前正在处理的请求数量。
  • 温度:测量可以上下波动的当前温度。

要创建仪表,您可以使用 Metric.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.

Options

  • 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
: "用于内存使用量的仪表"
})

创建后,可以通过传递产生您想要为仪表设置的值的 effect 来更新仪表。

示例(使用仪表)

import {
import Metric
Metric
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Random
Random
} from "effect"
// 创建一个跟踪温度的仪表
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.

Options

  • 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")
// 模拟获取随机温度
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<number, never, never> (+1 overload)

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

When to Use

Effect.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* () {
// 获取 -10 到 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
})
// 多次更新仪表的程序
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<YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<MetricState.Gauge<number>, never, never>>, number[], never>) => Effect.Effect<number[], never, never> (+1 overload)

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

When to Use

Effect.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> = []
// 用新的温度读数更新仪表
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
))
// 检索仪表的当前状态
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<MetricState.Gauge<number>, never, never>

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;
} | undefined) => Promise<number[]>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

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

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

@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<void>

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
)
/*
示例输出:
new temperature: 9
new temperature: -9
new temperature: 2
GaugeState {
value: 2, // 仪表中设置的最新值
...
}
[ 9, -9, 2 ]
*/

您可以指定仪表跟踪 number 还是 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.

Options

  • 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
: "用于内存使用量的仪表"
// bigint: false // 默认值
})
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.

Options

  • 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
: "用于 CPU 负载的仪表",
bigint: true
bigint
: true
})

Histogram 是一个用于分析数值随时间分布情况的指标。直方图不关注单个数据点,而是将值分组到预定义的范围(称为)中,并跟踪有多少值落入每个范围。

当记录一个值时,它会根据其范围被分配到直方图的某个桶中。每个桶都有一个上边界,如果值小于或等于其边界,该桶的计数就会增加。一旦记录,单个值就会被丢弃,重点转移到有多少值落入每个桶中。

直方图还跟踪:

  • 总计数:已观察到的值的数量。
  • 总和:所有观察值的总和。
  • 最小值:观察到的最小值。
  • 最大值:观察到的最大值。

直方图对于计算百分位数特别有用,通过分析每个桶中有多少值,可以帮助您估计数据集中的特定点。

这个概念受到 Prometheus(一个知名的监控和告警工具包)的启发。

直方图在性能分析和系统监控中特别有用。通过检查响应时间、延迟或其他指标的分布情况,您可以获得对系统行为的宝贵洞察。这些数据帮助您识别异常值、性能瓶颈或可能需要优化的趋势。

直方图的常见用例包括:

  • 百分位数估计:直方图允许您近似观察值的百分位数,如响应时间的第 95 百分位数。
  • 已知范围:如果您可以提前估计值的范围,直方图可以将数据组织到预定义的桶中以便更好地分析。
  • 性能指标:使用直方图跟踪请求延迟、内存使用量或随时间变化的吞吐量等指标。
  • 聚合:直方图可以跨多个实例聚合,使其成为分布式系统的理想选择,在这些系统中您需要从不同来源收集数据。

示例(具有线性桶的直方图)

在此示例中,我们定义了一个具有线性桶的直方图,其中值的范围从 0100,增量为 10。此外,我们还包括一个用于大于 100 的值的最终桶,称为”无穷大”桶。此配置对于跟踪特定范围内的数值(如请求延迟)很有用。

程序生成 1120 之间的随机数,将它们记录在直方图中,然后打印直方图的状态,显示落入每个桶的值的计数。

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Metric
Metric
,
import MetricBoundaries
MetricBoundaries
,
import Random
Random
} from "effect"
// 定义一个跟踪请求延迟的直方图,使用线性桶
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.

@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",
// 从 0-100 的桶,加上一个额外的无穷大桶
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 }),
// 可选
"测量请求延迟的分布。"
)
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<YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<MetricState.Histogram, never, never>>, void, never>) => Effect.Effect<void, never, never> (+1 overload)

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

When to Use

Effect.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* () {
// 生成 100 个随机值并将它们记录在直方图中
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<number, never, never>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<number, never, never> (+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)

Repeats an effect a specified number of times or until the first failure.

Details

This function executes an effect initially and then repeats it the specified number of times, as long as it succeeds. For example, calling repeatN(action, 2) will execute action once initially and then repeat it two additional times if there are no failures.

If the effect fails during any repetition, the failure is returned, and no further repetitions are attempted.

When to Use

This function is useful for tasks that need to be retried a fixed number of times or for performing repeated actions without requiring a schedule.

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))
// 获取并显示直方图的状态
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<MetricState.Histogram, never, never>

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;
} | undefined) => Promise<void>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

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

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

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
/*
示例输出:
HistogramState {
buckets: [
[ 0, 0 ], // 0-10 范围内没有值
[ 10, 7 ], // 10-20 范围内有 7 个值
[ 20, 11 ], // 20-30 范围内有 11 个值
[ 30, 20 ], // 30-40 范围内有 20 个值
[ 40, 27 ], // 以此类推...
[ 50, 38 ],
[ 60, 53 ],
[ 70, 64 ],
[ 80, 73 ],
[ 90, 84 ],
[ Infinity, 100 ] // 所有 100 个值都已记录
],
count: 100, // 观察值的总计数
min: 1, // 观察到的最小值
max: 119, // 观察到的最大值
sum: 5980, // 所有观察值的总和
...
}
*/

在此示例中,我们演示如何使用计时器指标来跟踪特定工作流的持续时间。计时器捕获某些任务执行所需的时间,将此信息存储在直方图中,从而提供对这些持续时间分布的洞察。

我们生成随机值来模拟不同的等待时间,在计时器中记录持续时间,然后打印出直方图的状态。

示例(使用计时器指标跟踪工作流持续时间)

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

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// 创建一个具有从 1 到 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"
const result = range(1, 3)
console.log(result) // [1, 2, 3]

@since2.0.0

range
(1, 10))
// 定义一个模拟随机等待时间的任务
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<void, never, never> (+1 overload)

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

When to Use

Effect.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* () {
// 生成 1 到 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)
// 基于随机值模拟延迟
yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Suspends the execution of an effect for a specified Duration.

Details

This function pauses the execution of an effect for a given duration. It is asynchronous, meaning that it does not block the fiber executing the effect. Instead, the fiber is suspended during the delay period and can resume once the specified time has passed.

The duration can be specified using various formats supported by the Duration module, such as a string ("2 seconds") or numeric value representing milliseconds.

Example

import { Effect } from "effect"
const program = Effect.gen(function*() {
console.log("Starting task...")
yield* Effect.sleep("3 seconds") // Waits for 3 seconds
console.log("Task completed!")
})
Effect.runFork(program)
// Output:
// Starting task...
// Task completed!

@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<void, never, never> (+1 overload)

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

When to Use

Effect.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* () {
// 跟踪任务的持续时间并重复 100 次
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<void, never, never> (+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<void, never, never>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<void, never, never> (+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)

Repeats an effect a specified number of times or until the first failure.

Details

This function executes an effect initially and then repeats it the specified number of times, as long as it succeeds. For example, calling repeatN(action, 2) will execute action once initially and then repeat it two additional times if there are no failures.

If the effect fails during any repetition, the failure is returned, and no further repetitions are attempted.

When to Use

This function is useful for tasks that need to be retried a fixed number of times or for performing repeated actions without requiring a schedule.

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))
// 检索并打印计时器直方图的当前状态
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<MetricState.Histogram, never, never>

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;
} | undefined) => Promise<void>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

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

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

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
/*
示例输出:
HistogramState {
buckets: [
[ 1, 3 ], // 3 个任务在 <= 1 ms 内完成
[ 2, 13 ], // 13 个任务在 <= 2 ms 内完成
[ 3, 17 ], // 以此类推...
[ 4, 26 ],
[ 5, 35 ],
[ 6, 43 ],
[ 7, 53 ],
[ 8, 56 ],
[ 9, 65 ],
[ 10, 72 ],
[ Infinity, 100 ] // 所有 100 个任务都已完成
],
count: 100, // 观察到的任务总数
min: 0.25797, // 最短任务持续时间(毫秒)
max: 12.25421, // 最长任务持续时间(毫秒)
sum: 683.0266810000002, // 所有任务花费的总时间
...
}
*/

Summary 是一个通过计算特定百分位数来洞察一系列数据点的指标。百分位数帮助我们了解数据是如何分布的。例如,如果您正在跟踪过去一小时内请求的响应时间,您可能想要检查关键百分位数,如第 50、90、95 或 99 百分位数,以更好地了解系统的性能。

Summary 与直方图类似,都观察 number 值,但采用不同的方法。Summary 不是立即将值分类到桶中并丢弃它们,而是在内存中保留观察到的值。但是,为了避免存储过多数据,summary 使用两个参数:

  • maxAge:值在被丢弃之前可以拥有的最大年龄。
  • maxSize:summary 中存储的最大值数量。

这创建了一个最近值的滑动窗口,因此 summary 始终表示固定数量的最新观察值。

Summary 通常用于在此滑动窗口上计算分位数分位数是介于 01 之间的数字,表示小于或等于某个阈值的值的百分比。例如,分位数 0.5(或第 50 百分位数)是中位数值,而 0.95(或第 95 百分位数)将表示 95% 的观察数据都低于该值。

分位数对于监控重要的性能指标(如延迟)以及确保系统满足性能目标(如服务级别协议或 SLA)很有帮助。

Effect Metrics API 还允许您使用误差边界配置 summary。此边界为分位数引入了可接受值的范围,提高了结果的准确性。

Summary 在以下情况下特别有用:

  • 您观察的值范围事先未知或未估计,使得直方图不太实用。
  • 您不需要跨多个实例聚合数据或平均结果。Summary 在应用程序端计算其结果,这意味着它们专注于使用它们的特定实例。

示例(创建和使用 Summary)

在此示例中,我们将创建一个 summary 来跟踪响应时间。该 summary 将:

  • 保存多达 100 个样本。
  • 丢弃超过 1 天 的样本。
  • 在计算分位数时具有 3% 的误差边界。
  • 报告 10%50%90% 分位数,这有助于跟踪响应时间分布。

我们将把 summary 应用于生成随机整数的 effect,模拟响应时间。

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

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// 定义响应时间的 summary
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.

Options

  • 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", // summary 指标的名称
maxAge: DurationInput
maxAge
: "1 day", // 最大样本年龄
maxSize: number
maxSize
: 100, // 要保留的最大样本数
error: number
error
: 0.03, // 分位数计算的误差边界
quantiles: readonly number[]
quantiles
: [0.1, 0.5, 0.9], // 要观察的分位数(10%、50%、90%)
// 可选
description?: string | undefined
description
: "测量响应时间的分布"
})
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<YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<MetricState.Summary, never, never>>, void, never>) => Effect.Effect<void, never, never> (+1 overload)

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

When to Use

Effect.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* () {
// 记录 100 个 1 到 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<number, never, never>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<number, never, never> (+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)

Repeats an effect a specified number of times or until the first failure.

Details

This function executes an effect initially and then repeats it the specified number of times, as long as it succeeds. For example, calling repeatN(action, 2) will execute action once initially and then repeat it two additional times if there are no failures.

If the effect fails during any repetition, the failure is returned, and no further repetitions are attempted.

When to Use

This function is useful for tasks that need to be retried a fixed number of times or for performing repeated actions without requiring a schedule.

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)
)
// 检索并记录 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<MetricState.Summary, never, never>

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;
} | undefined) => Promise<void>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

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

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

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
/*
示例输出:
SummaryState {
error: 0.03, // 用于分位数计算的误差边界
quantiles: [
[ 0.1, { _id: 'Option', _tag: 'Some', value: 17 } ], // 第 10 百分位数:17 ms
[ 0.5, { _id: 'Option', _tag: 'Some', value: 62 } ], // 第 50 百分位数(中位数):62 ms
[ 0.9, { _id: 'Option', _tag: 'Some', value: 109 } ] // 第 90 百分位数:109 ms
],
count: 100, // 记录的样本总数
min: 4, // 观察到的最小值
max: 119, // 观察到的最大值
sum: 6058, // 所有记录值的总和
...
}
*/

Frequency 是帮助计算特定值出现次数的指标。可以将它们视为一组计数器,每个计数器都与一个唯一值相关联。当观察到新值时,频率指标会自动为这些值创建新的计数器。

Frequency 对于跟踪不同字符串值出现的频率特别有用。一些示例用例包括:

  • 计算应用程序中每个服务的调用次数,其中每个服务都有一个逻辑名称。
  • 监控不同类型故障发生的频率。

示例(跟踪错误发生次数)

在此示例中,我们将创建一个 Frequency 来观察不同错误代码出现的频率。这可以应用于返回 string 值的 effect:

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

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// 定义一个跟踪错误的频率指标
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.

@example

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

@since2.0.0

frequency
("error_frequency", {
// 可选
description?: string | undefined
description
: "计算错误的发生次数。"
})
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<string, never, never> (+1 overload)

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

When to Use

Effect.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
}`
})
// 模拟随机错误并跟踪其发生次数的程序
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<YieldWrap<Effect.Effect<string, never, never>> | YieldWrap<Effect.Effect<MetricState.Frequency, never, never>>, void, never>) => Effect.Effect<void, never, never> (+1 overload)

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

When to Use

Effect.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 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<string, never, never>, ab: (_: Effect.Effect<string, never, never>) => Effect.Effect<string, never, never>): Effect.Effect<string, never, never> (+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)

Repeats an effect a specified number of times or until the first failure.

Details

This function executes an effect initially and then repeats it the specified number of times, as long as it succeeds. For example, calling repeatN(action, 2) will execute action once initially and then repeat it two additional times if there are no failures.

If the effect fails during any repetition, the failure is returned, and no further repetitions are attempted.

When to Use

This function is useful for tasks that need to be retried a fixed number of times or for performing repeated actions without requiring a schedule.

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))
// 检索并记录频率的当前状态
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<MetricState.Frequency, never, never>

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;
} | undefined) => Promise<void>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

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

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

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
/*
示例输出:
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
},
...
}
*/

标签是您可以添加到指标的键值对,以提供额外的上下文。它们有助于对指标进行分类和过滤,使分析应用程序性能或行为的特定方面变得更容易。

创建指标时,您可以向其添加标签。标签是提供额外上下文的键值对,有助于对指标进行分类和过滤。这使得分析和监控应用程序的特定方面变得更容易。

您可以使用 Metric.tagged 函数标记单个指标。 这允许您向单个指标添加特定标签,提供详细的上下文而不全局应用标签。

示例(标记单个指标)

import {
import Metric
Metric
} from "effect"
// 创建一个请求计数的计数器指标
// 并用 "environment: production" 标记它
const
const counter: Metric.Metric<MetricKeyType<number, MetricState.Counter<number>> & {
readonly incremental: boolean;
readonly bigint: boolean;
readonly [CounterKeyTypeTypeId]: CounterKeyTypeTypeId;
}, number, MetricState.Counter<number>>
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.

Options

  • 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<number>>>(this: Metric.Metric.Counter<...>, ab: (_: Metric.Metric.Counter<number>) => Metric.Metric<MetricKeyType<number, MetricState.Counter<number>> & {
readonly incremental: boolean;
readonly bigint: boolean;
readonly [CounterKeyTypeTypeId]: CounterKeyTypeTypeId;
}, number, MetricState.Counter<...>>): 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<number>>(key: string, value: string) => (self: Metric.Metric<MetricKeyType<number, MetricState.Counter<number>> & {
readonly incremental: boolean;
readonly bigint: boolean;
readonly [CounterKeyTypeTypeId]: CounterKeyTypeTypeId;
}, number, MetricState.Counter<...>>) => 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")
)

在这里,request_count 指标被标记为 "environment": "production",允许您稍后按此标签过滤或分析指标。

您可以使用 Effect.tagMetrics 将标签应用于同一上下文中的所有指标。当您想要在多个指标中应用通用标签(如环境,例如 “production” 或 “development”)时,这很有用。

示例(标记多个指标)

import {
import Metric
Metric
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// 创建两个独立的计数器
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.

Options

  • 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.

Options

  • 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")
// 定义一个模拟一些工作并稍有延迟的任务
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.

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

succeed
(1).
Pipeable.pipe<Effect.Effect<number, never, never>, Effect.Effect<number, never, never>>(this: Effect.Effect<number, never, never>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<number, never, never> (+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)

Delays the execution of an effect by a specified Duration.

**Details

This function postpones the execution of the provided effect by the specified duration. The duration can be provided in various formats supported by the Duration module.

Internally, this function does not block the thread; instead, it uses an efficient, non-blocking mechanism to introduce the delay.

Example

import { Console, Effect } from "effect"
const task = Console.log("Task executed")
const program = Console.log("start").pipe(
Effect.andThen(
// Delays the log message by 2 seconds
task.pipe(Effect.delay("2 seconds"))
)
)
Effect.runFork(program)
// Output:
// start
// Task executed

@since2.0.0

delay
("100 millis"))
// 在同一上下文中将环境标签应用于两个计数器
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<void, never, never> (+1 overload)

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

When to Use

Effect.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<void, never, never>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<void, never, never> (+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 an effect with specific key-value pairs.

Details

This function allows you to tag all metrics in an effect with a set of key-value pairs or a single key-value pair. Tags help you add metadata to metrics, making it easier to filter and categorize them in monitoring systems. The provided tags will apply to all metrics generated within the effect's scope.

@since2.0.0

tagMetrics
("environment", "production"))

如果您只想在特定 作用域 内应用标签,可以使用 Effect.tagMetricsScoped。这将标签应用限制在该作用域内的指标,允许更精确的标记控制。