Skip to content

Commit

Permalink
update WebSdk
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart committed Feb 5, 2025
1 parent 5872e34 commit b710d35
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 24 deletions.
16 changes: 5 additions & 11 deletions packages/opentelemetry/src/NodeSdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import type { SpanProcessor, TracerConfig } from "@opentelemetry/sdk-trace-base"
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node"
import type { NonEmptyReadonlyArray } from "effect/Array"
import * as Effect from "effect/Effect"
import type { LazyArg } from "effect/Function"
import { constant, type LazyArg } from "effect/Function"
import * as Layer from "effect/Layer"
import { isNonEmpty } from "./internal/utils.js"
import * as Logger from "./Logger.js"
import * as Metrics from "./Metrics.js"
import * as Resource from "./Resource.js"
Expand Down Expand Up @@ -79,16 +80,14 @@ export const layer: {
? evaluate as Effect.Effect<Configuration>
: Effect.sync(evaluate),
(config) => {
const ResourceLive = Resource.layerFromEnv(
config.resource ? Resource.configToAttributes(config.resource) : undefined
)
const ResourceLive = Resource.layerFromEnv(config.resource && Resource.configToAttributes(config.resource))

const TracerLive = isNonEmpty(config.spanProcessor)
? Layer.provide(Tracer.layer, layerTracerProvider(config.spanProcessor as any, config.tracerConfig))
? Layer.provide(Tracer.layer, layerTracerProvider(config.spanProcessor, config.tracerConfig))
: Layer.empty

const MetricsLive = isNonEmpty(config.metricReader)
? Metrics.layer(() => config.metricReader as any)
? Metrics.layer(constant(config.metricReader))
: Layer.empty

const LoggerLive = isNonEmpty(config.logRecordProcessor)
Expand All @@ -110,8 +109,3 @@ export const layer: {
* @category layer
*/
export const layerEmpty: Layer.Layer<Resource.Resource> = Resource.layerEmpty

// internal

const isNonEmpty = <A>(a: A | ReadonlyArray<A> | undefined): a is A | NonEmptyReadonlyArray<A> =>
a !== undefined && !(Array.isArray(a) && a.length === 0)
33 changes: 23 additions & 10 deletions packages/opentelemetry/src/WebSdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
* @since 1.0.0
*/
import type * as Resources from "@opentelemetry/resources"
import type { LoggerProviderConfig, LogRecordProcessor } from "@opentelemetry/sdk-logs"
import type { MetricReader } from "@opentelemetry/sdk-metrics"
import type { SpanProcessor, TracerConfig } from "@opentelemetry/sdk-trace-base"
import { WebTracerProvider } from "@opentelemetry/sdk-trace-web"
import type { NonEmptyReadonlyArray } from "effect/Array"
import * as Effect from "effect/Effect"
import type { LazyArg } from "effect/Function"
import { constant, type LazyArg } from "effect/Function"
import * as Layer from "effect/Layer"
import { isNonEmpty } from "./internal/utils.js"
import * as Logger from "./Logger.js"
import * as Metrics from "./Metrics.js"
import * as Resource from "./Resource.js"
import * as Tracer from "./Tracer.js"
Expand All @@ -21,6 +24,8 @@ export interface Configuration {
readonly spanProcessor?: SpanProcessor | ReadonlyArray<SpanProcessor> | undefined
readonly tracerConfig?: Omit<TracerConfig, "resource">
readonly metricReader?: MetricReader | ReadonlyArray<MetricReader> | undefined
readonly logRecordProcessor?: LogRecordProcessor | ReadonlyArray<LogRecordProcessor> | undefined
readonly loggerProviderConfig?: Omit<LoggerProviderConfig, "resource"> | undefined
readonly resource: {
readonly serviceName: string
readonly serviceVersion?: string
Expand Down Expand Up @@ -76,15 +81,23 @@ export const layer: {
: Effect.sync(evaluate),
(config) => {
const ResourceLive = Resource.layer(config.resource)
const TracerLive =
config.spanProcessor && !(Array.isArray(config.spanProcessor) && config.spanProcessor.length === 0) ?
Tracer.layer.pipe(Layer.provide(layerTracerProvider(config.spanProcessor as any, config.tracerConfig)))
: Layer.effectDiscard(Effect.void)
const MetricsLive =
config.metricReader && !(Array.isArray(config.metricReader) && config.metricReader.length === 0)
? Metrics.layer(() => config.metricReader as any)
: Layer.effectDiscard(Effect.void)
return Layer.merge(TracerLive, MetricsLive).pipe(

const TracerLive = isNonEmpty(config.spanProcessor)
? Layer.provide(Tracer.layer, layerTracerProvider(config.spanProcessor, config.tracerConfig))
: Layer.empty

const LoggerLive = isNonEmpty(config.logRecordProcessor)
? Layer.provide(
Logger.layerLoggerAdd,
Logger.layerLoggerProvider(config.logRecordProcessor, config.loggerProviderConfig)
)
: Layer.empty

const MetricsLive = isNonEmpty(config.metricReader)
? Metrics.layer(constant(config.metricReader))
: Layer.empty

return Layer.mergeAll(TracerLive, MetricsLive, LoggerLive).pipe(
Layer.provideMerge(ResourceLive)
)
}
Expand Down
14 changes: 11 additions & 3 deletions packages/opentelemetry/src/internal/utils.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import type * as OtelApi from "@opentelemetry/api"
import type { NonEmptyReadonlyArray } from "effect/Array"
import * as Inspectable from "effect/Inspectable"

const bigint1e9 = 1_000_000_000n

/** @internal */
export const nanosToHrTime = (timestamp: bigint): OtelApi.HrTime => {
return [Number(timestamp / bigint1e9), Number(timestamp % bigint1e9)]
}

export const recordToAttributes = (value: Record<string, unknown>): OtelApi.Attributes => {
return Object.entries(value).reduce((acc, [key, value]) => {
/** @internal */
export const recordToAttributes = (value: Record<string, unknown>): OtelApi.Attributes =>
Object.entries(value).reduce((acc, [key, value]) => {
acc[key] = unknownToAttributeValue(value)
return acc
}, {} as OtelApi.Attributes)
}

/** @internal */
export const unknownToAttributeValue = (value: unknown): OtelApi.AttributeValue => {
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
return value
Expand All @@ -21,3 +25,7 @@ export const unknownToAttributeValue = (value: unknown): OtelApi.AttributeValue
}
return Inspectable.toStringUnknown(value)
}

/** @internal */
export const isNonEmpty = <A>(a: A | ReadonlyArray<A> | undefined): a is A | NonEmptyReadonlyArray<A> =>
a !== undefined && !(Array.isArray(a) && a.length === 0)

0 comments on commit b710d35

Please sign in to comment.