@codemation/host 0.2.5 → 0.3.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 (109) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/{AppConfigFactory-CqKWXqOm.js → AppConfigFactory-BPp02HMv.js} +82 -5
  3. package/dist/{AppConfigFactory-CqKWXqOm.js.map → AppConfigFactory-BPp02HMv.js.map} +1 -1
  4. package/dist/{AppConfigFactory-CK28UPK0.d.ts → AppConfigFactory-Dq7ttwQ_.d.ts} +6001 -144
  5. package/dist/{AppContainerFactory-CcSGFNLW.js → AppContainerFactory-D9je1sSV.js} +2604 -155
  6. package/dist/AppContainerFactory-D9je1sSV.js.map +1 -0
  7. package/dist/{CodemationAppContext-KqDoeHqN.d.ts → CodemationAppContext-P7P-xZhQ.d.ts} +2 -2
  8. package/dist/{CodemationAuthoring.types-BP6Inucu.d.ts → CodemationAuthoring.types-OMYu7vKP.d.ts} +3 -3
  9. package/dist/{CodemationConfigNormalizer-DIAE0VHw.d.ts → CodemationConfigNormalizer-BCtBrJDe.d.ts} +2 -2
  10. package/dist/{CodemationConsumerConfigLoader-nj9kTmfJ.d.ts → CodemationConsumerConfigLoader-evvw4b_a.d.ts} +2 -2
  11. package/dist/CodemationPluginListMerger-PSTtEQjC.d.ts +674 -0
  12. package/dist/{CredentialServices-BFQD_VN1.d.ts → CredentialServices-0Hk8RFY1.d.ts} +3 -3
  13. package/dist/{CredentialServices-BPKUF8Xs.js → CredentialServices-BNBMFOPt.js} +6 -1
  14. package/dist/CredentialServices-BNBMFOPt.js.map +1 -0
  15. package/dist/{PublicFrontendBootstrapFactory-DTA1iDo0.d.ts → PublicFrontendBootstrapFactory-D0_ds7nS.d.ts} +2 -2
  16. package/dist/authoring.d.ts +3 -3
  17. package/dist/consumer.d.ts +4 -4
  18. package/dist/credentials.d.ts +3 -3
  19. package/dist/credentials.js +1 -1
  20. package/dist/devServerSidecar.d.ts +1 -1
  21. package/dist/{index-Dd6BrWyH.d.ts → index-CeS2saCe.d.ts} +105 -2
  22. package/dist/index.d.ts +12 -11
  23. package/dist/index.js +5 -5
  24. package/dist/nextServer.d.ts +8 -58
  25. package/dist/nextServer.js +6 -100
  26. package/dist/{persistenceServer-DKbFDxoS.js → persistenceServer-CA0_q0D7.js} +2 -2
  27. package/dist/{persistenceServer-DKbFDxoS.js.map → persistenceServer-CA0_q0D7.js.map} +1 -1
  28. package/dist/{persistenceServer-Y-u7lV7f.d.ts → persistenceServer-CJeu1STC.d.ts} +2 -2
  29. package/dist/persistenceServer.d.ts +5 -5
  30. package/dist/persistenceServer.js +2 -2
  31. package/dist/{server-CFpgKuVE.js → server-C_ZIEOTY.js} +4 -4
  32. package/dist/{server-CFpgKuVE.js.map → server-C_ZIEOTY.js.map} +1 -1
  33. package/dist/{server-axppTMgo.d.ts → server-Clvg5x1w.d.ts} +11 -5
  34. package/dist/server.d.ts +8 -8
  35. package/dist/server.js +5 -5
  36. package/package.json +6 -5
  37. package/prisma/migrations/20260414120000_telemetry_foundation/migration.sql +112 -0
  38. package/prisma/migrations/20260414153000_telemetry_retention_metrics_refactor/migration.sql +239 -0
  39. package/prisma/migrations.sqlite/20260414120000_telemetry_foundation/migration.sql +103 -0
  40. package/prisma/migrations.sqlite/20260414153000_telemetry_retention_metrics_refactor/migration.sql +540 -0
  41. package/prisma/schema.postgresql.prisma +100 -1
  42. package/prisma/schema.sqlite.prisma +100 -1
  43. package/scripts/generate-prisma-clients.mjs +89 -1
  44. package/src/application/contracts/TelemetryDashboardContracts.ts +113 -0
  45. package/src/application/contracts/TelemetryRunTraceContracts.ts +13 -0
  46. package/src/application/cost/FrameworkCostCatalogEntries.ts +126 -0
  47. package/src/application/queries/GetTelemetryDashboardDimensionsQuery.ts +11 -0
  48. package/src/application/queries/GetTelemetryDashboardDimensionsQueryHandler.ts +20 -0
  49. package/src/application/queries/GetTelemetryDashboardRunsQuery.ts +11 -0
  50. package/src/application/queries/GetTelemetryDashboardRunsQueryHandler.ts +20 -0
  51. package/src/application/queries/GetTelemetryDashboardSummaryQuery.ts +11 -0
  52. package/src/application/queries/GetTelemetryDashboardSummaryQueryHandler.ts +29 -0
  53. package/src/application/queries/GetTelemetryDashboardTimeseriesQuery.ts +11 -0
  54. package/src/application/queries/GetTelemetryDashboardTimeseriesQueryHandler.ts +36 -0
  55. package/src/application/queries/GetTelemetryRunTraceQuery.ts +8 -0
  56. package/src/application/queries/GetTelemetryRunTraceQueryHandler.ts +20 -0
  57. package/src/application/queries/WorkflowQueryHandlers.ts +5 -0
  58. package/src/application/runs/WorkflowRunRetentionPruneScheduler.ts +71 -26
  59. package/src/application/telemetry/CompositeTelemetryExporter.ts +13 -0
  60. package/src/application/telemetry/LazyExecutionTelemetryFactory.ts +21 -0
  61. package/src/application/telemetry/NoOpTelemetryExporter.ts +7 -0
  62. package/src/application/telemetry/OtelExecutionTelemetry.types.ts +41 -0
  63. package/src/application/telemetry/OtelExecutionTelemetryFactory.ts +56 -0
  64. package/src/application/telemetry/OtelIdentityFactory.ts +41 -0
  65. package/src/application/telemetry/RunEventBusTelemetryReporter.ts +188 -0
  66. package/src/application/telemetry/StoredExecutionTelemetry.ts +56 -0
  67. package/src/application/telemetry/StoredNodeExecutionTelemetry.ts +35 -0
  68. package/src/application/telemetry/StoredTelemetrySpanScope.ts +188 -0
  69. package/src/application/telemetry/TelemetryEnricherChain.ts +85 -0
  70. package/src/application/telemetry/TelemetryPrivacyPolicy.ts +19 -0
  71. package/src/application/telemetry/TelemetryQueryService.ts +815 -0
  72. package/src/application/telemetry/TelemetryRetentionTimestampFactory.ts +40 -0
  73. package/src/applicationTokens.ts +18 -0
  74. package/src/bootstrap/AppContainerFactory.ts +124 -1
  75. package/src/bootstrap/AppContainerLifecycle.ts +8 -0
  76. package/src/bootstrap/runtime/FrontendRuntime.ts +8 -0
  77. package/src/bootstrap/runtime/WorkerRuntime.ts +8 -0
  78. package/src/domain/runs/WorkflowRunRepository.ts +3 -1
  79. package/src/domain/telemetry/TelemetryContracts.ts +197 -0
  80. package/src/infrastructure/persistence/InMemoryRunTraceContextRepository.ts +56 -0
  81. package/src/infrastructure/persistence/InMemoryTelemetryArtifactStore.ts +56 -0
  82. package/src/infrastructure/persistence/InMemoryTelemetryMetricPointStore.ts +97 -0
  83. package/src/infrastructure/persistence/InMemoryTelemetrySpanStore.ts +113 -0
  84. package/src/infrastructure/persistence/InMemoryWorkflowRunRepository.ts +4 -2
  85. package/src/infrastructure/persistence/PrismaRunTraceContextRepository.ts +92 -0
  86. package/src/infrastructure/persistence/PrismaTelemetryArtifactStore.ts +125 -0
  87. package/src/infrastructure/persistence/PrismaTelemetryMetricPointStore.ts +134 -0
  88. package/src/infrastructure/persistence/PrismaTelemetrySpanStore.ts +166 -0
  89. package/src/infrastructure/persistence/PrismaWorkflowRunRepository.ts +20 -7
  90. package/src/infrastructure/persistence/generated/prisma-postgresql-client/edge.js +85 -4
  91. package/src/infrastructure/persistence/generated/prisma-postgresql-client/index-browser.js +81 -0
  92. package/src/infrastructure/persistence/generated/prisma-postgresql-client/index.d.ts +6488 -102
  93. package/src/infrastructure/persistence/generated/prisma-postgresql-client/index.js +85 -4
  94. package/src/infrastructure/persistence/generated/prisma-postgresql-client/package.json +1 -1
  95. package/src/infrastructure/persistence/generated/prisma-postgresql-client/schema.prisma +100 -0
  96. package/src/infrastructure/persistence/generated/prisma-sqlite-client/edge.js +85 -4
  97. package/src/infrastructure/persistence/generated/prisma-sqlite-client/index-browser.js +81 -0
  98. package/src/infrastructure/persistence/generated/prisma-sqlite-client/index.d.ts +6476 -98
  99. package/src/infrastructure/persistence/generated/prisma-sqlite-client/index.js +85 -4
  100. package/src/infrastructure/persistence/generated/prisma-sqlite-client/package.json +1 -1
  101. package/src/infrastructure/persistence/generated/prisma-sqlite-client/schema.prisma +100 -0
  102. package/src/presentation/http/ApiPaths.ts +22 -0
  103. package/src/presentation/http/hono/registrars/TelemetryHonoApiRouteRegistrar.ts +19 -0
  104. package/src/presentation/http/routeHandlers/TelemetryDashboardRequestError.ts +1 -0
  105. package/src/presentation/http/routeHandlers/TelemetryHttpRouteHandler.ts +181 -0
  106. package/dist/AppContainerFactory-CcSGFNLW.js.map +0 -1
  107. package/dist/CodemationPluginListMerger-QvUa2SIt.d.ts +0 -357
  108. package/dist/CredentialServices-BPKUF8Xs.js.map +0 -1
  109. package/dist/nextServer.js.map +0 -1
@@ -0,0 +1,40 @@
1
+ import type { PersistedRunPolicySnapshot } from "@codemation/core";
2
+ import { injectable } from "@codemation/core";
3
+
4
+ @injectable()
5
+ export class TelemetryRetentionTimestampFactory {
6
+ createSpanExpiry(policySnapshot: PersistedRunPolicySnapshot | undefined, observedAt: Date): string | undefined {
7
+ return this.createExpiry(policySnapshot?.telemetrySpanRetentionSeconds, observedAt);
8
+ }
9
+
10
+ createArtifactExpiry(policySnapshot: PersistedRunPolicySnapshot | undefined, observedAt: Date): string | undefined {
11
+ return this.createExpiry(policySnapshot?.telemetryArtifactRetentionSeconds, observedAt);
12
+ }
13
+
14
+ createMetricExpiry(policySnapshot: PersistedRunPolicySnapshot | undefined, observedAt: Date): string | undefined {
15
+ return this.createExpiry(policySnapshot?.telemetryMetricRetentionSeconds, observedAt);
16
+ }
17
+
18
+ createTraceContextExpiry(
19
+ policySnapshot: PersistedRunPolicySnapshot | undefined,
20
+ observedAt: Date,
21
+ ): string | undefined {
22
+ const candidates = [
23
+ policySnapshot?.telemetrySpanRetentionSeconds,
24
+ policySnapshot?.telemetryArtifactRetentionSeconds,
25
+ policySnapshot?.telemetryMetricRetentionSeconds,
26
+ ].filter((value): value is number => typeof value === "number" && value > 0);
27
+ if (candidates.length === 0) {
28
+ return undefined;
29
+ }
30
+ const maxSeconds = Math.max(...candidates);
31
+ return this.createExpiry(maxSeconds, observedAt);
32
+ }
33
+
34
+ private createExpiry(retentionSeconds: number | undefined, observedAt: Date): string | undefined {
35
+ if (!retentionSeconds || retentionSeconds <= 0) {
36
+ return undefined;
37
+ }
38
+ return new Date(observedAt.getTime() + retentionSeconds * 1000).toISOString();
39
+ }
40
+ }
@@ -12,6 +12,13 @@ import type { QueryHandler } from "./application/bus/QueryHandler";
12
12
  import type { Logger, LoggerFactory } from "./application/logging/Logger";
13
13
  import type { WorkflowWebsocketPublisher } from "./application/websocket/WorkflowWebsocketPublisher";
14
14
  import type { CredentialStore } from "./domain/credentials/CredentialServices";
15
+ import type {
16
+ RunTraceContextRepository,
17
+ TelemetryArtifactStore,
18
+ TelemetryExporter,
19
+ TelemetryMetricPointStore,
20
+ TelemetrySpanStore,
21
+ } from "./domain/telemetry/TelemetryContracts";
15
22
  import type { WorkflowRunRepository } from "./domain/runs/WorkflowRunRepository";
16
23
  import type { WorkflowDebuggerOverlayRepository } from "./domain/workflows/WorkflowDebuggerOverlayRepository";
17
24
  import type { WorkflowDefinitionRepository } from "./domain/workflows/WorkflowDefinitionRepository";
@@ -66,6 +73,17 @@ export const ApplicationTokens = {
66
73
  */
67
74
  PerformanceDiagnosticsLogger: Symbol.for("codemation.application.PerformanceDiagnosticsLogger") as TypeToken<Logger>,
68
75
  CredentialStore: Symbol.for("codemation.application.CredentialStore") as TypeToken<CredentialStore>,
76
+ RunTraceContextRepository: Symbol.for(
77
+ "codemation.application.RunTraceContextRepository",
78
+ ) as TypeToken<RunTraceContextRepository>,
79
+ TelemetrySpanStore: Symbol.for("codemation.application.TelemetrySpanStore") as TypeToken<TelemetrySpanStore>,
80
+ TelemetryArtifactStore: Symbol.for(
81
+ "codemation.application.TelemetryArtifactStore",
82
+ ) as TypeToken<TelemetryArtifactStore>,
83
+ TelemetryMetricPointStore: Symbol.for(
84
+ "codemation.application.TelemetryMetricPointStore",
85
+ ) as TypeToken<TelemetryMetricPointStore>,
86
+ TelemetryExporter: Symbol.for("codemation.application.TelemetryExporter") as TypeToken<TelemetryExporter>,
69
87
  PrismaClient: Symbol.for("codemation.application.PrismaClient") as TypeToken<PrismaDatabaseClient>,
70
88
  SessionVerifier: Symbol.for("codemation.application.SessionVerifier") as TypeToken<SessionVerifier>,
71
89
  Clock: Symbol.for("codemation.application.Clock") as TypeToken<Clock>,
@@ -9,8 +9,10 @@ import {
9
9
  SystemClock,
10
10
  container as tsyringeContainer,
11
11
  type WorkflowDefinition,
12
+ type WorkflowPolicyRuntimeDefaults,
12
13
  } from "@codemation/core";
13
14
  import {
15
+ CatalogBackedCostTrackingTelemetryFactory,
14
16
  ConfigDrivenOffloadPolicy,
15
17
  DefaultDrivingScheduler,
16
18
  DefaultExecutionContextFactory,
@@ -18,6 +20,7 @@ import {
18
20
  InMemoryRunDataFactory,
19
21
  InlineDrivingScheduler,
20
22
  PersistedWorkflowTokenRegistry,
23
+ StaticCostCatalog,
21
24
  WorkflowRepositoryWebhookTriggerMatcher,
22
25
  } from "@codemation/core/bootstrap";
23
26
  import { AIAgentConnectionWorkflowExpander, ConnectionCredentialNodeConfigFactory } from "@codemation/core-nodes";
@@ -60,6 +63,11 @@ import {
60
63
  } from "../application/queries/UserAccountQueryHandlers";
61
64
  import {
62
65
  GetRunBinaryAttachmentQueryHandler,
66
+ GetTelemetryDashboardDimensionsQueryHandler,
67
+ GetTelemetryDashboardRunsQueryHandler,
68
+ GetTelemetryRunTraceQueryHandler,
69
+ GetTelemetryDashboardSummaryQueryHandler,
70
+ GetTelemetryDashboardTimeseriesQueryHandler,
63
71
  GetRunStateQueryHandler,
64
72
  GetWorkflowDebuggerOverlayQueryHandler,
65
73
  GetWorkflowDetailQueryHandler,
@@ -72,6 +80,17 @@ import { OpenAiApiKeyCredentialHealthTester } from "../infrastructure/credential
72
80
  import { OpenAiApiKeyCredentialTypeFactory } from "../infrastructure/credentials/OpenAiApiKeyCredentialTypeFactory";
73
81
  import { CodemationPluginRegistrar } from "../infrastructure/config/CodemationPluginRegistrar";
74
82
  import { WorkflowRunEventWebsocketRelay } from "../application/websocket/WorkflowRunEventWebsocketRelay";
83
+ import { FrameworkCostCatalogEntries } from "../application/cost/FrameworkCostCatalogEntries";
84
+ import { CompositeTelemetryExporter } from "../application/telemetry/CompositeTelemetryExporter";
85
+ import { LazyExecutionTelemetryFactory } from "../application/telemetry/LazyExecutionTelemetryFactory";
86
+ import { NoOpTelemetryExporter } from "../application/telemetry/NoOpTelemetryExporter";
87
+ import { OtelExecutionTelemetryFactory } from "../application/telemetry/OtelExecutionTelemetryFactory";
88
+ import { OtelIdentityFactory } from "../application/telemetry/OtelIdentityFactory";
89
+ import { RunEventBusTelemetryReporter } from "../application/telemetry/RunEventBusTelemetryReporter";
90
+ import { TelemetryEnricherChain } from "../application/telemetry/TelemetryEnricherChain";
91
+ import { TelemetryPrivacyPolicy } from "../application/telemetry/TelemetryPrivacyPolicy";
92
+ import { TelemetryQueryService } from "../application/telemetry/TelemetryQueryService";
93
+ import { TelemetryRetentionTimestampFactory } from "../application/telemetry/TelemetryRetentionTimestampFactory";
75
94
  import { ApplicationTokens } from "../applicationTokens";
76
95
  import type { CredentialType } from "../domain/credentials/CredentialServices";
77
96
  import {
@@ -117,6 +136,7 @@ import { CredentialHonoApiRouteRegistrar } from "../presentation/http/hono/regis
117
136
  import { DevHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/DevHonoApiRouteRegistrar";
118
137
  import { OAuth2HonoApiRouteRegistrar } from "../presentation/http/hono/registrars/OAuth2HonoApiRouteRegistrar";
119
138
  import { RunHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/RunHonoApiRouteRegistrar";
139
+ import { TelemetryHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/TelemetryHonoApiRouteRegistrar";
120
140
  import { UserHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/UserHonoApiRouteRegistrar";
121
141
  import { WebhookHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/WebhookHonoApiRouteRegistrar";
122
142
  import { WhitelabelHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/WhitelabelHonoApiRouteRegistrar";
@@ -145,6 +165,10 @@ import {
145
165
  PrismaCredentialStore,
146
166
  } from "../infrastructure/persistence/CredentialPersistenceStore";
147
167
  import { InMemoryTriggerSetupStateRepository } from "../infrastructure/persistence/InMemoryTriggerSetupStateRepository";
168
+ import { InMemoryRunTraceContextRepository } from "../infrastructure/persistence/InMemoryRunTraceContextRepository";
169
+ import { InMemoryTelemetryArtifactStore } from "../infrastructure/persistence/InMemoryTelemetryArtifactStore";
170
+ import { InMemoryTelemetryMetricPointStore } from "../infrastructure/persistence/InMemoryTelemetryMetricPointStore";
171
+ import { InMemoryTelemetrySpanStore } from "../infrastructure/persistence/InMemoryTelemetrySpanStore";
148
172
  import { InMemoryWorkflowActivationRepository } from "../infrastructure/persistence/InMemoryWorkflowActivationRepository";
149
173
  import { InMemoryWorkflowDebuggerOverlayRepository } from "../infrastructure/persistence/InMemoryWorkflowDebuggerOverlayRepository";
150
174
  import { InMemoryWorkflowRunRepository } from "../infrastructure/persistence/InMemoryWorkflowRunRepository";
@@ -154,6 +178,10 @@ import {
154
178
  } from "../infrastructure/persistence/PrismaDatabaseClient";
155
179
  import { PrismaClientFactory } from "../infrastructure/persistence/PrismaClientFactory";
156
180
  import { PrismaTriggerSetupStateRepository } from "../infrastructure/persistence/PrismaTriggerSetupStateRepository";
181
+ import { PrismaRunTraceContextRepository } from "../infrastructure/persistence/PrismaRunTraceContextRepository";
182
+ import { PrismaTelemetryArtifactStore } from "../infrastructure/persistence/PrismaTelemetryArtifactStore";
183
+ import { PrismaTelemetryMetricPointStore } from "../infrastructure/persistence/PrismaTelemetryMetricPointStore";
184
+ import { PrismaTelemetrySpanStore } from "../infrastructure/persistence/PrismaTelemetrySpanStore";
157
185
  import { PrismaWorkflowActivationRepository } from "../infrastructure/persistence/PrismaWorkflowActivationRepository";
158
186
  import { PrismaWorkflowDebuggerOverlayRepository } from "../infrastructure/persistence/PrismaWorkflowDebuggerOverlayRepository";
159
187
  import { PrismaWorkflowRunRepository } from "../infrastructure/persistence/PrismaWorkflowRunRepository";
@@ -169,6 +197,7 @@ import { LocalFilesystemBinaryStorage } from "../infrastructure/binary/LocalFile
169
197
  import { InMemoryBinaryStorage } from "@codemation/core/bootstrap";
170
198
  import { RedisRunEventBus } from "@codemation/eventbus-redis";
171
199
  import { AppContainerLifecycle } from "./AppContainerLifecycle";
200
+ import { WorkflowRunRetentionPruneScheduler } from "../application/runs/WorkflowRunRetentionPruneScheduler";
172
201
  import { DatabaseMigrations } from "./runtime/DatabaseMigrations";
173
202
  import { FrontendRuntime } from "./runtime/FrontendRuntime";
174
203
  import { WorkerRuntime } from "./runtime/WorkerRuntime";
@@ -194,6 +223,11 @@ export class AppContainerFactory {
194
223
  ListUserAccountsQueryHandler,
195
224
  VerifyUserInviteQueryHandler,
196
225
  GetRunBinaryAttachmentQueryHandler,
226
+ GetTelemetryDashboardDimensionsQueryHandler,
227
+ GetTelemetryDashboardRunsQueryHandler,
228
+ GetTelemetryRunTraceQueryHandler,
229
+ GetTelemetryDashboardSummaryQueryHandler,
230
+ GetTelemetryDashboardTimeseriesQueryHandler,
197
231
  GetRunStateQueryHandler,
198
232
  GetWorkflowRunDetailQueryHandler,
199
233
  GetWorkflowDebuggerOverlayQueryHandler,
@@ -231,6 +265,7 @@ export class AppContainerFactory {
231
265
  DevHonoApiRouteRegistrar,
232
266
  OAuth2HonoApiRouteRegistrar,
233
267
  RunHonoApiRouteRegistrar,
268
+ TelemetryHonoApiRouteRegistrar,
234
269
  UserHonoApiRouteRegistrar,
235
270
  WebhookHonoApiRouteRegistrar,
236
271
  WhitelabelHonoApiRouteRegistrar,
@@ -356,6 +391,7 @@ export class AppContainerFactory {
356
391
  container.registerInstance(CoreTokens.WorkflowActivationPolicy, runtimeWorkflowActivationPolicy);
357
392
  new EngineRuntimeRegistrar().register(container, {
358
393
  resolveEngineExecutionLimits: () => inputs.appConfig.engineExecutionLimits,
394
+ workflowPolicyRuntimeDefaults: this.createWorkflowPolicyRuntimeDefaults(inputs.appConfig),
359
395
  webhookTriggerMatcherProvider: {
360
396
  createMatcher: (dependencyContainer) => {
361
397
  const webhookRoutingLogger = dependencyContainer
@@ -528,6 +564,26 @@ export class AppContainerFactory {
528
564
  }
529
565
 
530
566
  private registerRepositoriesAndBuses(container: Container): void {
567
+ container.register(OtelIdentityFactory, { useClass: OtelIdentityFactory });
568
+ container.register(TelemetryPrivacyPolicy, { useClass: TelemetryPrivacyPolicy });
569
+ container.register(TelemetryEnricherChain, { useClass: TelemetryEnricherChain });
570
+ container.register(TelemetryRetentionTimestampFactory, { useClass: TelemetryRetentionTimestampFactory });
571
+ container.register(TelemetryQueryService, { useClass: TelemetryQueryService });
572
+ container.register(NoOpTelemetryExporter, { useClass: NoOpTelemetryExporter });
573
+ container.register(CompositeTelemetryExporter, {
574
+ useFactory: instanceCachingFactory(
575
+ (dependencyContainer) => new CompositeTelemetryExporter([dependencyContainer.resolve(NoOpTelemetryExporter)]),
576
+ ),
577
+ });
578
+ container.register(OtelExecutionTelemetryFactory, { useClass: OtelExecutionTelemetryFactory });
579
+ container.register(InMemoryRunTraceContextRepository, { useClass: InMemoryRunTraceContextRepository });
580
+ container.register(InMemoryTelemetrySpanStore, { useClass: InMemoryTelemetrySpanStore });
581
+ container.register(InMemoryTelemetryArtifactStore, { useClass: InMemoryTelemetryArtifactStore });
582
+ container.register(InMemoryTelemetryMetricPointStore, { useClass: InMemoryTelemetryMetricPointStore });
583
+ container.register(PrismaRunTraceContextRepository, { useClass: PrismaRunTraceContextRepository });
584
+ container.register(PrismaTelemetrySpanStore, { useClass: PrismaTelemetrySpanStore });
585
+ container.register(PrismaTelemetryArtifactStore, { useClass: PrismaTelemetryArtifactStore });
586
+ container.register(PrismaTelemetryMetricPointStore, { useClass: PrismaTelemetryMetricPointStore });
531
587
  container.register(WorkflowDefinitionRepositoryAdapter, { useClass: WorkflowDefinitionRepositoryAdapter });
532
588
  container.register(InMemoryWorkflowRunRepository, { useClass: InMemoryWorkflowRunRepository });
533
589
  container.register(InMemoryTriggerSetupStateRepository, { useClass: InMemoryTriggerSetupStateRepository });
@@ -565,6 +621,11 @@ export class AppContainerFactory {
565
621
  container.register(ApplicationTokens.DomainEventBus, {
566
622
  useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(InMemoryDomainEventBus)),
567
623
  });
624
+ container.register(ApplicationTokens.TelemetryExporter, {
625
+ useFactory: instanceCachingFactory((dependencyContainer) =>
626
+ dependencyContainer.resolve(CompositeTelemetryExporter),
627
+ ),
628
+ });
568
629
  }
569
630
 
570
631
  private registerApplicationServicesAndRoutes(container: Container): void {
@@ -585,6 +646,8 @@ export class AppContainerFactory {
585
646
  useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(WorkflowWebsocketServer)),
586
647
  });
587
648
  container.register(WorkflowRunEventWebsocketRelay, { useClass: WorkflowRunEventWebsocketRelay });
649
+ container.register(RunEventBusTelemetryReporter, { useClass: RunEventBusTelemetryReporter });
650
+ container.register(WorkflowRunRetentionPruneScheduler, { useClass: WorkflowRunRetentionPruneScheduler });
588
651
  }
589
652
 
590
653
  private async registerRuntimeInfrastructure(container: Container, appConfig: AppConfig): Promise<PrismaOwnership> {
@@ -597,7 +660,6 @@ export class AppContainerFactory {
597
660
  const binaryStorage = this.createBinaryStorage(appConfig.repoRoot);
598
661
  container.registerInstance(CoreTokens.RunDataFactory, new InMemoryRunDataFactory());
599
662
  container.registerInstance(CoreTokens.BinaryStorage, binaryStorage);
600
- container.registerInstance(CoreTokens.ExecutionContextFactory, new DefaultExecutionContextFactory(binaryStorage));
601
663
  container.registerInstance(ApplicationTokens.Clock, new SystemClock());
602
664
 
603
665
  if (appConfig.persistence.kind === "none") {
@@ -620,6 +682,27 @@ export class AppContainerFactory {
620
682
  container.resolve(InMemoryWorkflowActivationRepository),
621
683
  );
622
684
  container.registerInstance(ApplicationTokens.CredentialStore, container.resolve(InMemoryCredentialStore));
685
+ container.registerInstance(
686
+ ApplicationTokens.RunTraceContextRepository,
687
+ container.resolve(InMemoryRunTraceContextRepository),
688
+ );
689
+ container.registerInstance(ApplicationTokens.TelemetrySpanStore, container.resolve(InMemoryTelemetrySpanStore));
690
+ container.registerInstance(
691
+ ApplicationTokens.TelemetryArtifactStore,
692
+ container.resolve(InMemoryTelemetryArtifactStore),
693
+ );
694
+ container.registerInstance(
695
+ ApplicationTokens.TelemetryMetricPointStore,
696
+ container.resolve(InMemoryTelemetryMetricPointStore),
697
+ );
698
+ container.registerInstance(
699
+ CoreTokens.ExecutionContextFactory,
700
+ new DefaultExecutionContextFactory(
701
+ binaryStorage,
702
+ new LazyExecutionTelemetryFactory(() => container.resolve(OtelExecutionTelemetryFactory)),
703
+ new CatalogBackedCostTrackingTelemetryFactory(new StaticCostCatalog(FrameworkCostCatalogEntries)),
704
+ ),
705
+ );
623
706
  this.registerRuntimeNodeActivationScheduler(container);
624
707
  return {
625
708
  ownedPrismaClient: null,
@@ -632,6 +715,10 @@ export class AppContainerFactory {
632
715
  const workflowRunRepository = childContainer.resolve(PrismaWorkflowRunRepository);
633
716
  const triggerSetupStateRepository = childContainer.resolve(PrismaTriggerSetupStateRepository);
634
717
  const workflowDebuggerOverlayRepository = childContainer.resolve(PrismaWorkflowDebuggerOverlayRepository);
718
+ const runTraceContextRepository = childContainer.resolve(PrismaRunTraceContextRepository);
719
+ const telemetrySpanStore = childContainer.resolve(PrismaTelemetrySpanStore);
720
+ const telemetryArtifactStore = childContainer.resolve(PrismaTelemetryArtifactStore);
721
+ const telemetryMetricPointStore = childContainer.resolve(PrismaTelemetryMetricPointStore);
635
722
  container.registerInstance(PrismaDatabaseClientToken, prismaOwnership.prismaClient);
636
723
  container.registerInstance(ApplicationTokens.PrismaClient, prismaOwnership.prismaClient);
637
724
  container.registerInstance(
@@ -649,6 +736,18 @@ export class AppContainerFactory {
649
736
  container.resolve(PrismaWorkflowActivationRepository),
650
737
  );
651
738
  container.registerInstance(ApplicationTokens.CredentialStore, container.resolve(PrismaCredentialStore));
739
+ container.registerInstance(ApplicationTokens.RunTraceContextRepository, runTraceContextRepository);
740
+ container.registerInstance(ApplicationTokens.TelemetrySpanStore, telemetrySpanStore);
741
+ container.registerInstance(ApplicationTokens.TelemetryArtifactStore, telemetryArtifactStore);
742
+ container.registerInstance(ApplicationTokens.TelemetryMetricPointStore, telemetryMetricPointStore);
743
+ container.registerInstance(
744
+ CoreTokens.ExecutionContextFactory,
745
+ new DefaultExecutionContextFactory(
746
+ binaryStorage,
747
+ new LazyExecutionTelemetryFactory(() => container.resolve(OtelExecutionTelemetryFactory)),
748
+ new CatalogBackedCostTrackingTelemetryFactory(new StaticCostCatalog(FrameworkCostCatalogEntries)),
749
+ ),
750
+ );
652
751
  if (appConfig.scheduler.kind === "bullmq") {
653
752
  container.registerInstance(
654
753
  ApplicationTokens.WorkerRuntimeScheduler,
@@ -705,6 +804,22 @@ export class AppContainerFactory {
705
804
  });
706
805
  }
707
806
 
807
+ private createWorkflowPolicyRuntimeDefaults(appConfig: AppConfig): WorkflowPolicyRuntimeDefaults {
808
+ return {
809
+ retentionSeconds: this.readPositiveInteger(appConfig.env.CODEMATION_RUN_RETENTION_DEFAULT_SECONDS),
810
+ binaryRetentionSeconds: this.readPositiveInteger(appConfig.env.CODEMATION_BINARY_RETENTION_DEFAULT_SECONDS),
811
+ telemetrySpanRetentionSeconds: this.readPositiveInteger(
812
+ appConfig.env.CODEMATION_TELEMETRY_SPAN_RETENTION_DEFAULT_SECONDS,
813
+ ),
814
+ telemetryArtifactRetentionSeconds: this.readPositiveInteger(
815
+ appConfig.env.CODEMATION_TELEMETRY_ARTIFACT_RETENTION_DEFAULT_SECONDS,
816
+ ),
817
+ telemetryMetricRetentionSeconds: this.readPositiveInteger(
818
+ appConfig.env.CODEMATION_TELEMETRY_METRIC_RETENTION_DEFAULT_SECONDS,
819
+ ),
820
+ };
821
+ }
822
+
708
823
  private createBinaryStorage(repoRoot: string): InMemoryBinaryStorage | LocalFilesystemBinaryStorage {
709
824
  if (!repoRoot) {
710
825
  return new InMemoryBinaryStorage();
@@ -730,6 +845,14 @@ export class AppContainerFactory {
730
845
  return redisUrl;
731
846
  }
732
847
 
848
+ private readPositiveInteger(value: string | undefined): number | undefined {
849
+ if (!value) {
850
+ return undefined;
851
+ }
852
+ const parsed = Number(value);
853
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
854
+ }
855
+
733
856
  private synchronizeLiveWorkflowRepository(container: Container, workflows: ReadonlyArray<WorkflowDefinition>): void {
734
857
  const liveWorkflowRepository = container.resolve(CoreTokens.LiveWorkflowRepository);
735
858
  liveWorkflowRepository.setWorkflows(workflows);
@@ -1,5 +1,7 @@
1
1
  import type { Container } from "@codemation/core";
2
2
  import { Engine } from "@codemation/core/bootstrap";
3
+ import { RunEventBusTelemetryReporter } from "../application/telemetry/RunEventBusTelemetryReporter";
4
+ import { WorkflowRunRetentionPruneScheduler } from "../application/runs/WorkflowRunRetentionPruneScheduler";
3
5
  import type { PrismaDatabaseClient } from "../infrastructure/persistence/PrismaDatabaseClient";
4
6
  import { WorkflowRunEventWebsocketRelay } from "../application/websocket/WorkflowRunEventWebsocketRelay";
5
7
  import { WorkflowWebsocketServer } from "../presentation/websocket/WorkflowWebsocketServer";
@@ -17,6 +19,12 @@ export class AppContainerLifecycle {
17
19
  if (this.container.isRegistered(WorkflowRunEventWebsocketRelay, true)) {
18
20
  await this.container.resolve(WorkflowRunEventWebsocketRelay).stop();
19
21
  }
22
+ if (this.container.isRegistered(RunEventBusTelemetryReporter, true)) {
23
+ await this.container.resolve(RunEventBusTelemetryReporter).stop();
24
+ }
25
+ if (this.container.isRegistered(WorkflowRunRetentionPruneScheduler, true)) {
26
+ this.container.resolve(WorkflowRunRetentionPruneScheduler).stop();
27
+ }
20
28
  if (args?.stopWebsocketServer !== false && this.container.isRegistered(WorkflowWebsocketServer, true)) {
21
29
  await this.container.resolve(WorkflowWebsocketServer).stop();
22
30
  }
@@ -3,10 +3,12 @@ import { Engine } from "@codemation/core/bootstrap";
3
3
  import { ApplicationTokens } from "../../applicationTokens";
4
4
  import type { AppConfig } from "../../presentation/config/AppConfig";
5
5
  import { RuntimeWorkflowActivationPolicy } from "../../infrastructure/persistence/RuntimeWorkflowActivationPolicy";
6
+ import { RunEventBusTelemetryReporter } from "../../application/telemetry/RunEventBusTelemetryReporter";
6
7
  import { WorkflowRunEventWebsocketRelay } from "../../application/websocket/WorkflowRunEventWebsocketRelay";
7
8
  import { WorkflowWebsocketServer } from "../../presentation/websocket/WorkflowWebsocketServer";
8
9
  import { DatabaseMigrations } from "./DatabaseMigrations";
9
10
  import type { WorkflowActivationRepository } from "../../domain/workflows/WorkflowActivationRepository";
11
+ import { WorkflowRunRetentionPruneScheduler } from "../../application/runs/WorkflowRunRetentionPruneScheduler";
10
12
 
11
13
  @injectable()
12
14
  export class FrontendRuntime {
@@ -25,6 +27,10 @@ export class FrontendRuntime {
25
27
  private readonly workflowWebsocketServer: WorkflowWebsocketServer,
26
28
  @inject(WorkflowRunEventWebsocketRelay)
27
29
  private readonly workflowRunEventWebsocketRelay: WorkflowRunEventWebsocketRelay,
30
+ @inject(RunEventBusTelemetryReporter)
31
+ private readonly runEventBusTelemetryReporter: RunEventBusTelemetryReporter,
32
+ @inject(WorkflowRunRetentionPruneScheduler)
33
+ private readonly workflowRunRetentionPruneScheduler: WorkflowRunRetentionPruneScheduler,
28
34
  @inject(Engine)
29
35
  private readonly engine: Engine,
30
36
  ) {}
@@ -39,6 +45,8 @@ export class FrontendRuntime {
39
45
  }
40
46
  await this.engine.start([...this.workflowRepository.list()]);
41
47
  await this.workflowWebsocketServer.start();
48
+ await this.runEventBusTelemetryReporter.start();
49
+ this.workflowRunRetentionPruneScheduler.start();
42
50
  await this.workflowRunEventWebsocketRelay.start();
43
51
  }
44
52
  }
@@ -11,6 +11,8 @@ import { RuntimeWorkflowActivationPolicy } from "../../infrastructure/persistenc
11
11
  import type { WorkflowActivationRepository } from "../../domain/workflows/WorkflowActivationRepository";
12
12
  import { DatabaseMigrations } from "./DatabaseMigrations";
13
13
  import { AppContainerLifecycle } from "../AppContainerLifecycle";
14
+ import { RunEventBusTelemetryReporter } from "../../application/telemetry/RunEventBusTelemetryReporter";
15
+ import { WorkflowRunRetentionPruneScheduler } from "../../application/runs/WorkflowRunRetentionPruneScheduler";
14
16
 
15
17
  @injectable()
16
18
  export class WorkerRuntime {
@@ -27,6 +29,10 @@ export class WorkerRuntime {
27
29
  private readonly workflowRepository: WorkflowRepository,
28
30
  @inject(Engine)
29
31
  private readonly engine: Engine,
32
+ @inject(RunEventBusTelemetryReporter)
33
+ private readonly runEventBusTelemetryReporter: RunEventBusTelemetryReporter,
34
+ @inject(WorkflowRunRetentionPruneScheduler)
35
+ private readonly workflowRunRetentionPruneScheduler: WorkflowRunRetentionPruneScheduler,
30
36
  @inject(ApplicationTokens.WorkerRuntimeScheduler)
31
37
  private readonly scheduler: WorkerRuntimeScheduler,
32
38
  @inject(AppContainerLifecycle)
@@ -40,6 +46,8 @@ export class WorkerRuntime {
40
46
  await this.runtimeWorkflowActivationPolicy.hydrateFromRepository(this.workflowActivationRepository);
41
47
  const workflows = [...this.workflowRepository.list()];
42
48
  await this.engine.start(workflows);
49
+ await this.runEventBusTelemetryReporter.start();
50
+ this.workflowRunRetentionPruneScheduler.start();
43
51
  const worker = this.scheduler.createWorker({
44
52
  queues,
45
53
  requestHandler: this.engine,
@@ -9,7 +9,9 @@ export interface WorkflowRunRepository {
9
9
 
10
10
  listRuns(args: Readonly<{ workflowId?: string; limit?: number }>): Promise<ReadonlyArray<RunSummary>>;
11
11
 
12
- listRunsOlderThan?(args: Readonly<{ beforeIso: string; limit?: number }>): Promise<ReadonlyArray<RunPruneCandidate>>;
12
+ listRunsOlderThan?(
13
+ args: Readonly<{ nowIso: string; defaultRetentionSeconds: number; limit?: number }>,
14
+ ): Promise<ReadonlyArray<RunPruneCandidate>>;
13
15
 
14
16
  listBinaryStorageKeys?(runId: RunId): Promise<ReadonlyArray<string>>;
15
17
 
@@ -0,0 +1,197 @@
1
+ import type {
2
+ TelemetryArtifactAttachment,
3
+ TelemetryAttributes,
4
+ TelemetryMetricRecord,
5
+ TelemetrySpanEventRecord,
6
+ } from "@codemation/core";
7
+
8
+ export type TelemetrySpanStatus = "running" | "completed" | "failed";
9
+ export type TelemetrySpanKind = "internal" | "client";
10
+
11
+ export interface TelemetryTraceContext {
12
+ readonly runId: string;
13
+ readonly workflowId: string;
14
+ readonly traceId: string;
15
+ readonly rootSpanId: string;
16
+ readonly serviceName?: string;
17
+ readonly createdAt: string;
18
+ readonly expiresAt?: string;
19
+ }
20
+
21
+ export interface TelemetrySpanRecord {
22
+ readonly traceId: string;
23
+ readonly spanId: string;
24
+ readonly parentSpanId?: string;
25
+ readonly runId: string;
26
+ readonly workflowId: string;
27
+ readonly nodeId?: string;
28
+ readonly activationId?: string;
29
+ readonly connectionInvocationId?: string;
30
+ readonly name: string;
31
+ readonly kind: TelemetrySpanKind;
32
+ readonly status?: TelemetrySpanStatus;
33
+ readonly statusMessage?: string;
34
+ readonly startTime?: string;
35
+ readonly endTime?: string;
36
+ readonly workflowFolder?: string;
37
+ readonly nodeType?: string;
38
+ readonly nodeRole?: string;
39
+ readonly modelName?: string;
40
+ readonly attributes?: TelemetryAttributes;
41
+ readonly events?: ReadonlyArray<TelemetrySpanEventRecord>;
42
+ readonly retentionExpiresAt?: string;
43
+ }
44
+
45
+ export interface TelemetrySpanUpsert {
46
+ readonly traceId: string;
47
+ readonly spanId: string;
48
+ readonly parentSpanId?: string;
49
+ readonly runId: string;
50
+ readonly workflowId: string;
51
+ readonly nodeId?: string;
52
+ readonly activationId?: string;
53
+ readonly connectionInvocationId?: string;
54
+ readonly name?: string;
55
+ readonly kind?: TelemetrySpanKind;
56
+ readonly status?: TelemetrySpanStatus;
57
+ readonly statusMessage?: string;
58
+ readonly startTime?: string;
59
+ readonly endTime?: string;
60
+ readonly workflowFolder?: string;
61
+ readonly nodeType?: string;
62
+ readonly nodeRole?: string;
63
+ readonly modelName?: string;
64
+ readonly attributes?: TelemetryAttributes;
65
+ readonly events?: ReadonlyArray<TelemetrySpanEventRecord>;
66
+ readonly retentionExpiresAt?: string;
67
+ }
68
+
69
+ export interface TelemetryArtifactRecord {
70
+ readonly artifactId: string;
71
+ readonly traceId: string;
72
+ readonly spanId: string;
73
+ readonly runId: string;
74
+ readonly workflowId: string;
75
+ readonly nodeId?: string;
76
+ readonly activationId?: string;
77
+ readonly kind: string;
78
+ readonly contentType: string;
79
+ readonly previewText?: string;
80
+ readonly previewJson?: unknown;
81
+ readonly payloadText?: string;
82
+ readonly payloadJson?: unknown;
83
+ readonly bytes?: number;
84
+ readonly truncated?: boolean;
85
+ readonly createdAt: string;
86
+ readonly expiresAt?: string;
87
+ readonly retentionExpiresAt?: string;
88
+ }
89
+
90
+ export interface TelemetryArtifactWrite extends TelemetryArtifactAttachment {
91
+ readonly traceId: string;
92
+ readonly spanId: string;
93
+ readonly runId: string;
94
+ readonly workflowId: string;
95
+ readonly nodeId?: string;
96
+ readonly activationId?: string;
97
+ readonly retentionExpiresAt?: string;
98
+ }
99
+
100
+ export interface TelemetryMetricPointRecord {
101
+ readonly metricPointId: string;
102
+ readonly traceId?: string;
103
+ readonly spanId?: string;
104
+ readonly runId?: string;
105
+ readonly workflowId: string;
106
+ readonly nodeId?: string;
107
+ readonly activationId?: string;
108
+ readonly metricName: string;
109
+ readonly value: number;
110
+ readonly unit?: string;
111
+ readonly observedAt: string;
112
+ readonly workflowFolder?: string;
113
+ readonly nodeType?: string;
114
+ readonly nodeRole?: string;
115
+ readonly modelName?: string;
116
+ readonly dimensions?: TelemetryAttributes;
117
+ readonly retentionExpiresAt?: string;
118
+ }
119
+
120
+ export interface TelemetryMetricPointWrite extends TelemetryMetricRecord {
121
+ readonly traceId?: string;
122
+ readonly spanId?: string;
123
+ readonly runId?: string;
124
+ readonly workflowId: string;
125
+ readonly nodeId?: string;
126
+ readonly activationId?: string;
127
+ readonly observedAt: string;
128
+ readonly workflowFolder?: string;
129
+ readonly nodeType?: string;
130
+ readonly nodeRole?: string;
131
+ readonly modelName?: string;
132
+ readonly retentionExpiresAt?: string;
133
+ }
134
+
135
+ export interface TelemetrySpanListQuery {
136
+ readonly traceId?: string;
137
+ readonly runId?: string;
138
+ readonly runIds?: ReadonlyArray<string>;
139
+ readonly workflowId?: string;
140
+ readonly workflowIds?: ReadonlyArray<string>;
141
+ readonly statuses?: ReadonlyArray<TelemetrySpanStatus>;
142
+ readonly names?: ReadonlyArray<string>;
143
+ readonly modelNames?: ReadonlyArray<string>;
144
+ readonly startTimeGte?: string;
145
+ readonly endTimeLte?: string;
146
+ readonly limit?: number;
147
+ }
148
+
149
+ export interface TelemetryMetricPointListQuery {
150
+ readonly traceId?: string;
151
+ readonly runId?: string;
152
+ readonly runIds?: ReadonlyArray<string>;
153
+ readonly workflowId?: string;
154
+ readonly workflowIds?: ReadonlyArray<string>;
155
+ readonly nodeId?: string;
156
+ readonly metricNames?: ReadonlyArray<string>;
157
+ readonly modelNames?: ReadonlyArray<string>;
158
+ readonly observedAtGte?: string;
159
+ readonly observedAtLte?: string;
160
+ readonly limit?: number;
161
+ }
162
+
163
+ export interface TelemetryPruneArgs {
164
+ readonly nowIso: string;
165
+ readonly limit?: number;
166
+ }
167
+
168
+ export interface RunTraceContextRepository {
169
+ load(runId: string): Promise<TelemetryTraceContext | undefined>;
170
+ getOrCreate(
171
+ args: Readonly<{ runId: string; workflowId: string; serviceName?: string }>,
172
+ ): Promise<TelemetryTraceContext>;
173
+ upsertExpiry(args: Readonly<{ runId: string; expiresAt?: string }>): Promise<void>;
174
+ }
175
+
176
+ export interface TelemetrySpanStore {
177
+ upsert(record: TelemetrySpanUpsert): Promise<void>;
178
+ list(args?: TelemetrySpanListQuery): Promise<ReadonlyArray<TelemetrySpanRecord>>;
179
+ listByTraceId(traceId: string): Promise<ReadonlyArray<TelemetrySpanRecord>>;
180
+ pruneExpired(args: TelemetryPruneArgs): Promise<number>;
181
+ }
182
+
183
+ export interface TelemetryArtifactStore {
184
+ save(record: TelemetryArtifactWrite): Promise<TelemetryArtifactRecord>;
185
+ listByTraceId(traceId: string): Promise<ReadonlyArray<TelemetryArtifactRecord>>;
186
+ pruneExpired(args: TelemetryPruneArgs): Promise<number>;
187
+ }
188
+
189
+ export interface TelemetryMetricPointStore {
190
+ save(record: TelemetryMetricPointWrite): Promise<TelemetryMetricPointRecord>;
191
+ list(args?: TelemetryMetricPointListQuery): Promise<ReadonlyArray<TelemetryMetricPointRecord>>;
192
+ pruneExpired(args: TelemetryPruneArgs): Promise<number>;
193
+ }
194
+
195
+ export interface TelemetryExporter {
196
+ exportSpans(spans: ReadonlyArray<TelemetrySpanRecord>): Promise<void>;
197
+ }