@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.
- package/CHANGELOG.md +55 -0
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
- package/dist/Model/Repository/internal/internal.js +28 -21
- package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
- package/dist/QueueMaker/SQLQueue.js +37 -14
- package/dist/QueueMaker/memQueue.d.ts.map +1 -1
- package/dist/QueueMaker/memQueue.js +37 -14
- package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
- package/dist/QueueMaker/sbqueue.js +28 -13
- package/dist/RequestContext.d.ts +6 -6
- package/dist/RequestContext.js +7 -7
- package/dist/Store/Cosmos.d.ts.map +1 -1
- package/dist/Store/Cosmos.js +80 -66
- package/dist/Store/Disk.d.ts.map +1 -1
- package/dist/Store/Disk.js +48 -14
- package/dist/Store/Memory.d.ts.map +1 -1
- package/dist/Store/Memory.js +60 -35
- package/dist/Store/SQL/Pg.d.ts.map +1 -1
- package/dist/Store/SQL/Pg.js +80 -38
- package/dist/Store/SQL.d.ts.map +1 -1
- package/dist/Store/SQL.js +160 -77
- package/dist/adapters/SQL/Model.d.ts +4 -1
- package/dist/adapters/SQL/Model.d.ts.map +1 -1
- package/dist/adapters/SQL/Model.js +28 -37
- package/dist/api/internal/events.js +2 -2
- package/dist/api/routing/middleware/middleware.js +3 -3
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +12 -2
- package/dist/otel.d.ts +66 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/otel.js +56 -0
- package/package.json +6 -2
- package/src/Model/Repository/internal/internal.ts +82 -71
- package/src/QueueMaker/SQLQueue.ts +35 -13
- package/src/QueueMaker/memQueue.ts +35 -13
- package/src/QueueMaker/sbqueue.ts +26 -12
- package/src/RequestContext.ts +6 -6
- package/src/Store/Cosmos.ts +81 -66
- package/src/Store/Disk.ts +50 -16
- package/src/Store/Memory.ts +59 -34
- package/src/Store/SQL/Pg.ts +74 -40
- package/src/Store/SQL.ts +149 -83
- package/src/adapters/SQL/Model.ts +31 -36
- package/src/api/internal/events.ts +1 -1
- package/src/api/routing/middleware/middleware.ts +2 -2
- package/src/api/routing.ts +11 -1
- 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
|