Hyperlinkv0.8.0-beta.28

Logger

Logger.batchedconsteffect/Logger.ts:764
<Output>(options: {
  readonly window: Duration.Input
  readonly flush: (
    messages: Array<NoInfer<Output>>
  ) => Effect.Effect<void>
}): <Message>(
  self: Logger<Message, Output>
) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>
<Message, Output>(
  self: Logger<Message, Output>,
  options: {
    readonly window: Duration.Input
    readonly flush: (
      messages: Array<NoInfer<Output>>
    ) => Effect.Effect<void>
  }
): Effect.Effect<Logger<Message, void>, never, Scope.Scope>

Creates a scoped logger that batches the output of another logger.

Details

The returned effect starts a scoped background process that periodically passes buffered outputs to flush. When the scope closes, the background process is interrupted and any remaining buffered entries are flushed.

Example (Batching logger output)

import { Duration, Effect, Logger } from "effect"

// Create a batched logger that flushes every 5 seconds
const batchedLogger = Logger.batched(Logger.formatJson, {
  window: Duration.seconds(5),
  flush: (messages) =>
    Effect.sync(() => {
      console.log(`Flushing ${messages.length} log entries:`)
      messages.forEach((msg, i) => console.log(`${i + 1}. ${msg}`))
    })
})

const program = Effect.gen(function*() {
  const logger = yield* batchedLogger

  yield* Effect.provide(
    Effect.all([
      Effect.log("Event 1"),
      Effect.log("Event 2"),
      Effect.log("Event 3"),
      Effect.sleep(Duration.seconds(6)), // Trigger flush
      Effect.log("Event 4")
    ]),
    Logger.layer([logger])
  )
})

// Remote batch logging example
const remoteBatchLogger = Logger.batched(Logger.formatStructured, {
  window: Duration.seconds(10),
  flush: (entries) =>
    Effect.sync(() => {
      // Send batch to remote logging service
      console.log(`Sending ${entries.length} log entries to remote service`)
    })
})
constructors
Source effect/Logger.ts:76450 lines
export const batched = dual<
  <Output>(options: {
    readonly window: Duration.Input
    readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>
  }) => <Message>(
    self: Logger<Message, Output>
  ) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>,
  <Message, Output>(
    self: Logger<Message, Output>,
    options: {
      readonly window: Duration.Input
      readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>
    }
  ) => Effect.Effect<Logger<Message, void>, never, Scope.Scope>
>(2, <Message, Output>(
  self: Logger<Message, Output>,
  options: {
    readonly window: Duration.Input
    readonly flush: (messages: Array<NoInfer<Output>>) => Effect.Effect<void>
  }
): Effect.Effect<Logger<Message, void>, never, Scope.Scope> =>
  effect.flatMap(effect.scope, (scope) => {
    let buffer: Array<Output> = []
    const flush = effect.suspend(() => {
      if (buffer.length === 0) {
        return effect.void
      }
      const arr = buffer
      buffer = []
      return options.flush(arr)
    })

    return effect.uninterruptibleMask((restore) =>
      restore(
        effect.sleep(options.window).pipe(
          effect.andThen(flush),
          effect.forever
        )
      ).pipe(
        effect.forkDetach,
        effect.flatMap((fiber) => effect.scopeAddFinalizerExit(scope, () => effect.fiberInterrupt(fiber))),
        effect.andThen(effect.addFinalizer(() => flush)),
        effect.as(
          effect.loggerMake((options) => {
            buffer.push(self.log(options))
          })
        )
      )
    )
  }))
Referenced by 1 symbols