@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/Store/SQL.ts CHANGED
@@ -7,6 +7,7 @@ import { SqlClient } from "effect/unstable/sql"
7
7
  import { OptimisticConcurrencyException } from "../errors.js"
8
8
  import { InfraLogger } from "../logger.js"
9
9
  import type { FieldValues } from "../Model/filter/types.js"
10
+ import { type DbSystem, withDbSpan } from "../otel.js"
10
11
  import { storeId } from "./Memory.js"
11
12
  import { type FilterArgs, type PersistenceModelType, type StorageConfig, type Store, type StoreConfig, StoreMaker } from "./service.js"
12
13
  import { buildWhereSQLQuery, logQuery, type SQLDialect, sqliteDialect } from "./SQL/query.js"
@@ -50,7 +51,7 @@ const parseSelectRow = (
50
51
  return result
51
52
  }
52
53
 
53
- function makeSQLStoreInt(dialect: SQLDialect, jsonColumnType: string) {
54
+ function makeSQLStoreInt(system: DbSystem, dialect: SQLDialect, jsonColumnType: string) {
54
55
  return Effect.fnUntraced(function*({ prefix }: StorageConfig) {
55
56
  const sql = yield* SqlClient.SqlClient
56
57
  return {
@@ -175,25 +176,28 @@ function makeSQLStoreInt(dialect: SQLDialect, jsonColumnType: string) {
175
176
  seedNamespace: (ns) => seedNamespace(ns),
176
177
 
177
178
  all: resolveNamespace.pipe(
178
- Effect.flatMap((ns) =>
179
- exec(`SELECT id, _etag, data FROM "${tableName}" WHERE _namespace = ?`, [ns])
179
+ Effect.flatMap((ns) => {
180
+ const sqlText = `SELECT id, _etag, data FROM "${tableName}" WHERE _namespace = ?`
181
+ return exec(sqlText, [ns])
180
182
  .pipe(
181
183
  Effect.map((rows) => (rows as any[]).map((r) => parseRow<Encoded>(r, idKey, defaultValues))),
182
- Effect.withSpan("SQL.all [effect-app/infra/Store]", {
183
- attributes: {
184
- "repository.table_name": tableName,
185
- "repository.model_name": name,
186
- "repository.namespace": ns
187
- }
188
- }, { captureStackTrace: false })
184
+ withDbSpan({
185
+ operation: "all",
186
+ system,
187
+ collection: tableName,
188
+ namespace: ns,
189
+ entity: name,
190
+ query: sqlText
191
+ })
189
192
  )
190
- )
193
+ })
191
194
  ),
192
195
 
193
196
  find: (id) =>
194
197
  resolveNamespace.pipe(
195
- Effect.flatMap((ns) =>
196
- exec(`SELECT id, _etag, data FROM "${tableName}" WHERE id = ? AND _namespace = ?`, [id, ns])
198
+ Effect.flatMap((ns) => {
199
+ const sqlText = `SELECT id, _etag, data FROM "${tableName}" WHERE id = ? AND _namespace = ?`
200
+ return exec(sqlText, [id, ns])
197
201
  .pipe(
198
202
  Effect.map((rows) => {
199
203
  const row = (rows as any[])[0]
@@ -201,11 +205,17 @@ function makeSQLStoreInt(dialect: SQLDialect, jsonColumnType: string) {
201
205
  ? Option.some(parseRow<Encoded>(row, idKey, defaultValues))
202
206
  : Option.none()
203
207
  }),
204
- Effect.withSpan("SQL.find [effect-app/infra/Store]", {
205
- attributes: { "repository.table_name": tableName, "repository.model_name": name, id }
206
- }, { captureStackTrace: false })
208
+ withDbSpan({
209
+ operation: "find",
210
+ system,
211
+ collection: tableName,
212
+ namespace: ns,
213
+ entity: name,
214
+ query: sqlText,
215
+ extra: { "app.entity.id": id }
216
+ })
207
217
  )
208
- )
218
+ })
209
219
  ),
210
220
 
211
221
  filter: <U extends keyof Encoded = never>(f: FilterArgs<Encoded, U>) => {
@@ -260,6 +270,7 @@ function makeSQLStoreInt(dialect: SQLDialect, jsonColumnType: string) {
260
270
  .pipe(
261
271
  Effect
262
272
  .tap((q) => logQuery(q)),
273
+ Effect.tap((q) => Effect.annotateCurrentSpan({ "db.query.text": q.sql })),
263
274
  Effect.flatMap((q) =>
264
275
  exec(q.sql, q.params).pipe(
265
276
  Effect.map((rows) => {
@@ -279,9 +290,13 @@ function makeSQLStoreInt(dialect: SQLDialect, jsonColumnType: string) {
279
290
  })
280
291
  )
281
292
  ),
282
- Effect.withSpan("SQL.filter [effect-app/infra/Store]", {
283
- attributes: { "repository.table_name": tableName, "repository.model_name": name }
284
- }, { captureStackTrace: false })
293
+ withDbSpan({
294
+ operation: "filter",
295
+ system,
296
+ collection: tableName,
297
+ namespace: ns,
298
+ entity: name
299
+ })
285
300
  )
286
301
  ))
287
302
  },
@@ -289,52 +304,71 @@ function makeSQLStoreInt(dialect: SQLDialect, jsonColumnType: string) {
289
304
  set: (e) =>
290
305
  resolveNamespace.pipe(Effect.flatMap((ns) =>
291
306
  setInternal(e, ns).pipe(
292
- Effect.withSpan("SQL.set [effect-app/infra/Store]", {
293
- attributes: { "repository.table_name": tableName, "repository.model_name": name, id: e[idKey] }
294
- }, { captureStackTrace: false })
307
+ withDbSpan({
308
+ operation: "set",
309
+ system,
310
+ collection: tableName,
311
+ namespace: ns,
312
+ entity: name,
313
+ extra: { "app.entity.id": e[idKey] }
314
+ })
295
315
  )
296
316
  )),
297
317
 
298
318
  batchSet: (items) =>
299
319
  resolveNamespace.pipe(Effect.flatMap((ns) =>
300
320
  bulkSetInternal(items, ns).pipe(
301
- Effect.withSpan("SQL.batchSet [effect-app/infra/Store]", {
302
- attributes: { "repository.table_name": tableName, "repository.model_name": name }
303
- }, { captureStackTrace: false })
321
+ withDbSpan({
322
+ operation: "batchSet",
323
+ system,
324
+ collection: tableName,
325
+ namespace: ns,
326
+ entity: name
327
+ })
304
328
  )
305
329
  )),
306
330
 
307
331
  bulkSet: (items) =>
308
332
  resolveNamespace.pipe(Effect.flatMap((ns) =>
309
333
  bulkSetInternal(items, ns).pipe(
310
- Effect.withSpan("SQL.bulkSet [effect-app/infra/Store]", {
311
- attributes: { "repository.table_name": tableName, "repository.model_name": name }
312
- }, { captureStackTrace: false })
334
+ withDbSpan({
335
+ operation: "bulkSet",
336
+ system,
337
+ collection: tableName,
338
+ namespace: ns,
339
+ entity: name
340
+ })
313
341
  )
314
342
  )),
315
343
 
316
344
  batchRemove: (ids) => {
317
345
  const placeholders = ids.map(() => "?").join(", ")
318
- return resolveNamespace.pipe(Effect.flatMap((ns) =>
319
- exec(
320
- `DELETE FROM "${tableName}" WHERE id IN (${placeholders}) AND _namespace = ?`,
321
- [...ids, ns]
322
- )
346
+ return resolveNamespace.pipe(Effect.flatMap((ns) => {
347
+ const sqlText = `DELETE FROM "${tableName}" WHERE id IN (${placeholders}) AND _namespace = ?`
348
+ return exec(sqlText, [...ids, ns])
323
349
  .pipe(
324
350
  Effect.asVoid,
325
- Effect.withSpan("SQL.batchRemove [effect-app/infra/Store]", {
326
- attributes: { "repository.table_name": tableName, "repository.model_name": name }
327
- }, { captureStackTrace: false })
351
+ withDbSpan({
352
+ operation: "batchRemove",
353
+ system,
354
+ collection: tableName,
355
+ namespace: ns,
356
+ entity: name,
357
+ query: sqlText
358
+ })
328
359
  )
329
- ))
360
+ }))
330
361
  },
331
362
 
332
363
  queryRaw: (query) =>
333
364
  s.all.pipe(
334
365
  Effect.map(query.memory),
335
- Effect.withSpan("SQL.queryRaw [effect-app/infra/Store]", {
336
- attributes: { "repository.table_name": tableName, "repository.model_name": name }
337
- }, { captureStackTrace: false })
366
+ withDbSpan({
367
+ operation: "queryRaw",
368
+ system,
369
+ collection: tableName,
370
+ entity: name
371
+ })
338
372
  )
339
373
  }
340
374
 
@@ -487,24 +521,27 @@ function makeSQLiteStorePerNs(
487
521
  const s: Store<IdKey, Encoded> = {
488
522
  seedNamespace: (ns) => seedNamespace(ns),
489
523
 
490
- all: resolveNamespace.pipe(Effect.flatMap((ns) =>
491
- exec(ns, `SELECT id, _etag, data FROM "${tableName}"`)
524
+ all: resolveNamespace.pipe(Effect.flatMap((ns) => {
525
+ const sqlText = `SELECT id, _etag, data FROM "${tableName}"`
526
+ return exec(ns, sqlText)
492
527
  .pipe(
493
528
  Effect.map((rows) => (rows as any[]).map((r) => parseRow<Encoded>(r, idKey, defaultValues))),
494
- Effect.withSpan("SQLite.all [effect-app/infra/Store]", {
495
- attributes: {
496
- "repository.table_name": tableName,
497
- "repository.model_name": name,
498
- "repository.namespace": ns
499
- }
500
- }, { captureStackTrace: false })
529
+ withDbSpan({
530
+ operation: "all",
531
+ system: "sqlite",
532
+ collection: tableName,
533
+ namespace: ns,
534
+ entity: name,
535
+ query: sqlText
536
+ })
501
537
  )
502
- )),
538
+ })),
503
539
 
504
540
  find: (id) =>
505
541
  resolveNamespace.pipe(
506
- Effect.flatMap((ns) =>
507
- exec(ns, `SELECT id, _etag, data FROM "${tableName}" WHERE id = ?`, [id])
542
+ Effect.flatMap((ns) => {
543
+ const sqlText = `SELECT id, _etag, data FROM "${tableName}" WHERE id = ?`
544
+ return exec(ns, sqlText, [id])
508
545
  .pipe(
509
546
  Effect.map((rows) => {
510
547
  const row = (rows as any[])[0]
@@ -512,11 +549,17 @@ function makeSQLiteStorePerNs(
512
549
  ? Option.some(parseRow<Encoded>(row, idKey, defaultValues))
513
550
  : Option.none()
514
551
  }),
515
- Effect.withSpan("SQLite.find [effect-app/infra/Store]", {
516
- attributes: { "repository.table_name": tableName, "repository.model_name": name, id }
517
- }, { captureStackTrace: false })
552
+ withDbSpan({
553
+ operation: "find",
554
+ system: "sqlite",
555
+ collection: tableName,
556
+ namespace: ns,
557
+ entity: name,
558
+ query: sqlText,
559
+ extra: { "app.entity.id": id }
560
+ })
518
561
  )
519
- )
562
+ })
520
563
  ),
521
564
 
522
565
  filter: <U extends keyof Encoded = never>(f: FilterArgs<Encoded, U>) => {
@@ -550,6 +593,7 @@ function makeSQLiteStorePerNs(
550
593
  .pipe(
551
594
  Effect
552
595
  .tap((q) => logQuery(q)),
596
+ Effect.tap((q) => Effect.annotateCurrentSpan({ "db.query.text": q.sql })),
553
597
  Effect.flatMap((q) =>
554
598
  exec(ns, q.sql, q.params).pipe(
555
599
  Effect.map((rows) => {
@@ -569,9 +613,13 @@ function makeSQLiteStorePerNs(
569
613
  })
570
614
  )
571
615
  ),
572
- Effect.withSpan("SQLite.filter [effect-app/infra/Store]", {
573
- attributes: { "repository.table_name": tableName, "repository.model_name": name }
574
- }, { captureStackTrace: false })
616
+ withDbSpan({
617
+ operation: "filter",
618
+ system: "sqlite",
619
+ collection: tableName,
620
+ namespace: ns,
621
+ entity: name
622
+ })
575
623
  )
576
624
  ))
577
625
  },
@@ -579,53 +627,71 @@ function makeSQLiteStorePerNs(
579
627
  set: (e) =>
580
628
  resolveNamespace.pipe(Effect.flatMap((ns) =>
581
629
  setInternal(e, ns).pipe(
582
- Effect.withSpan("SQLite.set [effect-app/infra/Store]", {
583
- attributes: { "repository.table_name": tableName, "repository.model_name": name, id: e[idKey] }
584
- }, { captureStackTrace: false })
630
+ withDbSpan({
631
+ operation: "set",
632
+ system: "sqlite",
633
+ collection: tableName,
634
+ namespace: ns,
635
+ entity: name,
636
+ extra: { "app.entity.id": e[idKey] }
637
+ })
585
638
  )
586
639
  )),
587
640
 
588
641
  batchSet: (items) =>
589
642
  resolveNamespace.pipe(Effect.flatMap((ns) =>
590
643
  bulkSetInternal(items, ns).pipe(
591
- Effect.withSpan("SQLite.batchSet [effect-app/infra/Store]", {
592
- attributes: { "repository.table_name": tableName, "repository.model_name": name }
593
- }, { captureStackTrace: false })
644
+ withDbSpan({
645
+ operation: "batchSet",
646
+ system: "sqlite",
647
+ collection: tableName,
648
+ namespace: ns,
649
+ entity: name
650
+ })
594
651
  )
595
652
  )),
596
653
 
597
654
  bulkSet: (items) =>
598
655
  resolveNamespace.pipe(Effect.flatMap((ns) =>
599
656
  bulkSetInternal(items, ns).pipe(
600
- Effect.withSpan("SQLite.bulkSet [effect-app/infra/Store]", {
601
- attributes: { "repository.table_name": tableName, "repository.model_name": name }
602
- }, { captureStackTrace: false })
657
+ withDbSpan({
658
+ operation: "bulkSet",
659
+ system: "sqlite",
660
+ collection: tableName,
661
+ namespace: ns,
662
+ entity: name
663
+ })
603
664
  )
604
665
  )),
605
666
 
606
667
  batchRemove: (ids) => {
607
668
  const placeholders = ids.map(() => "?").join(", ")
608
- return resolveNamespace.pipe(Effect.flatMap((ns) =>
609
- exec(
610
- ns,
611
- `DELETE FROM "${tableName}" WHERE id IN (${placeholders})`,
612
- [...ids]
613
- )
669
+ return resolveNamespace.pipe(Effect.flatMap((ns) => {
670
+ const sqlText = `DELETE FROM "${tableName}" WHERE id IN (${placeholders})`
671
+ return exec(ns, sqlText, [...ids])
614
672
  .pipe(
615
673
  Effect.asVoid,
616
- Effect.withSpan("SQLite.batchRemove [effect-app/infra/Store]", {
617
- attributes: { "repository.table_name": tableName, "repository.model_name": name }
618
- }, { captureStackTrace: false })
674
+ withDbSpan({
675
+ operation: "batchRemove",
676
+ system: "sqlite",
677
+ collection: tableName,
678
+ namespace: ns,
679
+ entity: name,
680
+ query: sqlText
681
+ })
619
682
  )
620
- ))
683
+ }))
621
684
  },
622
685
 
623
686
  queryRaw: (query) =>
624
687
  s.all.pipe(
625
688
  Effect.map(query.memory),
626
- Effect.withSpan("SQLite.queryRaw [effect-app/infra/Store]", {
627
- attributes: { "repository.table_name": tableName, "repository.model_name": name }
628
- }, { captureStackTrace: false })
689
+ withDbSpan({
690
+ operation: "queryRaw",
691
+ system: "sqlite",
692
+ collection: tableName,
693
+ entity: name
694
+ })
629
695
  )
630
696
  }
631
697
 
@@ -664,5 +730,5 @@ export function SQLiteStoreLayer(
664
730
  )
665
731
  }
666
732
  return StoreMaker
667
- .toLayer(makeSQLStoreInt(sqliteDialect, "JSON")(cfg))
733
+ .toLayer(makeSQLStoreInt("sqlite", sqliteDialect, "JSON")(cfg))
668
734
  }
@@ -24,6 +24,7 @@ import * as VariantSchema from "effect/unstable/schema/VariantSchema"
24
24
  import { SqlClient } from "effect/unstable/sql/SqlClient"
25
25
  import * as SqlResolver from "effect/unstable/sql/SqlResolver"
26
26
  import * as SqlSchema from "effect/unstable/sql/SqlSchema"
27
+ import { type DbSystem, withDbSpan } from "../../otel.js"
27
28
 
28
29
  const {
29
30
  Class,
@@ -596,6 +597,7 @@ export const makeRepository = <
596
597
  readonly spanPrefix: string
597
598
  readonly idColumn: Id
598
599
  readonly versionColumn?: string | undefined
600
+ readonly dbSystem?: DbSystem | undefined
599
601
  }): Effect.Effect<
600
602
  {
601
603
  readonly insert: (
@@ -629,6 +631,15 @@ export const makeRepository = <
629
631
  const idSchema = Model.fields[options.idColumn] as Schema.Top
630
632
  const idColumn = options.idColumn as string
631
633
  const versionColumn = options.versionColumn
634
+ const system: DbSystem = options.dbSystem ?? "other_sql"
635
+ const opSpan = (operation: string, idValue?: unknown) =>
636
+ withDbSpan({
637
+ operation,
638
+ system,
639
+ collection: options.tableName,
640
+ entity: options.spanPrefix,
641
+ ...(idValue !== undefined && { extra: { "app.entity.id": idValue } })
642
+ })
632
643
 
633
644
  const insertSchema = SqlSchema.findOne({
634
645
  Request: Model.insert,
@@ -650,9 +661,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
650
661
  ): Effect.Effect<S["Type"], Schema.SchemaError, S["DecodingServices"] | S["insert"]["EncodingServices"]> =>
651
662
  insertSchema(insert).pipe(
652
663
  Effect.catchTag("NoSuchElementError", Effect.die),
653
- Effect.withSpan(`${options.spanPrefix}.insert`, {}, {
654
- captureStackTrace: false
655
- })
664
+ opSpan("insert")
656
665
  ) as any
657
666
 
658
667
  const insertVoidSchema = SqlSchema.void({
@@ -663,9 +672,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
663
672
  insert: S["insert"]["Type"]
664
673
  ): Effect.Effect<void, Schema.SchemaError, S["insert"]["EncodingServices"]> =>
665
674
  insertVoidSchema(insert).pipe(
666
- Effect.withSpan(`${options.spanPrefix}.insertVoid`, {}, {
667
- captureStackTrace: false
668
- })
675
+ opSpan("insertVoid")
669
676
  ) as any
670
677
 
671
678
  const updateSchema = SqlSchema.findOne({
@@ -712,11 +719,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = ${request[idCol
712
719
  ): Effect.Effect<S["Type"], Schema.SchemaError, S["DecodingServices"] | S["update"]["EncodingServices"]> =>
713
720
  updateSchema(update).pipe(
714
721
  Effect.catchTag("NoSuchElementError", Effect.die),
715
- Effect.withSpan(`${options.spanPrefix}.update`, {
716
- attributes: { id: (update as any)[idColumn] }
717
- }, {
718
- captureStackTrace: false
719
- })
722
+ opSpan("update", (update as any)[idColumn])
720
723
  ) as any
721
724
 
722
725
  const updateVoidSchema = SqlSchema.void({
@@ -735,11 +738,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = ${request[idCol
735
738
  update: S["update"]["Type"]
736
739
  ): Effect.Effect<void, Schema.SchemaError, S["update"]["EncodingServices"]> =>
737
740
  updateVoidSchema(update).pipe(
738
- Effect.withSpan(`${options.spanPrefix}.updateVoid`, {
739
- attributes: { id: (update as any)[idColumn] }
740
- }, {
741
- captureStackTrace: false
742
- })
741
+ opSpan("updateVoid", (update as any)[idColumn])
743
742
  ) as any
744
743
 
745
744
  const findByIdSchema = SqlSchema.findOneOption({
@@ -755,9 +754,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = ${request[idCol
755
754
  S["DecodingServices"] | S["fields"][Id]["EncodingServices"]
756
755
  > =>
757
756
  findByIdSchema(id).pipe(
758
- Effect.withSpan(`${options.spanPrefix}.findById`, { attributes: { id } }, {
759
- captureStackTrace: false
760
- })
757
+ opSpan("findById", id)
761
758
  ) as any
762
759
 
763
760
  const deleteSchema = SqlSchema.void({
@@ -768,11 +765,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = ${request[idCol
768
765
  id: S["fields"][Id]["Type"]
769
766
  ): Effect.Effect<void, Schema.SchemaError, S["fields"][Id]["EncodingServices"]> =>
770
767
  deleteSchema(id).pipe(
771
- Effect.withSpan(`${options.spanPrefix}.delete`, {
772
- attributes: { id }
773
- }, {
774
- captureStackTrace: false
775
- })
768
+ opSpan("delete", id)
776
769
  ) as any
777
770
 
778
771
  return { insert, insertVoid, update, updateVoid, findById, delete: delete_ } as const
@@ -795,6 +788,7 @@ export const makeDataLoaders = <
795
788
  readonly idColumn: Id
796
789
  readonly window: Input
797
790
  readonly maxBatchSize?: number | undefined
791
+ readonly dbSystem?: DbSystem | undefined
798
792
  }
799
793
  ): Effect.Effect<
800
794
  {
@@ -827,6 +821,15 @@ export const makeDataLoaders = <
827
821
  const idSchema = Model.fields[options.idColumn] as Schema.Top
828
822
  const idColumn = options.idColumn as string
829
823
  const setMaxBatchSize = options.maxBatchSize ? RequestResolver.batchN(options.maxBatchSize) : identity
824
+ const system: DbSystem = options.dbSystem ?? "other_sql"
825
+ const opSpan = (operation: string, idValue?: unknown) =>
826
+ withDbSpan({
827
+ operation,
828
+ system,
829
+ collection: options.tableName,
830
+ entity: options.spanPrefix,
831
+ ...(idValue !== undefined && { extra: { "app.entity.id": idValue } })
832
+ })
830
833
 
831
834
  const insertResolver = SqlResolver
832
835
  .ordered({
@@ -860,9 +863,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
860
863
  > =>
861
864
  insertExecute(insert).pipe(
862
865
  Effect.catchTag("ResultLengthMismatch", Effect.die),
863
- Effect.withSpan(`${options.spanPrefix}.insert`, {}, {
864
- captureStackTrace: false
865
- })
866
+ opSpan("insert")
866
867
  ) as any
867
868
 
868
869
  const insertVoidResolver = SqlResolver
@@ -880,9 +881,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
880
881
  insert: S["insert"]["Type"]
881
882
  ): Effect.Effect<void, Schema.SchemaError, S["insert"]["EncodingServices"]> =>
882
883
  insertVoidExecute(insert).pipe(
883
- Effect.withSpan(`${options.spanPrefix}.insertVoid`, {}, {
884
- captureStackTrace: false
885
- })
884
+ opSpan("insertVoid")
886
885
  ) as any
887
886
 
888
887
  const findByIdResolver = SqlResolver
@@ -908,9 +907,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
908
907
  S["DecodingServices"] | S["fields"][Id]["EncodingServices"]
909
908
  > =>
910
909
  findByIdExecute(id).pipe(
911
- Effect.withSpan(`${options.spanPrefix}.findById`, { attributes: { id } }, {
912
- captureStackTrace: false
913
- })
910
+ opSpan("findById", id)
914
911
  ) as any
915
912
 
916
913
  const deleteResolver = SqlResolver
@@ -928,9 +925,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
928
925
  id: S["fields"][Id]["Type"]
929
926
  ): Effect.Effect<void, Schema.SchemaError, S["fields"][Id]["EncodingServices"]> =>
930
927
  deleteExecute(id).pipe(
931
- Effect.withSpan(`${options.spanPrefix}.delete`, { attributes: { id } }, {
932
- captureStackTrace: false
933
- })
928
+ opSpan("delete", id)
934
929
  ) as any
935
930
 
936
931
  return { insert, insertVoid, findById, delete: delete_ } as const
@@ -24,7 +24,7 @@ export const makeSSE = <A extends { id: any }, SI, SRD, SRE>(
24
24
  Effect
25
25
  .gen(function*() {
26
26
  const ns = yield* storeId
27
- yield* Effect.annotateCurrentSpan({ connectionId: id.toString() })
27
+ yield* Effect.annotateCurrentSpan({ "network.connection.id": id.toString() })
28
28
  yield* Effect.logInfo("$ start listening to events, id: " + id.toString() + ", ns: " + ns)
29
29
  yield* Effect.addFinalizer(() =>
30
30
  Effect.logInfo("$ end listening to events, id: " + id.toString() + ", ns: " + ns)
@@ -59,8 +59,8 @@ export const LoggerMiddlewareLive = Layer
59
59
  return (effect, { headers, payload, rpc }) =>
60
60
  Effect
61
61
  .annotateCurrentSpan({
62
- "request.name": rpc._tag,
63
- "requestInput": typeof payload === "object" && payload !== null
62
+ "rpc.method": rpc._tag,
63
+ "rpc.request.payload": typeof payload === "object" && payload !== null
64
64
  ? Object.entries(payload).reduce((prev, [key, value]: [string, unknown]) => {
65
65
  prev[key] = key === "password"
66
66
  ? "<redacted>"
@@ -496,7 +496,17 @@ export const makeRouter = <Live extends Layer.Layer<any, any, any> = Layer.Layer
496
496
  )
497
497
  }
498
498
  let effect = (result as Effect.Effect<unknown, unknown, unknown>).pipe(
499
- Effect.withSpan(`Request.${meta.moduleName}.${resource._tag}`, {}, {
499
+ Effect.withSpan(`${meta.moduleName}/${resource._tag}`, {
500
+ kind: "server",
501
+ attributes: {
502
+ "rpc.system": "effect-app",
503
+ "rpc.service": meta.moduleName,
504
+ "rpc.method": resource._tag,
505
+ "code.function.name": resource._tag,
506
+ "code.namespace": meta.moduleName,
507
+ "app.rpc.type": resource.type
508
+ }
509
+ }, {
500
510
  captureStackTrace: () => handler.stack // capturing the handler stack is the main reason why we are doing the span here
501
511
  })
502
512
  )