Skip to content

Commit

Permalink
add Layer.annotateLogs & Layer.annotateSpans (#2836)
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart authored and gcanti committed May 26, 2024
1 parent ab60531 commit 244ffef
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .changeset/purple-mangos-grin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
"effect": minor
---

add Layer.annotateLogs & Layer.annotateSpans

This allows you to add log & span annotation to a Layer.

```ts
import { Effect, Layer } from "effect";

Layer.effectDiscard(Effect.log("hello")).pipe(
Layer.annotateLogs({
service: "my-service",
}),
);
```
22 changes: 22 additions & 0 deletions packages/effect/src/Layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,28 @@ export const isLayer: (u: unknown) => u is Layer<unknown, unknown, unknown> = in
*/
export const isFresh: <RIn, E, ROut>(self: Layer<ROut, E, RIn>) => boolean = internal.isFresh

/**
* @since 3.3.0
* @category tracing
*/
export const annotateLogs: {
(key: string, value: unknown): <A, E, R>(self: Layer<A, E, R>) => Layer<A, E, R>
(values: Record<string, unknown>): <A, E, R>(self: Layer<A, E, R>) => Layer<A, E, R>
<A, E, R>(self: Layer<A, E, R>, key: string, value: unknown): Layer<A, E, R>
<A, E, R>(self: Layer<A, E, R>, values: Record<string, unknown>): Layer<A, E, R>
} = internal.annotateLogs

/**
* @since 3.3.0
* @category tracing
*/
export const annotateSpans: {
(key: string, value: unknown): <A, E, R>(self: Layer<A, E, R>) => Layer<A, E, R>
(values: Record<string, unknown>): <A, E, R>(self: Layer<A, E, R>) => Layer<A, E, R>
<A, E, R>(self: Layer<A, E, R>, key: string, value: unknown): Layer<A, E, R>
<A, E, R>(self: Layer<A, E, R>, values: Record<string, unknown>): Layer<A, E, R>
} = internal.annotateSpans

/**
* Builds a layer into a scoped value.
*
Expand Down
63 changes: 63 additions & 0 deletions packages/effect/src/internal/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { FiberRef } from "../FiberRef.js"
import * as FiberRefsPatch from "../FiberRefsPatch.js"
import type { LazyArg } from "../Function.js"
import { dual, pipe } from "../Function.js"
import * as HashMap from "../HashMap.js"
import type * as Layer from "../Layer.js"
import { pipeArguments } from "../Pipeable.js"
import { hasProperty } from "../Predicate.js"
Expand Down Expand Up @@ -1108,10 +1109,72 @@ export const unwrapScoped = <A, E1, R1, E, R>(
return flatMap(scoped(tag, self), (context) => Context.get(context, tag))
}

// -----------------------------------------------------------------------------
// logging
// -----------------------------------------------------------------------------

export const annotateLogs = dual<
{
(key: string, value: unknown): <A, E, R>(self: Layer.Layer<A, E, R>) => Layer.Layer<A, E, R>
(
values: Record<string, unknown>
): <A, E, R>(self: Layer.Layer<A, E, R>) => Layer.Layer<A, E, R>
},
{
<A, E, R>(self: Layer.Layer<A, E, R>, key: string, value: unknown): Layer.Layer<A, E, R>
<A, E, R>(self: Layer.Layer<A, E, R>, values: Record<string, unknown>): Layer.Layer<A, E, R>
}
>(
(args) => isLayer(args[0]),
function<A, E, R>() {
const args = arguments
return fiberRefLocallyWith(
args[0] as Layer.Layer<A, E, R>,
core.currentLogAnnotations,
typeof args[1] === "string"
? HashMap.set(args[1], args[2])
: (annotations) =>
Object.entries(args[1] as Record<string, unknown>).reduce(
(acc, [key, value]) => HashMap.set(acc, key, value),
annotations
)
)
}
)

// -----------------------------------------------------------------------------
// tracing
// -----------------------------------------------------------------------------

export const annotateSpans = dual<
{
(key: string, value: unknown): <A, E, R>(self: Layer.Layer<A, E, R>) => Layer.Layer<A, E, R>
(
values: Record<string, unknown>
): <A, E, R>(self: Layer.Layer<A, E, R>) => Layer.Layer<A, E, R>
},
{
<A, E, R>(self: Layer.Layer<A, E, R>, key: string, value: unknown): Layer.Layer<A, E, R>
<A, E, R>(self: Layer.Layer<A, E, R>, values: Record<string, unknown>): Layer.Layer<A, E, R>
}
>(
(args) => isLayer(args[0]),
function<A, E, R>() {
const args = arguments
return fiberRefLocallyWith(
args[0] as Layer.Layer<A, E, R>,
core.currentTracerSpanAnnotations,
typeof args[1] === "string"
? HashMap.set(args[1], args[2])
: (annotations) =>
Object.entries(args[1] as Record<string, unknown>).reduce(
(acc, [key, value]) => HashMap.set(acc, key, value),
annotations
)
)
}
)

/** @internal */
export const withSpan: {
(
Expand Down

0 comments on commit 244ffef

Please sign in to comment.