@effect/opentelemetry 0.60.0 → 4.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/LICENSE +1 -1
  2. package/dist/{dts/Logger.d.ts → Logger.d.ts} +19 -13
  3. package/dist/Logger.d.ts.map +1 -0
  4. package/dist/Logger.js +76 -0
  5. package/dist/Logger.js.map +1 -0
  6. package/dist/Metrics.d.ts +76 -0
  7. package/dist/Metrics.d.ts.map +1 -0
  8. package/dist/Metrics.js +59 -0
  9. package/dist/Metrics.js.map +1 -0
  10. package/dist/{dts/NodeSdk.d.ts → NodeSdk.d.ts} +12 -9
  11. package/dist/NodeSdk.d.ts.map +1 -0
  12. package/dist/{esm/NodeSdk.js → NodeSdk.js} +23 -14
  13. package/dist/NodeSdk.js.map +1 -0
  14. package/dist/{dts/Resource.d.ts → Resource.d.ts} +10 -13
  15. package/dist/Resource.d.ts.map +1 -0
  16. package/dist/{esm/Resource.js → Resource.js} +12 -13
  17. package/dist/Resource.js.map +1 -0
  18. package/dist/Tracer.d.ts +129 -0
  19. package/dist/Tracer.d.ts.map +1 -0
  20. package/dist/Tracer.js +391 -0
  21. package/dist/Tracer.js.map +1 -0
  22. package/dist/{dts/WebSdk.d.ts → WebSdk.d.ts} +12 -9
  23. package/dist/WebSdk.d.ts.map +1 -0
  24. package/dist/WebSdk.js +41 -0
  25. package/dist/WebSdk.js.map +1 -0
  26. package/dist/index.d.ts +28 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/{esm/index.js → index.js} +4 -20
  29. package/dist/index.js.map +1 -0
  30. package/dist/internal/attributes.d.ts +2 -0
  31. package/dist/internal/attributes.d.ts.map +1 -0
  32. package/dist/internal/attributes.js +19 -0
  33. package/dist/internal/attributes.js.map +1 -0
  34. package/dist/{dts/internal → internal}/metrics.d.ts.map +1 -1
  35. package/dist/internal/metrics.js +406 -0
  36. package/dist/internal/metrics.js.map +1 -0
  37. package/dist/internal/utilities.d.ts +2 -0
  38. package/dist/internal/utilities.d.ts.map +1 -0
  39. package/dist/internal/utilities.js +3 -0
  40. package/dist/internal/utilities.js.map +1 -0
  41. package/package.json +70 -118
  42. package/src/Logger.ts +52 -55
  43. package/src/Metrics.ts +92 -18
  44. package/src/NodeSdk.ts +67 -64
  45. package/src/Resource.ts +16 -24
  46. package/src/Tracer.ts +469 -78
  47. package/src/WebSdk.ts +59 -51
  48. package/src/index.ts +7 -26
  49. package/src/internal/attributes.ts +21 -0
  50. package/src/internal/metrics.ts +381 -250
  51. package/src/internal/utilities.ts +5 -0
  52. package/Logger/package.json +0 -6
  53. package/Metrics/package.json +0 -6
  54. package/NodeSdk/package.json +0 -6
  55. package/Otlp/package.json +0 -6
  56. package/OtlpLogger/package.json +0 -6
  57. package/OtlpMetrics/package.json +0 -6
  58. package/OtlpResource/package.json +0 -6
  59. package/OtlpTracer/package.json +0 -6
  60. package/Resource/package.json +0 -6
  61. package/Tracer/package.json +0 -6
  62. package/WebSdk/package.json +0 -6
  63. package/dist/cjs/Logger.js +0 -85
  64. package/dist/cjs/Logger.js.map +0 -1
  65. package/dist/cjs/Metrics.js +0 -24
  66. package/dist/cjs/Metrics.js.map +0 -1
  67. package/dist/cjs/NodeSdk.js +0 -53
  68. package/dist/cjs/NodeSdk.js.map +0 -1
  69. package/dist/cjs/Otlp.js +0 -46
  70. package/dist/cjs/Otlp.js.map +0 -1
  71. package/dist/cjs/OtlpLogger.js +0 -158
  72. package/dist/cjs/OtlpLogger.js.map +0 -1
  73. package/dist/cjs/OtlpMetrics.js +0 -354
  74. package/dist/cjs/OtlpMetrics.js.map +0 -1
  75. package/dist/cjs/OtlpResource.js +0 -136
  76. package/dist/cjs/OtlpResource.js.map +0 -1
  77. package/dist/cjs/OtlpTracer.js +0 -229
  78. package/dist/cjs/OtlpTracer.js.map +0 -1
  79. package/dist/cjs/Resource.js +0 -75
  80. package/dist/cjs/Resource.js.map +0 -1
  81. package/dist/cjs/Tracer.js +0 -87
  82. package/dist/cjs/Tracer.js.map +0 -1
  83. package/dist/cjs/WebSdk.js +0 -42
  84. package/dist/cjs/WebSdk.js.map +0 -1
  85. package/dist/cjs/index.js +0 -30
  86. package/dist/cjs/index.js.map +0 -1
  87. package/dist/cjs/internal/metrics.js +0 -288
  88. package/dist/cjs/internal/metrics.js.map +0 -1
  89. package/dist/cjs/internal/otlpExporter.js +0 -81
  90. package/dist/cjs/internal/otlpExporter.js.map +0 -1
  91. package/dist/cjs/internal/tracer.js +0 -299
  92. package/dist/cjs/internal/tracer.js.map +0 -1
  93. package/dist/cjs/internal/utils.js +0 -34
  94. package/dist/cjs/internal/utils.js.map +0 -1
  95. package/dist/dts/Logger.d.ts.map +0 -1
  96. package/dist/dts/Metrics.d.ts +0 -29
  97. package/dist/dts/Metrics.d.ts.map +0 -1
  98. package/dist/dts/NodeSdk.d.ts.map +0 -1
  99. package/dist/dts/Otlp.d.ts +0 -31
  100. package/dist/dts/Otlp.d.ts.map +0 -1
  101. package/dist/dts/OtlpLogger.d.ts +0 -46
  102. package/dist/dts/OtlpLogger.d.ts.map +0 -1
  103. package/dist/dts/OtlpMetrics.d.ts +0 -40
  104. package/dist/dts/OtlpMetrics.d.ts.map +0 -1
  105. package/dist/dts/OtlpResource.d.ts +0 -104
  106. package/dist/dts/OtlpResource.d.ts.map +0 -1
  107. package/dist/dts/OtlpTracer.d.ts +0 -49
  108. package/dist/dts/OtlpTracer.d.ts.map +0 -1
  109. package/dist/dts/Resource.d.ts.map +0 -1
  110. package/dist/dts/Tracer.d.ts +0 -143
  111. package/dist/dts/Tracer.d.ts.map +0 -1
  112. package/dist/dts/WebSdk.d.ts.map +0 -1
  113. package/dist/dts/index.d.ts +0 -45
  114. package/dist/dts/index.d.ts.map +0 -1
  115. package/dist/dts/internal/otlpExporter.d.ts +0 -2
  116. package/dist/dts/internal/otlpExporter.d.ts.map +0 -1
  117. package/dist/dts/internal/tracer.d.ts +0 -2
  118. package/dist/dts/internal/tracer.d.ts.map +0 -1
  119. package/dist/dts/internal/utils.d.ts +0 -2
  120. package/dist/dts/internal/utils.d.ts.map +0 -1
  121. package/dist/esm/Logger.js +0 -75
  122. package/dist/esm/Logger.js.map +0 -1
  123. package/dist/esm/Metrics.js +0 -17
  124. package/dist/esm/Metrics.js.map +0 -1
  125. package/dist/esm/NodeSdk.js.map +0 -1
  126. package/dist/esm/Otlp.js +0 -38
  127. package/dist/esm/Otlp.js.map +0 -1
  128. package/dist/esm/OtlpLogger.js +0 -150
  129. package/dist/esm/OtlpLogger.js.map +0 -1
  130. package/dist/esm/OtlpMetrics.js +0 -346
  131. package/dist/esm/OtlpMetrics.js.map +0 -1
  132. package/dist/esm/OtlpResource.js +0 -124
  133. package/dist/esm/OtlpResource.js.map +0 -1
  134. package/dist/esm/OtlpTracer.js +0 -221
  135. package/dist/esm/OtlpTracer.js.map +0 -1
  136. package/dist/esm/Resource.js.map +0 -1
  137. package/dist/esm/Tracer.js +0 -80
  138. package/dist/esm/Tracer.js.map +0 -1
  139. package/dist/esm/WebSdk.js +0 -33
  140. package/dist/esm/WebSdk.js.map +0 -1
  141. package/dist/esm/index.js.map +0 -1
  142. package/dist/esm/internal/metrics.js +0 -278
  143. package/dist/esm/internal/metrics.js.map +0 -1
  144. package/dist/esm/internal/otlpExporter.js +0 -74
  145. package/dist/esm/internal/otlpExporter.js.map +0 -1
  146. package/dist/esm/internal/tracer.js +0 -290
  147. package/dist/esm/internal/tracer.js.map +0 -1
  148. package/dist/esm/internal/utils.js +0 -23
  149. package/dist/esm/internal/utils.js.map +0 -1
  150. package/dist/esm/package.json +0 -4
  151. package/index/package.json +0 -6
  152. package/src/Otlp.ts +0 -66
  153. package/src/OtlpLogger.ts +0 -258
  154. package/src/OtlpMetrics.ts +0 -571
  155. package/src/OtlpResource.ts +0 -232
  156. package/src/OtlpTracer.ts +0 -349
  157. package/src/internal/otlpExporter.ts +0 -124
  158. package/src/internal/tracer.ts +0 -437
  159. package/src/internal/utils.ts +0 -31
  160. /package/dist/{dts/internal → internal}/metrics.d.ts +0 -0
package/package.json CHANGED
@@ -1,15 +1,58 @@
1
1
  {
2
2
  "name": "@effect/opentelemetry",
3
- "version": "0.60.0",
4
- "description": "OpenTelemetry integration for Effect",
3
+ "type": "module",
4
+ "version": "4.0.0-beta.0",
5
5
  "license": "MIT",
6
+ "description": "OpenTelemetry integration for Effect",
7
+ "homepage": "https://effect.website",
6
8
  "repository": {
7
9
  "type": "git",
8
- "url": "https://github.com/Effect-TS/effect.git",
10
+ "url": "https://github.com/Effect-TS/effect-smol.git",
9
11
  "directory": "packages/opentelemetry"
10
12
  },
13
+ "bugs": {
14
+ "url": "https://github.com/Effect-TS/effect-smol/issues"
15
+ },
16
+ "tags": [
17
+ "opentelemetry",
18
+ "observability",
19
+ "tracing",
20
+ "metrics",
21
+ "typescript",
22
+ "algebraic-data-types",
23
+ "functional-programming"
24
+ ],
25
+ "keywords": [
26
+ "opentelemetry",
27
+ "observability",
28
+ "tracing",
29
+ "metrics",
30
+ "typescript",
31
+ "algebraic-data-types",
32
+ "functional-programming"
33
+ ],
34
+ "engines": {
35
+ "node": ">=18.0.0"
36
+ },
11
37
  "sideEffects": [],
12
- "homepage": "https://effect.website",
38
+ "exports": {
39
+ "./package.json": "./package.json",
40
+ ".": "./dist/index.js",
41
+ "./*": "./dist/*.js",
42
+ "./internal/*": null,
43
+ "./*/index": null
44
+ },
45
+ "files": [
46
+ "src/**/*.ts",
47
+ "dist/**/*.js",
48
+ "dist/**/*.js.map",
49
+ "dist/**/*.d.ts",
50
+ "dist/**/*.d.ts.map"
51
+ ],
52
+ "publishConfig": {
53
+ "access": "public",
54
+ "provenance": true
55
+ },
13
56
  "peerDependencies": {
14
57
  "@opentelemetry/api": "^1.9",
15
58
  "@opentelemetry/resources": "^2.0.0",
@@ -19,8 +62,7 @@
19
62
  "@opentelemetry/sdk-trace-node": "^2.0.0",
20
63
  "@opentelemetry/sdk-trace-web": "^2.0.0",
21
64
  "@opentelemetry/semantic-conventions": "^1.33.0",
22
- "@effect/platform": "^0.94.0",
23
- "effect": "^3.19.13"
65
+ "effect": "^4.0.0-beta.0"
24
66
  },
25
67
  "peerDependenciesMeta": {
26
68
  "@opentelemetry/api": {
@@ -45,118 +87,28 @@
45
87
  "optional": true
46
88
  }
47
89
  },
48
- "publishConfig": {
49
- "provenance": true
90
+ "devDependencies": {
91
+ "@opentelemetry/api": "^1.9.0",
92
+ "@opentelemetry/context-async-hooks": "^2.5.0",
93
+ "@opentelemetry/exporter-metrics-otlp-http": "0.211.0",
94
+ "@opentelemetry/exporter-prometheus": "^0.211.0",
95
+ "@opentelemetry/exporter-trace-otlp-http": "^0.211.0",
96
+ "@opentelemetry/otlp-exporter-base": "^0.211.0",
97
+ "@opentelemetry/resources": "^2.5.0",
98
+ "@opentelemetry/sdk-logs": "^0.211.0",
99
+ "@opentelemetry/sdk-metrics": "^2.5.0",
100
+ "@opentelemetry/sdk-trace-base": "^2.5.0",
101
+ "@opentelemetry/sdk-trace-node": "^2.5.0",
102
+ "@opentelemetry/sdk-trace-web": "^2.5.0",
103
+ "@opentelemetry/semantic-conventions": "^1.39.0"
50
104
  },
51
- "main": "./dist/cjs/index.js",
52
- "module": "./dist/esm/index.js",
53
- "types": "./dist/dts/index.d.ts",
54
- "exports": {
55
- "./package.json": "./package.json",
56
- ".": {
57
- "types": "./dist/dts/index.d.ts",
58
- "import": "./dist/esm/index.js",
59
- "default": "./dist/cjs/index.js"
60
- },
61
- "./Logger": {
62
- "types": "./dist/dts/Logger.d.ts",
63
- "import": "./dist/esm/Logger.js",
64
- "default": "./dist/cjs/Logger.js"
65
- },
66
- "./Metrics": {
67
- "types": "./dist/dts/Metrics.d.ts",
68
- "import": "./dist/esm/Metrics.js",
69
- "default": "./dist/cjs/Metrics.js"
70
- },
71
- "./NodeSdk": {
72
- "types": "./dist/dts/NodeSdk.d.ts",
73
- "import": "./dist/esm/NodeSdk.js",
74
- "default": "./dist/cjs/NodeSdk.js"
75
- },
76
- "./Otlp": {
77
- "types": "./dist/dts/Otlp.d.ts",
78
- "import": "./dist/esm/Otlp.js",
79
- "default": "./dist/cjs/Otlp.js"
80
- },
81
- "./OtlpLogger": {
82
- "types": "./dist/dts/OtlpLogger.d.ts",
83
- "import": "./dist/esm/OtlpLogger.js",
84
- "default": "./dist/cjs/OtlpLogger.js"
85
- },
86
- "./OtlpMetrics": {
87
- "types": "./dist/dts/OtlpMetrics.d.ts",
88
- "import": "./dist/esm/OtlpMetrics.js",
89
- "default": "./dist/cjs/OtlpMetrics.js"
90
- },
91
- "./OtlpResource": {
92
- "types": "./dist/dts/OtlpResource.d.ts",
93
- "import": "./dist/esm/OtlpResource.js",
94
- "default": "./dist/cjs/OtlpResource.js"
95
- },
96
- "./OtlpTracer": {
97
- "types": "./dist/dts/OtlpTracer.d.ts",
98
- "import": "./dist/esm/OtlpTracer.js",
99
- "default": "./dist/cjs/OtlpTracer.js"
100
- },
101
- "./Resource": {
102
- "types": "./dist/dts/Resource.d.ts",
103
- "import": "./dist/esm/Resource.js",
104
- "default": "./dist/cjs/Resource.js"
105
- },
106
- "./Tracer": {
107
- "types": "./dist/dts/Tracer.d.ts",
108
- "import": "./dist/esm/Tracer.js",
109
- "default": "./dist/cjs/Tracer.js"
110
- },
111
- "./WebSdk": {
112
- "types": "./dist/dts/WebSdk.d.ts",
113
- "import": "./dist/esm/WebSdk.js",
114
- "default": "./dist/cjs/WebSdk.js"
115
- },
116
- "./index": {
117
- "types": "./dist/dts/index.d.ts",
118
- "import": "./dist/esm/index.js",
119
- "default": "./dist/cjs/index.js"
120
- }
121
- },
122
- "typesVersions": {
123
- "*": {
124
- "Logger": [
125
- "./dist/dts/Logger.d.ts"
126
- ],
127
- "Metrics": [
128
- "./dist/dts/Metrics.d.ts"
129
- ],
130
- "NodeSdk": [
131
- "./dist/dts/NodeSdk.d.ts"
132
- ],
133
- "Otlp": [
134
- "./dist/dts/Otlp.d.ts"
135
- ],
136
- "OtlpLogger": [
137
- "./dist/dts/OtlpLogger.d.ts"
138
- ],
139
- "OtlpMetrics": [
140
- "./dist/dts/OtlpMetrics.d.ts"
141
- ],
142
- "OtlpResource": [
143
- "./dist/dts/OtlpResource.d.ts"
144
- ],
145
- "OtlpTracer": [
146
- "./dist/dts/OtlpTracer.d.ts"
147
- ],
148
- "Resource": [
149
- "./dist/dts/Resource.d.ts"
150
- ],
151
- "Tracer": [
152
- "./dist/dts/Tracer.d.ts"
153
- ],
154
- "WebSdk": [
155
- "./dist/dts/WebSdk.d.ts"
156
- ],
157
- "index": [
158
- "./dist/dts/index.d.ts"
159
- ]
160
- }
105
+ "scripts": {
106
+ "codegen": "effect-utils codegen",
107
+ "build": "tsc -b tsconfig.json && pnpm babel",
108
+ "build:tsgo": "tsgo -b tsconfig.json && pnpm babel",
109
+ "babel": "babel dist --plugins annotate-pure-calls --out-dir dist --source-maps",
110
+ "check": "tsc -b tsconfig.json",
111
+ "test": "vitest",
112
+ "coverage": "vitest --coverage"
161
113
  }
162
114
  }
package/src/Logger.ts CHANGED
@@ -4,30 +4,30 @@
4
4
  import * as Otel from "@opentelemetry/sdk-logs"
5
5
  import type { NonEmptyReadonlyArray } from "effect/Array"
6
6
  import * as Arr from "effect/Array"
7
- import * as Context from "effect/Context"
7
+ import * as Clock from "effect/Clock"
8
8
  import type { DurationInput } from "effect/Duration"
9
9
  import * as Effect from "effect/Effect"
10
- import * as FiberId from "effect/FiberId"
11
- import * as FiberRef from "effect/FiberRef"
12
- import * as FiberRefs from "effect/FiberRefs"
13
10
  import * as Layer from "effect/Layer"
14
11
  import * as Logger from "effect/Logger"
12
+ import * as LogLevel from "effect/LogLevel"
13
+ import * as Predicate from "effect/Predicate"
14
+ import * as ServiceMap from "effect/ServiceMap"
15
15
  import * as Tracer from "effect/Tracer"
16
- import { unknownToAttributeValue } from "./internal/utils.js"
17
- import { Resource } from "./Resource.js"
16
+ import { unknownToAttributeValue } from "./internal/attributes.ts"
17
+ import { Resource } from "./Resource.ts"
18
18
 
19
19
  /**
20
20
  * @since 1.0.0
21
- * @category tags
21
+ * @category Services
22
22
  */
23
- export class OtelLoggerProvider extends Context.Tag("@effect/opentelemetry/Logger/OtelLoggerProvider")<
23
+ export class OtelLoggerProvider extends ServiceMap.Service<
24
24
  OtelLoggerProvider,
25
25
  Otel.LoggerProvider
26
- >() {}
26
+ >()("@effect/opentelemetry/Logger/OtelLoggerProvider") {}
27
27
 
28
28
  /**
29
29
  * @since 1.0.0
30
- * @category constructors
30
+ * @category Constructors
31
31
  */
32
32
  export const make: Effect.Effect<
33
33
  Logger.Logger<unknown, void>,
@@ -35,40 +35,37 @@ export const make: Effect.Effect<
35
35
  OtelLoggerProvider
36
36
  > = Effect.gen(function*() {
37
37
  const loggerProvider = yield* OtelLoggerProvider
38
- const clock = yield* Effect.clock
38
+ const clock = yield* Clock.Clock
39
39
  const otelLogger = loggerProvider.getLogger("@effect/opentelemetry")
40
40
 
41
41
  return Logger.make((options) => {
42
- const now = options.date.getTime()
43
-
44
42
  const attributes: Record<string, any> = {
45
- fiberId: FiberId.threadName(options.fiberId)
43
+ fiberId: options.fiber.id
46
44
  }
47
45
 
48
- const maybeSpan = Context.getOption(
49
- FiberRefs.getOrDefault(options.context, FiberRef.currentContext),
50
- Tracer.ParentSpan
51
- )
46
+ const span = ServiceMap.getOrUndefined(options.fiber.services, Tracer.ParentSpan)
52
47
 
53
- if (maybeSpan._tag === "Some") {
54
- attributes.spanId = maybeSpan.value.spanId
55
- attributes.traceId = maybeSpan.value.traceId
48
+ if (Predicate.isNotUndefined(span)) {
49
+ attributes.spanId = span.spanId
50
+ attributes.traceId = span.traceId
56
51
  }
57
52
 
58
- for (const [key, value] of options.annotations) {
59
- attributes[key] = unknownToAttributeValue(value)
60
- }
61
- for (const span of options.spans) {
62
- attributes[`logSpan.${span.label}`] = `${now - span.startTime}ms`
63
- }
53
+ // TODO: add back after log spans / annotations
54
+ // for (const [key, value] of options.annotations) {
55
+ // attributes[key] = unknownToAttributeValue(value)
56
+ // }
57
+ // const now = options.date.getTime()
58
+ // for (const span of options.spans) {
59
+ // attributes[`logSpan.${span.label}`] = `${now - span.startTime}ms`
60
+ // }
64
61
 
65
62
  const message = Arr.ensure(options.message).map(unknownToAttributeValue)
66
63
  otelLogger.emit({
67
64
  body: message.length === 1 ? message[0] : message,
68
- severityText: options.logLevel.label,
69
- severityNumber: options.logLevel.ordinal,
65
+ severityText: options.logLevel,
66
+ severityNumber: LogLevel.getOrdinal(options.logLevel),
70
67
  timestamp: options.date,
71
- observedTimestamp: clock.unsafeCurrentTimeMillis(),
68
+ observedTimestamp: clock.currentTimeMillisUnsafe(),
72
69
  attributes
73
70
  })
74
71
  })
@@ -76,27 +73,27 @@ export const make: Effect.Effect<
76
73
 
77
74
  /**
78
75
  * @since 1.0.0
79
- * @category layers
76
+ * @category Layers
80
77
  */
81
- export const layerLoggerAdd: Layer.Layer<
82
- never,
83
- never,
84
- OtelLoggerProvider
85
- > = Logger.addEffect(make)
86
-
87
- /**
88
- * @since 1.0.0
89
- * @category layers
90
- */
91
- export const layerLoggerReplace: Layer.Layer<
92
- never,
93
- never,
94
- OtelLoggerProvider
95
- > = Logger.replaceEffect(Logger.defaultLogger, make)
78
+ export const layer = (options: {
79
+ /**
80
+ * If set to `true`, the OpenTelemetry logger will be merged with existing
81
+ * loggers in the application.
82
+ *
83
+ * If set to `false`, the OpenTelemetry logger will replace all existing
84
+ * loggers in the application.
85
+ *
86
+ * Defaults to `true`.
87
+ */
88
+ readonly mergeWithExisting?: boolean | undefined
89
+ }): Layer.Layer<never, never, OtelLoggerProvider> =>
90
+ Logger.layer([make], {
91
+ mergeWithExisting: options.mergeWithExisting ?? true
92
+ })
96
93
 
97
94
  /**
98
95
  * @since 1.0.0
99
- * @category layers
96
+ * @category Layers
100
97
  */
101
98
  export const layerLoggerProvider = (
102
99
  processor: Otel.LogRecordProcessor | NonEmptyReadonlyArray<Otel.LogRecordProcessor>,
@@ -104,10 +101,11 @@ export const layerLoggerProvider = (
104
101
  readonly shutdownTimeout?: DurationInput | undefined
105
102
  }
106
103
  ): Layer.Layer<OtelLoggerProvider, never, Resource> =>
107
- Layer.scoped(
104
+ Layer.effect(
108
105
  OtelLoggerProvider,
109
- Effect.flatMap(Resource, (resource) =>
110
- Effect.acquireRelease(
106
+ Effect.gen(function*() {
107
+ const resource = yield* Resource
108
+ return yield* Effect.acquireRelease(
111
109
  Effect.sync(() =>
112
110
  new Otel.LoggerProvider({
113
111
  ...(config ?? undefined),
@@ -116,12 +114,11 @@ export const layerLoggerProvider = (
116
114
  })
117
115
  ),
118
116
  (provider) =>
119
- Effect.promise(
120
- () => provider.forceFlush().then(() => provider.shutdown())
121
- ).pipe(
122
- Effect.ignoreLogged,
117
+ Effect.promise(() => provider.forceFlush().then(() => provider.shutdown())).pipe(
118
+ Effect.ignore,
123
119
  Effect.interruptible,
124
120
  Effect.timeoutOption(config?.shutdownTimeout ?? 3000)
125
121
  )
126
- ))
122
+ )
123
+ })
127
124
  )
package/src/Metrics.ts CHANGED
@@ -2,39 +2,113 @@
2
2
  * @since 1.0.0
3
3
  */
4
4
  import type { MetricProducer, MetricReader } from "@opentelemetry/sdk-metrics"
5
- import type { NonEmptyReadonlyArray } from "effect/Array"
5
+ import type * as Arr from "effect/Array"
6
6
  import type { DurationInput } from "effect/Duration"
7
- import type * as Effect from "effect/Effect"
7
+ import * as Effect from "effect/Effect"
8
8
  import type { LazyArg } from "effect/Function"
9
- import type { Layer } from "effect/Layer"
9
+ import * as Layer from "effect/Layer"
10
10
  import type * as Scope from "effect/Scope"
11
- import * as internal from "./internal/metrics.js"
12
- import type { Resource } from "./Resource.js"
11
+ import { MetricProducerImpl } from "./internal/metrics.ts"
12
+ import { Resource } from "./Resource.ts"
13
13
 
14
14
  /**
15
+ * Determines how metric values relate to the time interval over which they
16
+ * are aggregated.
17
+ *
18
+ * - `cumulative`: Reports total since a fixed start time. Each data point
19
+ * depends on all previous measurements. This is the default behavior.
20
+ *
21
+ * - `delta`: Reports changes since the last export. Each interval is
22
+ * independent with no dependency on previous measurements.
23
+ *
15
24
  * @since 1.0.0
16
- * @category producer
25
+ * @category Models
17
26
  */
18
- export const makeProducer: Effect.Effect<MetricProducer, never, Resource> = internal.makeProducer
27
+ export type TemporalityPreference = "cumulative" | "delta"
19
28
 
20
29
  /**
30
+ * Creates an OpenTelemetry metric producer from Effect metrics.
31
+ *
21
32
  * @since 1.0.0
22
- * @category producer
33
+ * @category Constructors
23
34
  */
24
- export const registerProducer: (
35
+ export const makeProducer = (temporality?: TemporalityPreference): Effect.Effect<MetricProducer, never, Resource> =>
36
+ Effect.gen(function*() {
37
+ const resource = yield* Resource
38
+ const services = yield* Effect.services<never>()
39
+ return new MetricProducerImpl(resource, services, temporality)
40
+ })
41
+
42
+ /**
43
+ * Registers a metric producer with one or more metric readers.
44
+ *
45
+ * @since 1.0.0
46
+ * @category Constructors
47
+ */
48
+ export const registerProducer = (
25
49
  self: MetricProducer,
26
- metricReader: LazyArg<MetricReader | NonEmptyReadonlyArray<MetricReader>>
27
- ) => Effect.Effect<Array<any>, never, Scope.Scope> = internal.registerProducer
50
+ metricReader: LazyArg<MetricReader | Arr.NonEmptyReadonlyArray<MetricReader>>,
51
+ options?: {
52
+ readonly shutdownTimeout?: DurationInput | undefined
53
+ }
54
+ ): Effect.Effect<Array<any>, never, Scope.Scope> =>
55
+ Effect.acquireRelease(
56
+ Effect.sync(() => {
57
+ const reader = metricReader()
58
+ const readers: Array<MetricReader> = Array.isArray(reader) ? reader : [reader] as any
59
+ readers.forEach((reader) => reader.setMetricProducer(self))
60
+ return readers
61
+ }),
62
+ (readers) =>
63
+ Effect.promise(() =>
64
+ Promise.all(
65
+ readers.map((reader) => reader.shutdown())
66
+ )
67
+ ).pipe(
68
+ Effect.ignore,
69
+ Effect.interruptible,
70
+ Effect.timeoutOption(options?.shutdownTimeout ?? 3000)
71
+ )
72
+ )
28
73
 
29
74
  /**
75
+ * Creates a Layer that registers a metric producer with metric readers.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * import { Metrics } from "@effect/opentelemetry"
80
+ * import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics"
81
+ * import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http"
82
+ *
83
+ * const metricExporter = new OTLPMetricExporter({ url: "<your-otel-url>" })
84
+ *
85
+ * // Use delta temporality for backends like Datadog or Dynatrace
86
+ * const metricsLayer = Metrics.layer(
87
+ * () => new PeriodicExportingMetricReader({
88
+ * exporter: metricExporter,
89
+ * exportIntervalMillis: 10000
90
+ * }),
91
+ * { temporality: "delta" }
92
+ * )
93
+ *
94
+ * // Use cumulative temporality for backends like Prometheus (default)
95
+ * const cumulativeLayer = Metrics.layer(
96
+ * () => new PeriodicExportingMetricReader({ exporter: metricExporter }),
97
+ * { temporality: "cumulative" }
98
+ * )
99
+ * ```
100
+ *
30
101
  * @since 1.0.0
31
- * @category layers
102
+ * @category Layers
32
103
  */
33
- export const layer: (
34
- evaluate: LazyArg<MetricReader | NonEmptyReadonlyArray<MetricReader>>,
104
+ export const layer = (
105
+ evaluate: LazyArg<MetricReader | Arr.NonEmptyReadonlyArray<MetricReader>>,
35
106
  options?: {
36
- readonly shutdownTimeout?:
37
- | DurationInput
38
- | undefined
107
+ readonly shutdownTimeout?: DurationInput | undefined
108
+ readonly temporality?: TemporalityPreference | undefined
39
109
  }
40
- ) => Layer<never, never, Resource> = internal.layer
110
+ ): Layer.Layer<never, never, Resource> =>
111
+ Layer.effectDiscard(Effect.flatMap(
112
+ makeProducer(options?.temporality),
113
+ (producer) => registerProducer(producer, evaluate, options)
114
+ ))