@effect-app/infra 4.0.0-beta.209 → 4.0.0-beta.210

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 (47) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
  3. package/dist/Model/Repository/internal/internal.js +28 -21
  4. package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
  5. package/dist/QueueMaker/SQLQueue.js +37 -14
  6. package/dist/QueueMaker/memQueue.d.ts.map +1 -1
  7. package/dist/QueueMaker/memQueue.js +37 -14
  8. package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
  9. package/dist/QueueMaker/sbqueue.js +28 -13
  10. package/dist/RequestContext.d.ts +6 -6
  11. package/dist/RequestContext.js +7 -7
  12. package/dist/Store/Cosmos.d.ts.map +1 -1
  13. package/dist/Store/Cosmos.js +80 -66
  14. package/dist/Store/Disk.d.ts.map +1 -1
  15. package/dist/Store/Disk.js +48 -14
  16. package/dist/Store/Memory.d.ts.map +1 -1
  17. package/dist/Store/Memory.js +60 -35
  18. package/dist/Store/SQL/Pg.d.ts.map +1 -1
  19. package/dist/Store/SQL/Pg.js +80 -38
  20. package/dist/Store/SQL.d.ts.map +1 -1
  21. package/dist/Store/SQL.js +160 -77
  22. package/dist/adapters/SQL/Model.d.ts +4 -1
  23. package/dist/adapters/SQL/Model.d.ts.map +1 -1
  24. package/dist/adapters/SQL/Model.js +28 -37
  25. package/dist/api/internal/events.js +2 -2
  26. package/dist/api/routing/middleware/middleware.js +3 -3
  27. package/dist/api/routing.d.ts.map +1 -1
  28. package/dist/api/routing.js +12 -2
  29. package/dist/otel.d.ts +66 -0
  30. package/dist/otel.d.ts.map +1 -0
  31. package/dist/otel.js +56 -0
  32. package/package.json +6 -2
  33. package/src/Model/Repository/internal/internal.ts +82 -71
  34. package/src/QueueMaker/SQLQueue.ts +35 -13
  35. package/src/QueueMaker/memQueue.ts +35 -13
  36. package/src/QueueMaker/sbqueue.ts +26 -12
  37. package/src/RequestContext.ts +6 -6
  38. package/src/Store/Cosmos.ts +81 -66
  39. package/src/Store/Disk.ts +50 -16
  40. package/src/Store/Memory.ts +59 -34
  41. package/src/Store/SQL/Pg.ts +74 -40
  42. package/src/Store/SQL.ts +149 -83
  43. package/src/adapters/SQL/Model.ts +31 -36
  44. package/src/api/internal/events.ts +1 -1
  45. package/src/api/routing/middleware/middleware.ts +2 -2
  46. package/src/api/routing.ts +11 -1
  47. package/src/otel.ts +141 -0
package/src/otel.ts ADDED
@@ -0,0 +1,141 @@
1
+ /**
2
+ * OpenTelemetry semantic-convention helpers for span attributes.
3
+ *
4
+ * Aligns repository / queue / cache adapters with stable OTel semconv keys so
5
+ * downstream collectors and dashboards work without per-adapter mappings.
6
+ *
7
+ * - Database: https://opentelemetry.io/docs/specs/semconv/database/
8
+ * - Messaging: https://opentelemetry.io/docs/specs/semconv/messaging/
9
+ * - Cosmos DB: https://opentelemetry.io/docs/specs/semconv/database/cosmosdb/
10
+ */
11
+
12
+ import { Effect } from "effect-app"
13
+
14
+ export type DbSystem =
15
+ | "postgresql"
16
+ | "sqlite"
17
+ | "cosmosdb"
18
+ | "mongodb"
19
+ | "redis"
20
+ | "other_sql"
21
+ | "memory"
22
+ | "disk"
23
+
24
+ export interface DbSpanOptions {
25
+ /** OTel `db.operation.name` (e.g. `find`, `all`, `filter`, `set`). */
26
+ readonly operation: string
27
+ readonly system: DbSystem
28
+ /** Logical collection / table / container name. */
29
+ readonly collection: string
30
+ /** Tenant / namespace / database name. */
31
+ readonly namespace?: string | undefined
32
+ /** Application-level entity / model name (custom: `app.entity`). */
33
+ readonly entity?: string | undefined
34
+ /** Sanitized / parameterized query text. Never include bound values. */
35
+ readonly query?: string | undefined
36
+ /** Optional fragments merged into final attributes (e.g. id, partition). */
37
+ readonly extra?: Record<string, unknown> | undefined
38
+ }
39
+
40
+ const dbAttributes = (a: DbSpanOptions): Record<string, unknown> => ({
41
+ "db.system.name": a.system,
42
+ "db.operation.name": a.operation,
43
+ "db.collection.name": a.collection,
44
+ ...(a.namespace !== undefined && { "db.namespace": a.namespace }),
45
+ ...(a.query !== undefined && { "db.query.text": a.query }),
46
+ ...(a.entity !== undefined && { "app.entity": a.entity }),
47
+ ...a.extra
48
+ })
49
+
50
+ /**
51
+ * Wrap an effect with an OTel-semconv database span.
52
+ *
53
+ * Span name follows the low-cardinality convention: `<operation> <collection>`.
54
+ */
55
+ export const withDbSpan = (a: DbSpanOptions) =>
56
+ Effect.withSpan(
57
+ `${a.operation} ${a.collection}`,
58
+ { attributes: dbAttributes(a), kind: "client" as const },
59
+ { captureStackTrace: false }
60
+ )
61
+
62
+ /** Annotate the current span with response metrics from a DB call. */
63
+ export const annotateDbResponse = (m: {
64
+ readonly returnedRows?: number | undefined
65
+ readonly responseBytes?: number | undefined
66
+ }) =>
67
+ Effect.annotateCurrentSpan({
68
+ ...(m.returnedRows !== undefined && { "db.response.returned_rows": m.returnedRows }),
69
+ ...(m.responseBytes !== undefined && { "db.response.body.size": m.responseBytes })
70
+ })
71
+
72
+ /** Cosmos-specific response annotations. */
73
+ export const annotateCosmosResponse = (m: {
74
+ readonly requestCharge?: number | undefined
75
+ readonly returnedRows?: number | undefined
76
+ readonly responseBytes?: number | undefined
77
+ readonly statusCode?: number | undefined
78
+ }) =>
79
+ Effect.annotateCurrentSpan({
80
+ ...(m.requestCharge !== undefined && { "azure.cosmosdb.operation.request_charge": m.requestCharge }),
81
+ ...(m.statusCode !== undefined && { "db.response.status_code": String(m.statusCode) }),
82
+ ...(m.returnedRows !== undefined && { "db.response.returned_rows": m.returnedRows }),
83
+ ...(m.responseBytes !== undefined && { "db.response.body.size": m.responseBytes })
84
+ })
85
+
86
+ export type MessagingSystem =
87
+ | "servicebus"
88
+ | "rabbitmq"
89
+ | "kafka"
90
+ | "memory"
91
+ | "sql"
92
+
93
+ export type MessagingOperation =
94
+ | "publish"
95
+ | "create"
96
+ | "receive"
97
+ | "process"
98
+ | "settle"
99
+
100
+ export interface MessagingSpanOptions {
101
+ readonly operation: MessagingOperation
102
+ readonly system: MessagingSystem
103
+ /** Queue / topic name. */
104
+ readonly destination: string
105
+ readonly messageId?: string | undefined
106
+ readonly conversationId?: string | undefined
107
+ readonly bodySize?: number | undefined
108
+ readonly extra?: Record<string, unknown> | undefined
109
+ }
110
+
111
+ const messagingAttributes = (a: MessagingSpanOptions): Record<string, unknown> => ({
112
+ "messaging.system": a.system,
113
+ "messaging.operation.name": a.operation,
114
+ "messaging.destination.name": a.destination,
115
+ ...(a.messageId !== undefined && { "messaging.message.id": a.messageId }),
116
+ ...(a.conversationId !== undefined && { "messaging.message.conversation_id": a.conversationId }),
117
+ ...(a.bodySize !== undefined && { "messaging.message.body.size": a.bodySize }),
118
+ ...a.extra
119
+ })
120
+
121
+ /** Wrap an effect with an OTel-semconv messaging span. */
122
+ export const withMessagingSpan = (
123
+ a: MessagingSpanOptions,
124
+ kind: "producer" | "consumer"
125
+ ) =>
126
+ Effect.withSpan(
127
+ `${a.operation} ${a.destination}`,
128
+ { kind, attributes: messagingAttributes(a) },
129
+ { captureStackTrace: false }
130
+ )
131
+
132
+ /** Build messaging span options without wrapping (for Effect.fn / setupRequestContextWithCustomSpan). */
133
+ export const messagingSpanArgs = (
134
+ a: MessagingSpanOptions,
135
+ kind: "producer" | "consumer"
136
+ ) =>
137
+ ({
138
+ name: `${a.operation} ${a.destination}`,
139
+ kind,
140
+ attributes: messagingAttributes(a)
141
+ }) as const