(
name: string,
options?: {
readonly description?: string | undefined
readonly attributes?: Metric.Attributes | undefined
readonly bigint?: false | undefined
readonly incremental?: boolean | undefined
}
): Counter<number>
(
name: string,
options: {
readonly description?: string | undefined
readonly attributes?: Metric.Attributes | undefined
readonly bigint: true
readonly incremental?: boolean | undefined
}
): Counter<bigint>Represents a Counter metric that tracks cumulative numerical values over time. Counters can be incremented and decremented and provide a running total of changes.
Details
The optional description describes the counter, and attributes attach
dimensions to it. Set bigint to create a counter that accepts bigint
inputs. Set incremental to true to create a counter that can only ever be
incremented.
Example (Creating counter metrics)
import { Data, Effect, Metric } from "effect"
class CounterError extends Data.TaggedError("CounterError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create a basic counter for tracking requests
const requestCounter = Metric.counter("http_requests_total", {
description: "Total number of HTTP requests processed"
})
// Create an incremental-only counter for events
const eventCounter = Metric.counter("events_processed", {
description: "Events processed (increment only)",
incremental: true
})
// Create a bigint counter for large values
const bytesCounter = Metric.counter("bytes_transferred", {
description: "Total bytes transferred",
bigint: true,
attributes: { service: "file-transfer" }
})
// Update counters with values
yield* Metric.update(requestCounter, 1) // Increment by 1
yield* Metric.update(requestCounter, 5) // Increment by 5 (total: 6)
yield* Metric.update(eventCounter, 1) // Increment by 1
yield* Metric.update(bytesCounter, 1024n) // Add 1024 bytes
// Get current counter values
const requestValue = yield* Metric.value(requestCounter)
const eventValue = yield* Metric.value(eventCounter)
const bytesValue = yield* Metric.value(bytesCounter)
return { requestValue, eventValue, bytesValue }
})export const const counter: {
(
name: string,
options?: {
readonly description?: string | undefined
readonly attributes?:
| Metric.Attributes
| undefined
readonly bigint?: false | undefined
readonly incremental?: boolean | undefined
}
): Counter<number>
(
name: string,
options: {
readonly description?: string | undefined
readonly attributes?:
| Metric.Attributes
| undefined
readonly bigint: true
readonly incremental?: boolean | undefined
}
): Counter<bigint>
}
Represents a Counter metric that tracks cumulative numerical values over
time. Counters can be incremented and decremented and provide a running total
of changes.
Details
The optional description describes the counter, and attributes attach
dimensions to it. Set bigint to create a counter that accepts bigint
inputs. Set incremental to true to create a counter that can only ever be
incremented.
Example (Creating counter metrics)
import { Data, Effect, Metric } from "effect"
class CounterError extends Data.TaggedError("CounterError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create a basic counter for tracking requests
const requestCounter = Metric.counter("http_requests_total", {
description: "Total number of HTTP requests processed"
})
// Create an incremental-only counter for events
const eventCounter = Metric.counter("events_processed", {
description: "Events processed (increment only)",
incremental: true
})
// Create a bigint counter for large values
const bytesCounter = Metric.counter("bytes_transferred", {
description: "Total bytes transferred",
bigint: true,
attributes: { service: "file-transfer" }
})
// Update counters with values
yield* Metric.update(requestCounter, 1) // Increment by 1
yield* Metric.update(requestCounter, 5) // Increment by 5 (total: 6)
yield* Metric.update(eventCounter, 1) // Increment by 1
yield* Metric.update(bytesCounter, 1024n) // Add 1024 bytes
// Get current counter values
const requestValue = yield* Metric.value(requestCounter)
const eventValue = yield* Metric.value(eventCounter)
const bytesValue = yield* Metric.value(bytesCounter)
return { requestValue, eventValue, bytesValue }
})
counter: {
(
name: stringname: string,
options: | {
readonly description?: string | undefined
readonly attributes?:
| Metric.Attributes
| undefined
readonly bigint?: false | undefined
readonly incremental?: boolean | undefined
}
| undefined
options?: {
readonly description?: string | undefineddescription?: string | undefined
readonly attributes?: Metric.Attributes | undefinedattributes?: 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 | undefined
readonly bigint?: false | undefinedbigint?: false | undefined
readonly incremental?: boolean | undefinedincremental?: boolean | undefined
}
): interface Counter<in Input extends number | bigint>A Counter metric that tracks cumulative values that typically only increase.
When to use
Use when counters are useful for tracking monotonically increasing values like request counts,
bytes processed, errors encountered, or any value that accumulates over time.
Example (Using counter metrics)
import { Data, Effect, Metric } from "effect"
class CounterInterfaceError extends Data.TaggedError("CounterInterfaceError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of counters
const requestCounter: Metric.Counter<number> = Metric.counter(
"http_requests",
{
description: "Total HTTP requests processed",
incremental: true // Only allows increments
}
)
const bytesCounter: Metric.Counter<bigint> = Metric.counter(
"bytes_processed",
{
description: "Total bytes processed",
bigint: true,
attributes: { service: "data-processor" }
}
)
// Update counters
yield* Metric.update(requestCounter, 1) // Increment by 1
yield* Metric.update(requestCounter, 5) // Increment by 5 (total: 6)
yield* Metric.update(bytesCounter, 1024n) // Add 1024 bytes
// Read counter state
const requestState: Metric.CounterState<number> = yield* Metric.value(
requestCounter
)
const bytesState: Metric.CounterState<bigint> = yield* Metric.value(
bytesCounter
)
// Counter state contains:
// - count: current accumulated value
// - incremental: whether only increments are allowed
return {
requests: {
count: requestState.count,
incremental: requestState.incremental
},
bytes: { count: bytesState.count, incremental: bytesState.incremental }
}
})
Counter<number>
(
name: stringname: string,
options: {
readonly description?: string | undefined
readonly attributes?:
| Metric.Attributes
| undefined
readonly bigint: true
readonly incremental?: boolean | undefined
}
options: {
readonly description?: string | undefineddescription?: string | undefined
readonly attributes?: Metric.Attributes | undefinedattributes?: 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 | undefined
readonly bigint: truebigint: true
readonly incremental?: boolean | undefinedincremental?: boolean | undefined
}
): interface Counter<in Input extends number | bigint>A Counter metric that tracks cumulative values that typically only increase.
When to use
Use when counters are useful for tracking monotonically increasing values like request counts,
bytes processed, errors encountered, or any value that accumulates over time.
Example (Using counter metrics)
import { Data, Effect, Metric } from "effect"
class CounterInterfaceError extends Data.TaggedError("CounterInterfaceError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of counters
const requestCounter: Metric.Counter<number> = Metric.counter(
"http_requests",
{
description: "Total HTTP requests processed",
incremental: true // Only allows increments
}
)
const bytesCounter: Metric.Counter<bigint> = Metric.counter(
"bytes_processed",
{
description: "Total bytes processed",
bigint: true,
attributes: { service: "data-processor" }
}
)
// Update counters
yield* Metric.update(requestCounter, 1) // Increment by 1
yield* Metric.update(requestCounter, 5) // Increment by 5 (total: 6)
yield* Metric.update(bytesCounter, 1024n) // Add 1024 bytes
// Read counter state
const requestState: Metric.CounterState<number> = yield* Metric.value(
requestCounter
)
const bytesState: Metric.CounterState<bigint> = yield* Metric.value(
bytesCounter
)
// Counter state contains:
// - count: current accumulated value
// - incremental: whether only increments are allowed
return {
requests: {
count: requestState.count,
incremental: requestState.incremental
},
bytes: { count: bytesState.count, incremental: bytesState.incremental }
}
})
Counter<bigint>
} = (name: stringname, options: | {
readonly description?: string | undefined
readonly attributes?:
| Metric.Attributes
| undefined
readonly bigint?: false | undefined
readonly incremental?: boolean | undefined
}
| {
readonly description?: string | undefined
readonly attributes?:
| Metric.Attributes
| undefined
readonly bigint: true
readonly incremental?: boolean | undefined
}
| undefined
options) => new constructor CounterMetric<number | bigint>(id: string, options?: {
readonly description?: string | undefined;
readonly attributes?: Metric.Attributes | undefined;
readonly bigint?: boolean | undefined;
readonly incremental?: boolean | undefined;
}): CounterMetric<number | bigint>
CounterMetric(name: stringname, options: | {
readonly description?: string | undefined
readonly attributes?:
| Metric.Attributes
| undefined
readonly bigint?: false | undefined
readonly incremental?: boolean | undefined
}
| {
readonly description?: string | undefined
readonly attributes?:
| Metric.Attributes
| undefined
readonly bigint: true
readonly incremental?: boolean | undefined
}
| undefined
options) as any