Hyperlinkv0.8.0-beta.28

Metric

Metric.withAttributesconsteffect/Metric.ts:2972
(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)
    }
  }
})
Attributes
Source effect/Metric.ts:297216 lines
export 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>
} = dual<
  (attributes: Metric.Attributes) => <Input, State>(self: Metric<Input, State>) => Metric<Input, State>,
  <Input, State>(self: Metric<Input, State>, attributes: Metric.Attributes) => Metric<Input, State>
>(2, <Input, State>(
  self: Metric<Input, State>,
  attributes: Metric.Attributes
): Metric<Input, State> =>
  new MetricTransform(
    self,
    (context) => self.valueUnsafe(addAttributesToContext(context, attributes)),
    (input, context) => self.updateUnsafe(input, addAttributesToContext(context, attributes)),
    (input, context) => self.modifyUnsafe(input, addAttributesToContext(context, attributes))
  ))