Hyperlinkv0.8.0-beta.28

Effect

Effect.trackErrorsconsteffect/Effect.ts:14374
<Input, State, E>(
  metric: Metric.Metric<Input, State>,
  f: (error: E) => Input
): <A, R>(self: Effect<A, E, R>) => Effect<A, E, R>
<State, E>(metric: Metric.Metric<NoInfer<E>, State>): <A, R>(
  self: Effect<A, E, R>
) => Effect<A, E, R>
<A, E, R, Input, State>(
  self: Effect<A, E, R>,
  metric: Metric.Metric<Input, State>,
  f: (error: E) => Input
): Effect<A, E, R>
<A, E, R, State>(
  self: Effect<A, E, R>,
  metric: Metric.Metric<NoInfer<E>, State>
): Effect<A, E, R>

Updates the provided Metric every time the wrapped Effect fails with an expected error.

Details

Also accepts an optional function which can be used to map the error value of the Effect into a valid Input for the Metric.

Example (Counting expected failures)

import { Effect, Metric } from "effect"

const errorCounter = Metric.counter("errors").pipe(
  Metric.withConstantInput(1)
)

const program = Effect.fail("Network timeout").pipe(
  Effect.trackErrors(errorCounter)
)

Effect.runPromiseExit(program).then(() =>
  Effect.runPromise(Metric.value(errorCounter)).then(console.log)
  // Output: { count: 1, incremental: false }
)

Example (Mapping errors before tracking)

import { Data, Effect, Metric } from "effect"

class ConnectionFailedError extends Data.TaggedError("ConnectionFailedError")<{}> {}

// Track error types using frequency metric
const errorTypeFrequency = Metric.frequency("error_types")

const program = Effect.fail(new ConnectionFailedError()).pipe(
  Effect.trackErrors(errorTypeFrequency, (error: ConnectionFailedError) => error._tag)
)

Effect.runPromiseExit(program).then(() =>
  Effect.runPromise(Metric.value(errorTypeFrequency)).then(console.log)
  // Output: { occurrences: Map(1) { "ConnectionFailedError" => 1 } }
)
tracking
Source effect/Effect.ts:1437429 lines
export const trackErrors: {
  <Input, State, E>(
    metric: Metric.Metric<Input, State>,
    f: (error: E) => Input
  ): <A, R>(self: Effect<A, E, R>) => Effect<A, E, R>
  <State, E>(
    metric: Metric.Metric<NoInfer<E>, State>
  ): <A, R>(self: Effect<A, E, R>) => Effect<A, E, R>
  <A, E, R, Input, State>(
    self: Effect<A, E, R>,
    metric: Metric.Metric<Input, State>,
    f: (error: E) => Input
  ): Effect<A, E, R>
  <A, E, R, State>(
    self: Effect<A, E, R>,
    metric: Metric.Metric<NoInfer<E>, State>
  ): Effect<A, E, R>
} = dual(
  (args) => isEffect(args[0]),
  <A, E, R, Input, State>(
    self: Effect<A, E, R>,
    metric: Metric.Metric<Input, State>,
    f: ((error: E) => Input) | undefined
  ): Effect<A, E, R> =>
    tapError(self, (error) => {
      const input = f === undefined ? error : internalCall(() => f(error))
      return Metric.update(metric, input as any)
    })
)