Hyperlinkv0.8.0-beta.28

Layer

Layer.withSpanconsteffect/Layer.ts:2627
(name: string, options?: SpanOptions): <A, E, R>(
  self: Layer<A, E, R>
) => Layer<A, E, Exclude<R, Tracer.ParentSpan>>
<A, E, R>(
  self: Layer<A, E, R>,
  name: string,
  options?: SpanOptions
): Layer<A, E, Exclude<R, Tracer.ParentSpan>>

Wraps a Layer with a new tracing span, making all operations in the layer constructor part of the named trace span.

Details

This creates a new span for the layer's construction and execution. The span is automatically ended when the layer's scope is closed. This is useful for tracking the lifecycle and performance of layer initialization.

Example (Wrapping a layer with a span)

import { Context, Effect, Layer } from "effect"

class Database extends Context.Service<Database, {
  readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}

class Logger extends Context.Service<Logger, {
  readonly log: (msg: string) => Effect.Effect<void>
}>()("Logger") {}

// Create layers with tracing
const databaseLayer = Layer.effect(Database, Effect.gen(function*() {
  yield* Effect.log("Connecting to database")
  yield* Effect.sleep("100 millis")
  return {
    query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`Result: ${sql}`))
  }
})).pipe(Layer.withSpan("database-initialization", {
  attributes: { dbType: "postgres" }
}))

const loggerLayer = Layer.succeed(Logger, {
  log: Effect.fn("Logger.log")((msg: string) => Effect.sync(() => console.log(msg)))
}).pipe(Layer.withSpan("logger-initialization"))

// Combine traced layers
const appLayer = Layer.mergeAll(databaseLayer, loggerLayer).pipe(
  Layer.withSpan("app-initialization", {
    onEnd: (span, exit) =>
      Effect.sync(() => {
        console.log(`Application initialization completed: ${exit._tag}`)
      })
  })
)

const program = Effect.gen(function*() {
  const database = yield* Database
  const logger = yield* Logger

  yield* logger.log("Application ready")
  return yield* database.query("SELECT * FROM users")
}).pipe(Effect.provide(appLayer))
tracing
Source effect/Layer.ts:262743 lines
export const withSpan: {
  (
    name: string,
    options?: SpanOptions
  ): <A, E, R>(
    self: Layer<A, E, R>
  ) => Layer<A, E, Exclude<R, Tracer.ParentSpan>>
  <A, E, R>(
    self: Layer<A, E, R>,
    name: string,
    options?: SpanOptions
  ): Layer<A, E, Exclude<R, Tracer.ParentSpan>>
} = function() {
  const dataFirst = typeof arguments[0] !== "string"
  const name = dataFirst ? arguments[1] : arguments[0]
  const options = internalTracer.addSpanStackTrace(dataFirst ? arguments[2] : arguments[1]) as SpanOptions
  if (dataFirst) {
    const self = arguments[0]
    return unwrap(
      internalEffect.map(
        options?.onEnd !== undefined
          ? internalEffect.tap(
            internalEffect.makeSpanScoped(name, options),
            (span) => internalEffect.addFinalizer((exit) => options.onEnd!(span, exit))
          )
          : internalEffect.makeSpanScoped(name, options),
        (span) => withParentSpan(self, span)
      )
    )
  }
  return (self: Layer<any, any, any>) =>
    unwrap(
      internalEffect.map(
        options?.onEnd !== undefined
          ? internalEffect.tap(
            internalEffect.makeSpanScoped(name, options),
            (span) => internalEffect.addFinalizer((exit) => options.onEnd!(span, exit))
          )
          : internalEffect.makeSpanScoped(name, options),
        (span) => withParentSpan(self, span)
      )
    )
} as any