(attributes: Metric.Attributes): <Input, State>(
self: Metric<Input, State>
) => Metric<Input, State>
<Input, State>(
self: Metric<Input, State>,
attributes: Metric.Attributes
): Metric<Input, State>Returns a new metric that applies the specified attributes to all operations.
Details
Attributes are key-value pairs that provide additional context for metrics, enabling filtering, grouping, and more detailed analysis. Each combination of attribute values creates a separate metric series.
Example (Applying metric attributes)
import { Effect, Metric } from "effect"
const requestCounter = Metric.counter("http_requests_total", {
description: "Total HTTP requests"
})
// Create tagged versions of the metric
const getRequests = Metric.withAttributes(requestCounter, {
method: "GET",
endpoint: "/api/users"
})
const postRequests = Metric.withAttributes(requestCounter, {
method: "POST",
endpoint: "/api/users"
})
const program = Effect.gen(function*() {
// These will be tracked as separate metric series
yield* Metric.update(getRequests, 1) // http_requests_total{method="GET", endpoint="/api/users"}
yield* Metric.update(postRequests, 1) // http_requests_total{method="POST", endpoint="/api/users"}
yield* Metric.update(getRequests, 1) // Increments the GET counter
// You can also chain attributes
const taggedMetric = requestCounter.pipe(
Metric.withAttributes({ service: "user-api" }),
Metric.withAttributes({ version: "v1" })
)
yield* Metric.update(taggedMetric, 1) // http_requests_total{service="user-api", version="v1"}
})
// When taking snapshots, each attribute combination appears as a separate metric
const viewMetrics = Effect.gen(function*() {
const snapshots = yield* Metric.snapshot
for (const metric of snapshots) {
if (metric.id === "http_requests_total") {
console.log(`${metric.id}`, metric.attributes, metric.state)
}
}
})export const const withAttributes: {
(attributes: Metric.Attributes): <Input, State>(
self: Metric<Input, State>
) => Metric<Input, State>
<Input, State>(
self: Metric<Input, State>,
attributes: Metric.Attributes
): Metric<Input, State>
}
Returns a new metric that applies the specified attributes to all operations.
Details
Attributes are key-value pairs that provide additional context for metrics,
enabling filtering, grouping, and more detailed analysis. Each combination
of attribute values creates a separate metric series.
Example (Applying metric attributes)
import { Effect, Metric } from "effect"
const requestCounter = Metric.counter("http_requests_total", {
description: "Total HTTP requests"
})
// Create tagged versions of the metric
const getRequests = Metric.withAttributes(requestCounter, {
method: "GET",
endpoint: "/api/users"
})
const postRequests = Metric.withAttributes(requestCounter, {
method: "POST",
endpoint: "/api/users"
})
const program = Effect.gen(function*() {
// These will be tracked as separate metric series
yield* Metric.update(getRequests, 1) // http_requests_total{method="GET", endpoint="/api/users"}
yield* Metric.update(postRequests, 1) // http_requests_total{method="POST", endpoint="/api/users"}
yield* Metric.update(getRequests, 1) // Increments the GET counter
// You can also chain attributes
const taggedMetric = requestCounter.pipe(
Metric.withAttributes({ service: "user-api" }),
Metric.withAttributes({ version: "v1" })
)
yield* Metric.update(taggedMetric, 1) // http_requests_total{service="user-api", version="v1"}
})
// When taking snapshots, each attribute combination appears as a separate metric
const viewMetrics = Effect.gen(function*() {
const snapshots = yield* Metric.snapshot
for (const metric of snapshots) {
if (metric.id === "http_requests_total") {
console.log(`${metric.id}`, metric.attributes, metric.state)
}
}
})
withAttributes: {
(attributes: Metric.Attributesattributes: Metric.type Metric<in Input, out State>.Attributes = Readonly<Record<string, string>> | readonly [string, string][]Union type for metric attributes that can be provided as either an object or array of tuples.
Example (Providing attributes in different formats)
import { Data, Effect, Metric } from "effect"
class AttributesError extends Data.TaggedError("AttributesError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Different ways to specify attributes
const attributesAsObject = {
service: "api",
environment: "production",
version: "1.2.3"
}
const attributesAsArray: ReadonlyArray<[string, string]> = [
["service", "api"],
["environment", "production"],
["version", "1.2.3"]
]
// Create metrics with different attribute formats
const requestCounter1 = Metric.counter("requests", {
description: "Total requests",
attributes: attributesAsObject // Using object format
})
const requestCounter2 = Metric.counter("requests", {
description: "Total requests",
attributes: attributesAsArray // Using array format
})
// Function to normalize attributes to object format
const normalizeAttributes = (
attrs: typeof attributesAsObject | ReadonlyArray<[string, string]>
) => {
if (Array.isArray(attrs)) {
return Object.fromEntries(attrs)
}
return attrs
}
// Add runtime attributes using withAttributes
const contextualCounter = Metric.withAttributes(requestCounter1, {
method: "GET",
endpoint: "/api/users"
})
// Update metrics with different attribute combinations
yield* Metric.update(contextualCounter, 1)
// Both formats result in the same internal representation
const normalizedObject = normalizeAttributes(attributesAsObject)
const normalizedArray = normalizeAttributes(attributesAsArray)
return {
attributeFormats: {
object: normalizedObject, // { service: "api", environment: "production", version: "1.2.3" }
array: normalizedArray, // { service: "api", environment: "production", version: "1.2.3" }
areEqual:
JSON.stringify(normalizedObject) === JSON.stringify(normalizedArray) // true
}
}
})
Attributes): <function (type parameter) Input in <Input, State>(self: Metric<Input, State>): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>): Metric<Input, State>State>(self: Metric<Input, State>(parameter) self: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self: interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <Input, State>(self: Metric<Input, State>): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>): Metric<Input, State>State>) => interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <Input, State>(self: Metric<Input, State>): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>): Metric<Input, State>State>
<function (type parameter) Input in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>State>(self: Metric<Input, State>(parameter) self: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self: interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>State>, attributes: Metric.Attributesattributes: Metric.type Metric<in Input, out State>.Attributes = Readonly<Record<string, string>> | readonly [string, string][]Union type for metric attributes that can be provided as either an object or array of tuples.
Example (Providing attributes in different formats)
import { Data, Effect, Metric } from "effect"
class AttributesError extends Data.TaggedError("AttributesError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Different ways to specify attributes
const attributesAsObject = {
service: "api",
environment: "production",
version: "1.2.3"
}
const attributesAsArray: ReadonlyArray<[string, string]> = [
["service", "api"],
["environment", "production"],
["version", "1.2.3"]
]
// Create metrics with different attribute formats
const requestCounter1 = Metric.counter("requests", {
description: "Total requests",
attributes: attributesAsObject // Using object format
})
const requestCounter2 = Metric.counter("requests", {
description: "Total requests",
attributes: attributesAsArray // Using array format
})
// Function to normalize attributes to object format
const normalizeAttributes = (
attrs: typeof attributesAsObject | ReadonlyArray<[string, string]>
) => {
if (Array.isArray(attrs)) {
return Object.fromEntries(attrs)
}
return attrs
}
// Add runtime attributes using withAttributes
const contextualCounter = Metric.withAttributes(requestCounter1, {
method: "GET",
endpoint: "/api/users"
})
// Update metrics with different attribute combinations
yield* Metric.update(contextualCounter, 1)
// Both formats result in the same internal representation
const normalizedObject = normalizeAttributes(attributesAsObject)
const normalizedArray = normalizeAttributes(attributesAsArray)
return {
attributeFormats: {
object: normalizedObject, // { service: "api", environment: "production", version: "1.2.3" }
array: normalizedArray, // { service: "api", environment: "production", version: "1.2.3" }
areEqual:
JSON.stringify(normalizedObject) === JSON.stringify(normalizedArray) // true
}
}
})
Attributes): interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>State>
} = import dualdual<
(attributes: Metric.Attributesattributes: Metric.type Metric<in Input, out State>.Attributes = Readonly<Record<string, string>> | readonly [string, string][]Union type for metric attributes that can be provided as either an object or array of tuples.
Example (Providing attributes in different formats)
import { Data, Effect, Metric } from "effect"
class AttributesError extends Data.TaggedError("AttributesError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Different ways to specify attributes
const attributesAsObject = {
service: "api",
environment: "production",
version: "1.2.3"
}
const attributesAsArray: ReadonlyArray<[string, string]> = [
["service", "api"],
["environment", "production"],
["version", "1.2.3"]
]
// Create metrics with different attribute formats
const requestCounter1 = Metric.counter("requests", {
description: "Total requests",
attributes: attributesAsObject // Using object format
})
const requestCounter2 = Metric.counter("requests", {
description: "Total requests",
attributes: attributesAsArray // Using array format
})
// Function to normalize attributes to object format
const normalizeAttributes = (
attrs: typeof attributesAsObject | ReadonlyArray<[string, string]>
) => {
if (Array.isArray(attrs)) {
return Object.fromEntries(attrs)
}
return attrs
}
// Add runtime attributes using withAttributes
const contextualCounter = Metric.withAttributes(requestCounter1, {
method: "GET",
endpoint: "/api/users"
})
// Update metrics with different attribute combinations
yield* Metric.update(contextualCounter, 1)
// Both formats result in the same internal representation
const normalizedObject = normalizeAttributes(attributesAsObject)
const normalizedArray = normalizeAttributes(attributesAsArray)
return {
attributeFormats: {
object: normalizedObject, // { service: "api", environment: "production", version: "1.2.3" }
array: normalizedArray, // { service: "api", environment: "production", version: "1.2.3" }
areEqual:
JSON.stringify(normalizedObject) === JSON.stringify(normalizedArray) // true
}
}
})
Attributes) => <function (type parameter) Input in <Input, State>(self: Metric<Input, State>): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>): Metric<Input, State>State>(self: Metric<Input, State>(parameter) self: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self: interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <Input, State>(self: Metric<Input, State>): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>): Metric<Input, State>State>) => interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <Input, State>(self: Metric<Input, State>): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>): Metric<Input, State>State>,
<function (type parameter) Input in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>State>(self: Metric<Input, State>(parameter) self: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self: interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>State>, attributes: Metric.Attributesattributes: Metric.type Metric<in Input, out State>.Attributes = Readonly<Record<string, string>> | readonly [string, string][]Union type for metric attributes that can be provided as either an object or array of tuples.
Example (Providing attributes in different formats)
import { Data, Effect, Metric } from "effect"
class AttributesError extends Data.TaggedError("AttributesError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Different ways to specify attributes
const attributesAsObject = {
service: "api",
environment: "production",
version: "1.2.3"
}
const attributesAsArray: ReadonlyArray<[string, string]> = [
["service", "api"],
["environment", "production"],
["version", "1.2.3"]
]
// Create metrics with different attribute formats
const requestCounter1 = Metric.counter("requests", {
description: "Total requests",
attributes: attributesAsObject // Using object format
})
const requestCounter2 = Metric.counter("requests", {
description: "Total requests",
attributes: attributesAsArray // Using array format
})
// Function to normalize attributes to object format
const normalizeAttributes = (
attrs: typeof attributesAsObject | ReadonlyArray<[string, string]>
) => {
if (Array.isArray(attrs)) {
return Object.fromEntries(attrs)
}
return attrs
}
// Add runtime attributes using withAttributes
const contextualCounter = Metric.withAttributes(requestCounter1, {
method: "GET",
endpoint: "/api/users"
})
// Update metrics with different attribute combinations
yield* Metric.update(contextualCounter, 1)
// Both formats result in the same internal representation
const normalizedObject = normalizeAttributes(attributesAsObject)
const normalizedArray = normalizeAttributes(attributesAsArray)
return {
attributeFormats: {
object: normalizedObject, // { service: "api", environment: "production", version: "1.2.3" }
array: normalizedArray, // { service: "api", environment: "production", version: "1.2.3" }
areEqual:
JSON.stringify(normalizedObject) === JSON.stringify(normalizedArray) // true
}
}
})
Attributes) => interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>State>
>(2, <function (type parameter) Input in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>State>(
self: Metric<Input, State>(parameter) self: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self: interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>State>,
attributes: Metric.Attributesattributes: Metric.type Metric<in Input, out State>.Attributes = Readonly<Record<string, string>> | readonly [string, string][]Union type for metric attributes that can be provided as either an object or array of tuples.
Example (Providing attributes in different formats)
import { Data, Effect, Metric } from "effect"
class AttributesError extends Data.TaggedError("AttributesError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Different ways to specify attributes
const attributesAsObject = {
service: "api",
environment: "production",
version: "1.2.3"
}
const attributesAsArray: ReadonlyArray<[string, string]> = [
["service", "api"],
["environment", "production"],
["version", "1.2.3"]
]
// Create metrics with different attribute formats
const requestCounter1 = Metric.counter("requests", {
description: "Total requests",
attributes: attributesAsObject // Using object format
})
const requestCounter2 = Metric.counter("requests", {
description: "Total requests",
attributes: attributesAsArray // Using array format
})
// Function to normalize attributes to object format
const normalizeAttributes = (
attrs: typeof attributesAsObject | ReadonlyArray<[string, string]>
) => {
if (Array.isArray(attrs)) {
return Object.fromEntries(attrs)
}
return attrs
}
// Add runtime attributes using withAttributes
const contextualCounter = Metric.withAttributes(requestCounter1, {
method: "GET",
endpoint: "/api/users"
})
// Update metrics with different attribute combinations
yield* Metric.update(contextualCounter, 1)
// Both formats result in the same internal representation
const normalizedObject = normalizeAttributes(attributesAsObject)
const normalizedArray = normalizeAttributes(attributesAsArray)
return {
attributeFormats: {
object: normalizedObject, // { service: "api", environment: "production", version: "1.2.3" }
array: normalizedArray, // { service: "api", environment: "production", version: "1.2.3" }
areEqual:
JSON.stringify(normalizedObject) === JSON.stringify(normalizedArray) // true
}
}
})
Attributes
): interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>Input, function (type parameter) State in <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes): Metric<Input, State>State> =>
new constructor MetricTransform<Input, State, Input>(metric: Metric<Input, State>, valueUnsafe: (context: Context.Context<never>) => State, updateUnsafe: (input: Input, context: Context.Context<never>) => void, modifyUnsafe: (input: Input, context: Context.Context<never>) => void): MetricTransform<Input, State, Input>MetricTransform(
self: Metric<Input, State>(parameter) self: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self,
(context: Context.Context<never>(parameter) context: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
context) => self: Metric<Input, State>(parameter) self: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self.Metric<Input, State>.valueUnsafe: (context: Context.Context<never>) => StatevalueUnsafe(function addAttributesToContext(
context: Context.Context<never>,
attributes: Metric.Attributes
): Context.Context<never>
addAttributesToContext(context: Context.Context<never>(parameter) context: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
context, attributes: Metric.Attributesattributes)),
(input: Inputinput, context: Context.Context<never>(parameter) context: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
context) => self: Metric<Input, State>(parameter) self: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self.Metric<Input, State>.updateUnsafe: (input: Input, context: Context.Context<never>) => voidupdateUnsafe(input: Inputinput, function addAttributesToContext(
context: Context.Context<never>,
attributes: Metric.Attributes
): Context.Context<never>
addAttributesToContext(context: Context.Context<never>(parameter) context: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
context, attributes: Metric.Attributesattributes)),
(input: Inputinput, context: Context.Context<never>(parameter) context: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
context) => self: Metric<Input, State>(parameter) self: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self.Metric<Input, State>.modifyUnsafe: (input: Input, context: Context.Context<never>) => voidmodifyUnsafe(input: Inputinput, function addAttributesToContext(
context: Context.Context<never>,
attributes: Metric.Attributes
): Context.Context<never>
addAttributesToContext(context: Context.Context<never>(parameter) context: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
context, attributes: Metric.Attributesattributes))
))