@forklaunch/core 1.5.1 → 1.5.3

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 (265) hide show
  1. package/lib/cache/{index.d.mts → cacheKey.d.ts} +2 -6
  2. package/lib/cache/cacheKey.d.ts.map +1 -0
  3. package/lib/cache/index.d.ts +4 -15
  4. package/lib/cache/index.d.ts.map +1 -0
  5. package/lib/{ttlCache.interface-B3xaLT00.d.ts → cache/interfaces/ttlCache.interface.d.ts} +3 -5
  6. package/lib/cache/interfaces/ttlCache.interface.d.ts.map +1 -0
  7. package/lib/{ttlCacheRecord.types-oX0ti5SP.d.mts → cache/types/ttlCacheRecord.types.d.ts} +3 -4
  8. package/lib/cache/types/ttlCacheRecord.types.d.ts.map +1 -0
  9. package/lib/controllers/index.d.ts +2 -13
  10. package/lib/controllers/index.d.ts.map +1 -0
  11. package/lib/controllers/{index.d.mts → interfaces/controller.interface.d.ts} +2 -3
  12. package/lib/controllers/interfaces/controller.interface.d.ts.map +1 -0
  13. package/lib/environment/index.d.ts +2 -28
  14. package/lib/environment/index.d.ts.map +1 -0
  15. package/lib/environment/{index.d.mts → loadCascadingEnv.d.ts} +4 -5
  16. package/lib/environment/loadCascadingEnv.d.ts.map +1 -0
  17. package/lib/http/application/expressLikeApplication.d.ts +34 -0
  18. package/lib/http/application/expressLikeApplication.d.ts.map +1 -0
  19. package/lib/http/bootstrap/listen.d.ts +2 -0
  20. package/lib/http/bootstrap/listen.d.ts.map +1 -0
  21. package/lib/http/cluster/cluster.types.d.ts +17 -0
  22. package/lib/http/cluster/cluster.types.d.ts.map +1 -0
  23. package/lib/http/cluster/isPortBound.d.ts +2 -0
  24. package/lib/http/cluster/isPortBound.d.ts.map +1 -0
  25. package/lib/http/createHmacToken.d.ts +19 -0
  26. package/lib/http/createHmacToken.d.ts.map +1 -0
  27. package/lib/http/discriminateAuthMethod.d.ts +85 -0
  28. package/lib/http/discriminateAuthMethod.d.ts.map +1 -0
  29. package/lib/http/generateHmacAuthHeaders.d.ts +31 -0
  30. package/lib/http/generateHmacAuthHeaders.d.ts.map +1 -0
  31. package/lib/http/guards/hasFeatureChecks.d.ts +2 -0
  32. package/lib/http/guards/hasFeatureChecks.d.ts.map +1 -0
  33. package/lib/http/guards/hasPermissionChecks.d.ts +2 -0
  34. package/lib/http/guards/hasPermissionChecks.d.ts.map +1 -0
  35. package/lib/http/guards/hasRoleChecks.d.ts +2 -0
  36. package/lib/http/guards/hasRoleChecks.d.ts.map +1 -0
  37. package/lib/http/guards/hasScopeChecks.d.ts +2 -0
  38. package/lib/http/guards/hasScopeChecks.d.ts.map +1 -0
  39. package/lib/http/guards/hasSend.d.ts +17 -0
  40. package/lib/http/guards/hasSend.d.ts.map +1 -0
  41. package/lib/http/guards/hasSubscriptionChecks.d.ts +2 -0
  42. package/lib/http/guards/hasSubscriptionChecks.d.ts.map +1 -0
  43. package/lib/http/guards/hasVersionedSchema.d.ts +2 -0
  44. package/lib/http/guards/hasVersionedSchema.d.ts.map +1 -0
  45. package/lib/http/guards/isBasicAuthMethod.d.ts +3 -0
  46. package/lib/http/guards/isBasicAuthMethod.d.ts.map +1 -0
  47. package/lib/http/guards/isConstrainedForklaunchRouter.d.ts +21 -0
  48. package/lib/http/guards/isConstrainedForklaunchRouter.d.ts.map +1 -0
  49. package/lib/http/guards/isExpressLikeSchemaHandler.d.ts +32 -0
  50. package/lib/http/guards/isExpressLikeSchemaHandler.d.ts.map +1 -0
  51. package/lib/http/guards/isForklaunchExpressLikeRouter.d.ts +28 -0
  52. package/lib/http/guards/isForklaunchExpressLikeRouter.d.ts.map +1 -0
  53. package/lib/http/guards/isForklaunchRequest.d.ts +26 -0
  54. package/lib/http/guards/isForklaunchRequest.d.ts.map +1 -0
  55. package/lib/http/guards/isForklaunchResponse.d.ts +23 -0
  56. package/lib/http/guards/isForklaunchResponse.d.ts.map +1 -0
  57. package/lib/http/guards/isForklaunchRouter.d.ts +21 -0
  58. package/lib/http/guards/isForklaunchRouter.d.ts.map +1 -0
  59. package/lib/http/guards/isHmacMethod.d.ts +9 -0
  60. package/lib/http/guards/isHmacMethod.d.ts.map +1 -0
  61. package/lib/http/guards/isHttpContractDetails.d.ts +29 -0
  62. package/lib/http/guards/isHttpContractDetails.d.ts.map +1 -0
  63. package/lib/http/guards/isJwtAuthMethod.d.ts +3 -0
  64. package/lib/http/guards/isJwtAuthMethod.d.ts.map +1 -0
  65. package/lib/http/guards/isLoggerMeta.d.ts +3 -0
  66. package/lib/http/guards/isLoggerMeta.d.ts.map +1 -0
  67. package/lib/http/guards/isPath.d.ts +2 -0
  68. package/lib/http/guards/isPath.d.ts.map +1 -0
  69. package/lib/http/guards/isPathParamContractDetails.d.ts +4 -0
  70. package/lib/http/guards/isPathParamContractDetails.d.ts.map +1 -0
  71. package/lib/http/guards/isRequestShape.d.ts +3 -0
  72. package/lib/http/guards/isRequestShape.d.ts.map +1 -0
  73. package/lib/http/guards/isResponseCompiledSchema.d.ts +3 -0
  74. package/lib/http/guards/isResponseCompiledSchema.d.ts.map +1 -0
  75. package/lib/http/guards/isSdkHandler.d.ts +9 -0
  76. package/lib/http/guards/isSdkHandler.d.ts.map +1 -0
  77. package/lib/http/guards/isSdkRouter.d.ts +9 -0
  78. package/lib/http/guards/isSdkRouter.d.ts.map +1 -0
  79. package/lib/http/guards/isTypedHandler.d.ts +5 -0
  80. package/lib/http/guards/isTypedHandler.d.ts.map +1 -0
  81. package/lib/http/guards/isVersionedInputSchema.d.ts +3 -0
  82. package/lib/http/guards/isVersionedInputSchema.d.ts.map +1 -0
  83. package/lib/http/handlers/delete.d.ts +5 -0
  84. package/lib/http/handlers/delete.d.ts.map +1 -0
  85. package/lib/http/handlers/get.d.ts +5 -0
  86. package/lib/http/handlers/get.d.ts.map +1 -0
  87. package/lib/http/handlers/head.d.ts +5 -0
  88. package/lib/http/handlers/head.d.ts.map +1 -0
  89. package/lib/http/handlers/middleware.d.ts +10 -0
  90. package/lib/http/handlers/middleware.d.ts.map +1 -0
  91. package/lib/http/handlers/options.d.ts +5 -0
  92. package/lib/http/handlers/options.d.ts.map +1 -0
  93. package/lib/http/handlers/patch.d.ts +5 -0
  94. package/lib/http/handlers/patch.d.ts.map +1 -0
  95. package/lib/http/handlers/post.d.ts +5 -0
  96. package/lib/http/handlers/post.d.ts.map +1 -0
  97. package/lib/http/handlers/put.d.ts +5 -0
  98. package/lib/http/handlers/put.d.ts.map +1 -0
  99. package/lib/http/handlers/trace.d.ts +5 -0
  100. package/lib/http/handlers/trace.d.ts.map +1 -0
  101. package/lib/http/handlers/typedAuthHandler.d.ts +5 -0
  102. package/lib/http/handlers/typedAuthHandler.d.ts.map +1 -0
  103. package/lib/http/handlers/typedHandler.d.ts +14 -0
  104. package/lib/http/handlers/typedHandler.d.ts.map +1 -0
  105. package/lib/http/httpStatusCodes.d.ts +75 -0
  106. package/lib/http/httpStatusCodes.d.ts.map +1 -0
  107. package/lib/http/index.d.ts +47 -1244
  108. package/lib/http/index.d.ts.map +1 -0
  109. package/lib/http/index.js +445 -410
  110. package/lib/http/index.js.map +1 -1
  111. package/lib/http/index.mjs +439 -407
  112. package/lib/http/index.mjs.map +1 -1
  113. package/lib/http/interfaces/expressLikeRouter.interface.d.ts +25 -0
  114. package/lib/http/interfaces/expressLikeRouter.interface.d.ts.map +1 -0
  115. package/lib/http/mcpGenerator/mcpGenerator.d.ts +17 -0
  116. package/lib/http/mcpGenerator/mcpGenerator.d.ts.map +1 -0
  117. package/lib/http/middleware/request/auth.middleware.d.ts +16 -0
  118. package/lib/http/middleware/request/auth.middleware.d.ts.map +1 -0
  119. package/lib/http/middleware/request/cors.middleware.d.ts +13 -0
  120. package/lib/http/middleware/request/cors.middleware.d.ts.map +1 -0
  121. package/lib/http/middleware/request/createContext.middleware.d.ts +15 -0
  122. package/lib/http/middleware/request/createContext.middleware.d.ts.map +1 -0
  123. package/lib/http/middleware/request/enrichDetails.middleware.d.ts +18 -0
  124. package/lib/http/middleware/request/enrichDetails.middleware.d.ts.map +1 -0
  125. package/lib/http/middleware/request/parse.middleware.d.ts +17 -0
  126. package/lib/http/middleware/request/parse.middleware.d.ts.map +1 -0
  127. package/lib/http/middleware/request/tenantContext.middleware.d.ts +41 -0
  128. package/lib/http/middleware/request/tenantContext.middleware.d.ts.map +1 -0
  129. package/lib/http/middleware/response/enrichExpressLikeSend.middleware.d.ts +32 -0
  130. package/lib/http/middleware/response/enrichExpressLikeSend.middleware.d.ts.map +1 -0
  131. package/lib/http/middleware/response/parse.middleware.d.ts +31 -0
  132. package/lib/http/middleware/response/parse.middleware.d.ts.map +1 -0
  133. package/lib/http/openApiV3Generator/openApiV3Generator.d.ts +17 -0
  134. package/lib/http/openApiV3Generator/openApiV3Generator.d.ts.map +1 -0
  135. package/lib/http/rateLimit/index.d.ts +2 -0
  136. package/lib/http/rateLimit/index.d.ts.map +1 -0
  137. package/lib/http/rateLimit/rateLimiter.d.ts +66 -0
  138. package/lib/http/rateLimit/rateLimiter.d.ts.map +1 -0
  139. package/lib/http/router/discriminateBody.d.ts +43 -0
  140. package/lib/http/router/discriminateBody.d.ts.map +1 -0
  141. package/lib/http/router/expressLikeRouter.d.ts +240 -0
  142. package/lib/http/router/expressLikeRouter.d.ts.map +1 -0
  143. package/lib/http/router/routerSharedLogic.d.ts +50 -0
  144. package/lib/http/router/routerSharedLogic.d.ts.map +1 -0
  145. package/lib/http/router/unpackRouters.d.ts +7 -0
  146. package/lib/http/router/unpackRouters.d.ts.map +1 -0
  147. package/lib/http/telemetry/auditLogger.d.ts +21 -0
  148. package/lib/http/telemetry/auditLogger.d.ts.map +1 -0
  149. package/lib/http/telemetry/constants.d.ts +6 -0
  150. package/lib/http/telemetry/constants.d.ts.map +1 -0
  151. package/lib/http/telemetry/evaluateTelemetryOptions.d.ts +11 -0
  152. package/lib/http/telemetry/evaluateTelemetryOptions.d.ts.map +1 -0
  153. package/lib/http/telemetry/metricsDefinition.d.ts +3 -0
  154. package/lib/http/telemetry/metricsDefinition.d.ts.map +1 -0
  155. package/lib/http/telemetry/openTelemetryCollector.d.ts +53 -0
  156. package/lib/http/telemetry/openTelemetryCollector.d.ts.map +1 -0
  157. package/lib/http/telemetry/pinoLogger.d.ts +20 -0
  158. package/lib/http/telemetry/pinoLogger.d.ts.map +1 -0
  159. package/lib/http/telemetry/recordMetric.d.ts +5 -0
  160. package/lib/http/telemetry/recordMetric.d.ts.map +1 -0
  161. package/lib/http/types/apiDefinition.types.d.ts +471 -0
  162. package/lib/http/types/apiDefinition.types.d.ts.map +1 -0
  163. package/lib/http/types/contractDetails.types.d.ts +404 -0
  164. package/lib/http/types/contractDetails.types.d.ts.map +1 -0
  165. package/lib/http/types/docsConfiguration.types.d.ts +7 -0
  166. package/lib/http/types/docsConfiguration.types.d.ts.map +1 -0
  167. package/lib/http/types/expressLikeOptions.d.ts +224 -0
  168. package/lib/http/types/expressLikeOptions.d.ts.map +1 -0
  169. package/lib/http/types/expressLikeRouter.types.d.ts +127 -0
  170. package/lib/http/types/expressLikeRouter.types.d.ts.map +1 -0
  171. package/lib/http/types/openTelemetryCollector.types.d.ts +21 -0
  172. package/lib/http/types/openTelemetryCollector.types.d.ts.map +1 -0
  173. package/lib/http/types/router.types.d.ts +52 -0
  174. package/lib/http/types/router.types.d.ts.map +1 -0
  175. package/lib/http/types/sdk.types.d.ts +259 -0
  176. package/lib/http/types/sdk.types.d.ts.map +1 -0
  177. package/lib/http/types/typedHandler.types.d.ts +18 -0
  178. package/lib/http/types/typedHandler.types.d.ts.map +1 -0
  179. package/lib/mappers/guards/isSchemaResolutionFunction.d.ts +10 -0
  180. package/lib/mappers/guards/isSchemaResolutionFunction.d.ts.map +1 -0
  181. package/lib/mappers/index.d.ts +3 -68
  182. package/lib/mappers/index.d.ts.map +1 -0
  183. package/lib/mappers/mapServiceSchemas.d.ts +33 -0
  184. package/lib/mappers/mapServiceSchemas.d.ts.map +1 -0
  185. package/lib/mappers/mapper.d.ts +26 -0
  186. package/lib/mappers/mapper.d.ts.map +1 -0
  187. package/lib/mappers/types/schemaResolution.types.d.ts +9 -0
  188. package/lib/mappers/types/schemaResolution.types.d.ts.map +1 -0
  189. package/lib/objectstore/index.d.ts +3 -71
  190. package/lib/objectstore/index.d.ts.map +1 -0
  191. package/lib/objectstore/{index.d.mts → interfaces/objectstore.interface.d.ts} +3 -16
  192. package/lib/objectstore/interfaces/objectstore.interface.d.ts.map +1 -0
  193. package/lib/objectstore/objectstoreKey.d.ts +11 -0
  194. package/lib/objectstore/objectstoreKey.d.ts.map +1 -0
  195. package/lib/persistence/complianceEventSubscriber.d.ts +13 -0
  196. package/lib/persistence/complianceEventSubscriber.d.ts.map +1 -0
  197. package/lib/persistence/compliancePropertyBuilder.d.ts +26 -0
  198. package/lib/persistence/compliancePropertyBuilder.d.ts.map +1 -0
  199. package/lib/persistence/complianceTypes.d.ts +64 -0
  200. package/lib/persistence/complianceTypes.d.ts.map +1 -0
  201. package/lib/persistence/defineComplianceEntity.d.ts +19 -0
  202. package/lib/persistence/defineComplianceEntity.d.ts.map +1 -0
  203. package/lib/persistence/encryptedType.d.ts +85 -0
  204. package/lib/persistence/encryptedType.d.ts.map +1 -0
  205. package/lib/persistence/fieldEncryptor.d.ts +48 -0
  206. package/lib/persistence/fieldEncryptor.d.ts.map +1 -0
  207. package/lib/persistence/index.d.ts +10 -403
  208. package/lib/persistence/index.d.ts.map +1 -0
  209. package/lib/persistence/index.js.map +1 -1
  210. package/lib/persistence/index.mjs.map +1 -1
  211. package/lib/persistence/rls.d.ts +56 -0
  212. package/lib/persistence/rls.d.ts.map +1 -0
  213. package/lib/persistence/tenantEm.d.ts +60 -0
  214. package/lib/persistence/tenantEm.d.ts.map +1 -0
  215. package/lib/persistence/tenantFilter.d.ts +47 -0
  216. package/lib/persistence/tenantFilter.d.ts.map +1 -0
  217. package/lib/secrets/index.d.ts +2 -0
  218. package/lib/secrets/index.d.ts.map +1 -0
  219. package/lib/secrets/secretsAccessor.d.ts +17 -0
  220. package/lib/secrets/secretsAccessor.d.ts.map +1 -0
  221. package/lib/services/complianceDataService.d.ts +47 -0
  222. package/lib/services/complianceDataService.d.ts.map +1 -0
  223. package/lib/services/configInjector.d.ts +43 -0
  224. package/lib/services/configInjector.d.ts.map +1 -0
  225. package/lib/services/guards/isConstructed.d.ts +3 -0
  226. package/lib/services/guards/isConstructed.d.ts.map +1 -0
  227. package/lib/services/guards/isConstructedSingleton.d.ts +3 -0
  228. package/lib/services/guards/isConstructedSingleton.d.ts.map +1 -0
  229. package/lib/services/guards/isConstructor.d.ts +3 -0
  230. package/lib/services/guards/isConstructor.d.ts.map +1 -0
  231. package/lib/services/index.d.ts +10 -184
  232. package/lib/services/index.d.ts.map +1 -0
  233. package/lib/services/retentionService.d.ts +31 -0
  234. package/lib/services/retentionService.d.ts.map +1 -0
  235. package/lib/services/runRetentionEnforcement.d.ts +19 -0
  236. package/lib/services/runRetentionEnforcement.d.ts.map +1 -0
  237. package/lib/services/types/configInjector.types.d.ts +39 -0
  238. package/lib/services/types/configInjector.types.d.ts.map +1 -0
  239. package/lib/services/types/entityManager.types.d.ts +4 -0
  240. package/lib/services/types/entityManager.types.d.ts.map +1 -0
  241. package/lib/services/types/service.types.d.ts +5 -0
  242. package/lib/services/types/service.types.d.ts.map +1 -0
  243. package/lib/ws/asyncApiV3Generator/asyncApiV3Generator.d.ts +12 -0
  244. package/lib/ws/asyncApiV3Generator/asyncApiV3Generator.d.ts.map +1 -0
  245. package/lib/ws/index.d.ts +4 -67
  246. package/lib/ws/index.d.ts.map +1 -0
  247. package/lib/ws/index.js.map +1 -1
  248. package/lib/ws/index.mjs.map +1 -1
  249. package/lib/ws/types/eventSchema.types.d.ts +28 -0
  250. package/lib/ws/types/eventSchema.types.d.ts.map +1 -0
  251. package/lib/ws/webSocketLike.d.ts +18 -0
  252. package/lib/ws/webSocketLike.d.ts.map +1 -0
  253. package/package.json +47 -46
  254. package/LICENSE +0 -21
  255. package/lib/apiDefinition.types-DF_crhB0.d.mts +0 -1092
  256. package/lib/apiDefinition.types-DW4lfZqy.d.ts +0 -1092
  257. package/lib/http/index.d.mts +0 -1244
  258. package/lib/mappers/index.d.mts +0 -68
  259. package/lib/openTelemetryCollector-BS-ej09T.d.mts +0 -70
  260. package/lib/openTelemetryCollector-BS-ej09T.d.ts +0 -70
  261. package/lib/persistence/index.d.mts +0 -403
  262. package/lib/services/index.d.mts +0 -185
  263. package/lib/ttlCache.interface-CEOkrt8d.d.mts +0 -77
  264. package/lib/ttlCacheRecord.types-oX0ti5SP.d.ts +0 -25
  265. package/lib/ws/index.d.mts +0 -67
@@ -92,8 +92,9 @@ function isTypedHandler(maybeTypedHandler) {
92
92
  }
93
93
 
94
94
  // src/http/middleware/request/createContext.middleware.ts
95
- import { getEnvVar } from "@forklaunch/common";
96
- import { context, trace } from "@opentelemetry/api";
95
+ import { getEnvVar as getEnvVar2 } from "@forklaunch/common";
96
+ import { context, trace as trace2 } from "@opentelemetry/api";
97
+ import { ATTR_SERVICE_NAME as OTEL_ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
97
98
  import { v4 } from "uuid";
98
99
 
99
100
  // src/http/telemetry/constants.ts
@@ -107,6 +108,331 @@ var ATTR_API_NAME = "api.name";
107
108
  var ATTR_CORRELATION_ID = "correlation.id";
108
109
  var ATTR_APPLICATION_ID = "application_id";
109
110
 
111
+ // src/http/telemetry/openTelemetryCollector.ts
112
+ import { getEnvVar } from "@forklaunch/common";
113
+ import { HyperExpressInstrumentation } from "@forklaunch/opentelemetry-instrumentation-hyper-express";
114
+ import {
115
+ metrics
116
+ } from "@opentelemetry/api";
117
+ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
118
+ import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
119
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
120
+ import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";
121
+ import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
122
+ import { resourceFromAttributes } from "@opentelemetry/resources";
123
+ import { BatchLogRecordProcessor } from "@opentelemetry/sdk-logs";
124
+ import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
125
+ import { NodeSDK } from "@opentelemetry/sdk-node";
126
+ import {
127
+ ATTR_SERVICE_NAME as ATTR_SERVICE_NAME2
128
+ } from "@opentelemetry/semantic-conventions";
129
+ import dotenv from "dotenv";
130
+
131
+ // src/http/guards/isForklaunchRequest.ts
132
+ function isForklaunchRequest(request) {
133
+ return request != null && typeof request === "object" && "contractDetails" in request;
134
+ }
135
+
136
+ // src/http/telemetry/pinoLogger.ts
137
+ import { isNever } from "@forklaunch/common";
138
+ import { trace } from "@opentelemetry/api";
139
+ import { logs } from "@opentelemetry/api-logs";
140
+ import pino from "pino";
141
+
142
+ // src/http/guards/isLoggerMeta.ts
143
+ function isLoggerMeta(arg) {
144
+ return typeof arg === "object" && arg !== null && "_meta" in arg;
145
+ }
146
+
147
+ // src/http/telemetry/pinoLogger.ts
148
+ function meta(meta2) {
149
+ return meta2;
150
+ }
151
+ function mapSeverity(level) {
152
+ switch (level) {
153
+ case "silent":
154
+ return 0;
155
+ case "trace":
156
+ return 1;
157
+ case "debug":
158
+ return 5;
159
+ case "info":
160
+ return 9;
161
+ case "warn":
162
+ return 13;
163
+ case "error":
164
+ return 17;
165
+ case "fatal":
166
+ return 21;
167
+ default:
168
+ isNever(level);
169
+ return 0;
170
+ }
171
+ }
172
+ function normalizeLogArgs(args) {
173
+ let message = "";
174
+ const metaObjects = [];
175
+ for (const arg of args) {
176
+ if (typeof arg === "string" && message === "") {
177
+ message = arg;
178
+ } else if (arg instanceof Error) {
179
+ metaObjects.push({
180
+ err: {
181
+ message: arg.message,
182
+ name: arg.name,
183
+ stack: arg.stack,
184
+ ...Object.keys(arg).length > 0 ? arg : {}
185
+ }
186
+ });
187
+ } else if (arg && typeof arg === "object" && !Array.isArray(arg)) {
188
+ metaObjects.push(arg);
189
+ } else {
190
+ message += ` ${String(arg)}`;
191
+ }
192
+ }
193
+ const metadata = Object.assign({}, ...metaObjects);
194
+ return [metadata, message.trim()];
195
+ }
196
+ function safePrettyFormat(level, args, timestamp) {
197
+ try {
198
+ const [metadata, message] = normalizeLogArgs(args);
199
+ const formattedTimestamp = timestamp || (/* @__PURE__ */ new Date()).toISOString();
200
+ return `[${formattedTimestamp}] ${level.toUpperCase()}: ${message}${Object.keys(metadata).length > 0 ? `
201
+ ${JSON.stringify(metadata, null, 2)}` : ""}`;
202
+ } catch (error) {
203
+ const fallbackMessage = args.map((arg) => {
204
+ try {
205
+ if (typeof arg === "string") return arg;
206
+ if (arg === null) return "null";
207
+ if (arg === void 0) return "undefined";
208
+ return JSON.stringify(arg);
209
+ } catch {
210
+ return "[Circular/Non-serializable Object]";
211
+ }
212
+ }).join(" ");
213
+ return `[${(/* @__PURE__ */ new Date()).toISOString()}] ${level.toUpperCase()}: ${fallbackMessage} [Pretty Print Error: ${error instanceof Error ? error.message : "Unknown error"}]`;
214
+ }
215
+ }
216
+ var PinoLogger = class _PinoLogger {
217
+ _pinoLogger;
218
+ _meta;
219
+ constructor(level, meta2 = {}) {
220
+ this._pinoLogger = pino({
221
+ level: level || "info",
222
+ formatters: {
223
+ level(label) {
224
+ return { level: label };
225
+ }
226
+ },
227
+ timestamp: pino.stdTimeFunctions.isoTime,
228
+ transport: {
229
+ target: "pino-pretty",
230
+ options: {
231
+ colorize: true,
232
+ errorLikeObjectKeys: ["err", "error"],
233
+ ignore: "pid,hostname",
234
+ translateTime: "SYS:standard"
235
+ }
236
+ }
237
+ });
238
+ this._meta = meta2;
239
+ }
240
+ log(level, ...args) {
241
+ let meta2 = {};
242
+ const filteredArgs = args.filter((arg) => {
243
+ if (isLoggerMeta(arg)) {
244
+ Object.assign(meta2, arg);
245
+ return false;
246
+ }
247
+ return true;
248
+ });
249
+ const [errorMetadata] = normalizeLogArgs(filteredArgs);
250
+ Object.assign(meta2, errorMetadata);
251
+ const activeSpan = trace.getActiveSpan();
252
+ if (activeSpan) {
253
+ const activeSpanContext = activeSpan.spanContext();
254
+ meta2.trace_id = activeSpanContext.traceId;
255
+ meta2.span_id = activeSpanContext.spanId;
256
+ meta2.trace_flags = activeSpanContext.traceFlags;
257
+ meta2 = {
258
+ // @ts-expect-error accessing private property
259
+ ...activeSpan.attributes,
260
+ ...meta2
261
+ };
262
+ }
263
+ meta2 = {
264
+ "api.name": "none",
265
+ "correlation.id": "none",
266
+ ...meta2
267
+ };
268
+ this._pinoLogger[level](...normalizeLogArgs(filteredArgs));
269
+ const formattedBody = safePrettyFormat(level, filteredArgs);
270
+ try {
271
+ logs.getLogger(process.env.OTEL_SERVICE_NAME ?? "unknown").emit({
272
+ severityText: level,
273
+ severityNumber: mapSeverity(level),
274
+ body: formattedBody,
275
+ attributes: { ...this._meta, ...meta2 }
276
+ });
277
+ } catch (error) {
278
+ console.error("Failed to emit OpenTelemetry log:", error);
279
+ console.log(
280
+ `[${(/* @__PURE__ */ new Date()).toISOString()}] ${level.toUpperCase()}:`,
281
+ ...filteredArgs
282
+ );
283
+ }
284
+ }
285
+ error = (msg, ...args) => this.log("error", msg, ...args);
286
+ info = (msg, ...args) => this.log("info", msg, ...args);
287
+ debug = (msg, ...args) => this.log("debug", msg, ...args);
288
+ warn = (msg, ...args) => this.log("warn", msg, ...args);
289
+ trace = (msg, ...args) => this.log("trace", msg, ...args);
290
+ child(meta2 = {}) {
291
+ return new _PinoLogger(this._pinoLogger.level, { ...this._meta, ...meta2 });
292
+ }
293
+ getBaseLogger() {
294
+ return this._pinoLogger;
295
+ }
296
+ };
297
+ function logger(level, meta2 = {}) {
298
+ return new PinoLogger(level, meta2);
299
+ }
300
+
301
+ // src/http/telemetry/openTelemetryCollector.ts
302
+ var OpenTelemetryCollector = class {
303
+ _logger;
304
+ _serviceName;
305
+ _metrics;
306
+ // scoped creation and create this in middleware when api execute. Also add correlation id
307
+ constructor(serviceName, level, metricDefinitions) {
308
+ this._serviceName = serviceName;
309
+ this._logger = logger(level || "info");
310
+ this._metrics = {};
311
+ for (const [metricId, metricType] of Object.entries(
312
+ metricDefinitions ?? {}
313
+ )) {
314
+ switch (metricType) {
315
+ case "counter":
316
+ this._metrics[metricId] = metrics.getMeter(this._serviceName).createCounter(metricId);
317
+ break;
318
+ case "gauge":
319
+ this._metrics[metricId] = metrics.getMeter(this._serviceName).createGauge(metricId);
320
+ break;
321
+ case "histogram":
322
+ this._metrics[metricId] = metrics.getMeter(this._serviceName).createHistogram(metricId);
323
+ break;
324
+ case "upDownCounter":
325
+ this._metrics[metricId] = metrics.getMeter(this._serviceName).createUpDownCounter(metricId);
326
+ break;
327
+ case "observableCounter":
328
+ this._metrics[metricId] = metrics.getMeter(this._serviceName).createObservableCounter(metricId);
329
+ break;
330
+ case "observableGauge":
331
+ this._metrics[metricId] = metrics.getMeter(this._serviceName).createObservableGauge(metricId);
332
+ break;
333
+ case "observableUpDownCounter":
334
+ this._metrics[metricId] = metrics.getMeter(this._serviceName).createObservableUpDownCounter(metricId);
335
+ break;
336
+ }
337
+ }
338
+ this.log(
339
+ "info",
340
+ "OpenTelemetry Collector (Traces + Logs + Metrics) started"
341
+ );
342
+ }
343
+ log(level, ...args) {
344
+ this._logger.log(level, ...args);
345
+ }
346
+ info = (msg, ...args) => {
347
+ this._logger.log("info", msg, ...args);
348
+ };
349
+ error = (msg, ...args) => {
350
+ this._logger.log("error", msg, ...args);
351
+ };
352
+ warn = (msg, ...args) => {
353
+ this._logger.log("warn", msg, ...args);
354
+ };
355
+ debug = (msg, ...args) => {
356
+ this._logger.log("debug", msg, ...args);
357
+ };
358
+ trace = (msg, ...args) => {
359
+ this._logger.log("trace", msg, ...args);
360
+ };
361
+ getMetric(metricId) {
362
+ return this._metrics[metricId];
363
+ }
364
+ };
365
+ dotenv.config({ path: getEnvVar("DOTENV_FILE_PATH") });
366
+ function parseOtelHeaders() {
367
+ const headersEnv = getEnvVar("OTEL_EXPORTER_OTLP_HEADERS");
368
+ if (!headersEnv) return void 0;
369
+ const headers = {};
370
+ for (const pair of headersEnv.split(",")) {
371
+ const [key, ...valueParts] = pair.split("=");
372
+ if (key && valueParts.length > 0) {
373
+ headers[key.trim()] = valueParts.join("=").trim();
374
+ }
375
+ }
376
+ return Object.keys(headers).length > 0 ? headers : void 0;
377
+ }
378
+ var otelHeaders = parseOtelHeaders();
379
+ new NodeSDK({
380
+ resource: resourceFromAttributes({
381
+ [ATTR_SERVICE_NAME2]: getEnvVar("OTEL_SERVICE_NAME")
382
+ }),
383
+ traceExporter: new OTLPTraceExporter({
384
+ url: `${getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/traces`,
385
+ headers: otelHeaders
386
+ }),
387
+ metricReader: new PeriodicExportingMetricReader({
388
+ exporter: new OTLPMetricExporter({
389
+ url: `${getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/metrics`,
390
+ headers: otelHeaders
391
+ }),
392
+ exportIntervalMillis: 5e3
393
+ }),
394
+ logRecordProcessors: [
395
+ new BatchLogRecordProcessor({
396
+ exporter: new OTLPLogExporter({
397
+ url: `${getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/logs`,
398
+ headers: otelHeaders
399
+ })
400
+ })
401
+ ],
402
+ instrumentations: [
403
+ new HttpInstrumentation({
404
+ applyCustomAttributesOnSpan: (span, request) => {
405
+ span.setAttribute(
406
+ ATTR_SERVICE_NAME2,
407
+ getEnvVar("OTEL_SERVICE_NAME") ?? "unknown"
408
+ );
409
+ if (isForklaunchRequest(request)) {
410
+ span.setAttribute(ATTR_API_NAME, request.contractDetails?.name);
411
+ span.setAttribute(ATTR_CORRELATION_ID, request.context.correlationId);
412
+ }
413
+ }
414
+ }),
415
+ new ExpressInstrumentation(),
416
+ new HyperExpressInstrumentation()
417
+ ]
418
+ }).start();
419
+ var httpRequestsTotalCounter = metrics.getMeter(getEnvVar("OTEL_SERVICE_NAME") || "unknown").createCounter("http_requests_total", {
420
+ description: "Number of HTTP requests"
421
+ });
422
+ var httpServerDurationHistogram = metrics.getMeter(getEnvVar("OTEL_SERVICE_NAME") || "unknown").createHistogram("http_server_duration", {
423
+ description: "Duration of HTTP server requests",
424
+ unit: "s"
425
+ });
426
+ var httpRequestDurationMsHistogram = metrics.getMeter(getEnvVar("OTEL_SERVICE_NAME") || "unknown").createHistogram("http_request_duration_ms", {
427
+ description: "Duration of HTTP requests in milliseconds"
428
+ });
429
+ var httpErrorsTotalCounter = metrics.getMeter(getEnvVar("OTEL_SERVICE_NAME") || "unknown").createCounter("http_errors_total", {
430
+ description: "Total number of HTTP errors (4xx/5xx)"
431
+ });
432
+ var httpRequestsInFlightCounter = metrics.getMeter(getEnvVar("OTEL_SERVICE_NAME") || "unknown").createUpDownCounter("http_requests_in_flight", {
433
+ description: "Number of HTTP requests currently in flight"
434
+ });
435
+
110
436
  // src/http/middleware/request/createContext.middleware.ts
111
437
  function createContext(schemaValidator) {
112
438
  return function setContext(req, res, next) {
@@ -117,16 +443,30 @@ function createContext(schemaValidator) {
117
443
  }
118
444
  res.setHeader("x-correlation-id", correlationId);
119
445
  req.context = {
120
- correlationId
446
+ correlationId,
447
+ requestStartTime: Date.now()
448
+ };
449
+ const serviceName = getEnvVar2("OTEL_SERVICE_NAME") || "unknown";
450
+ const inFlightAttrs = {
451
+ [OTEL_ATTR_SERVICE_NAME]: serviceName
121
452
  };
122
- const span = trace.getSpan(context.active());
453
+ let inFlightActive = true;
454
+ const decrementInFlight = () => {
455
+ if (!inFlightActive) {
456
+ return;
457
+ }
458
+ httpRequestsInFlightCounter.add(-1, inFlightAttrs);
459
+ inFlightActive = false;
460
+ };
461
+ httpRequestsInFlightCounter.add(1, inFlightAttrs);
462
+ res.on("finish", decrementInFlight);
463
+ res.on("close", decrementInFlight);
464
+ res.on("error", decrementInFlight);
465
+ const span = trace2.getSpan(context.active());
123
466
  if (span != null) {
124
467
  req.context.span = span;
125
468
  req.context.span?.setAttribute(ATTR_CORRELATION_ID, correlationId);
126
- req.context.span?.setAttribute(
127
- ATTR_SERVICE_NAME,
128
- getEnvVar("OTEL_SERVICE_NAME")
129
- );
469
+ req.context.span?.setAttribute(ATTR_SERVICE_NAME, serviceName);
130
470
  }
131
471
  next?.();
132
472
  };
@@ -387,254 +727,89 @@ async function discriminateAuthMethod(auth, openTelemetryCollector) {
387
727
  };
388
728
  } else {
389
729
  let jwks;
390
- if ("jwksPublicKeyUrl" in jwt) {
391
- jwks = await getCachedJwks(jwt.jwksPublicKeyUrl);
392
- } else if ("jwksPublicKey" in jwt) {
393
- jwks = [jwt.jwksPublicKey];
394
- }
395
- verificationFunction = async (token) => {
396
- for (const key of jwks) {
397
- try {
398
- const { payload } = await jwtVerify(token, key);
399
- return payload;
400
- } catch {
401
- cachedJwks.value = null;
402
- cachedJwks.lastUpdated = null;
403
- cachedJwks.ttl = DEFAULT_TTL;
404
- continue;
405
- }
406
- }
407
- };
408
- }
409
- authMethod = {
410
- type: "jwt",
411
- auth: {
412
- decodeResource: auth.decodeResource,
413
- verificationFunction
414
- }
415
- };
416
- } else if (isHmacMethod(auth)) {
417
- authMethod = {
418
- type: "hmac",
419
- auth: {
420
- secretKeys: auth.hmac.secretKeys,
421
- verificationFunction: async ({
422
- method,
423
- path,
424
- body,
425
- timestamp,
426
- nonce,
427
- signature,
428
- secretKey
429
- }) => {
430
- const computedSignature = createHmacToken({
431
- method,
432
- path,
433
- body,
434
- timestamp,
435
- nonce,
436
- secretKey
437
- });
438
- const isValid = computedSignature === signature;
439
- if (!isValid) {
440
- const errorInfo = {
441
- method,
442
- path,
443
- timestamp: timestamp.toISOString(),
444
- nonce,
445
- receivedSignature: signature,
446
- computedSignature
447
- };
448
- openTelemetryCollector?.debug("[HMAC Verification Failed]", {
449
- ...errorInfo,
450
- bodyType: body ? typeof body : "undefined",
451
- body: body ? safeStringify2(body) : "undefined"
452
- });
453
- }
454
- return isValid;
455
- }
456
- }
457
- };
458
- }
459
- if (authMethod == null) {
460
- throw new Error("Invalid auth method");
461
- }
462
- return authMethod;
463
- }
464
-
465
- // src/http/guards/hasFeatureChecks.ts
466
- function hasFeatureChecks(maybeFeatureAuth) {
467
- return typeof maybeFeatureAuth === "object" && maybeFeatureAuth !== null && "requiredFeatures" in maybeFeatureAuth && Array.isArray(maybeFeatureAuth.requiredFeatures) && maybeFeatureAuth.requiredFeatures.length > 0;
468
- }
469
-
470
- // src/http/guards/hasSubscriptionChecks.ts
471
- function hasSubscriptionChecks(maybeSubscriptionAuth) {
472
- return typeof maybeSubscriptionAuth === "object" && maybeSubscriptionAuth !== null && "requireActiveSubscription" in maybeSubscriptionAuth && maybeSubscriptionAuth.requireActiveSubscription === true;
473
- }
474
-
475
- // src/http/telemetry/pinoLogger.ts
476
- import { isNever } from "@forklaunch/common";
477
- import { trace as trace2 } from "@opentelemetry/api";
478
- import { logs } from "@opentelemetry/api-logs";
479
- import pino from "pino";
480
-
481
- // src/http/guards/isLoggerMeta.ts
482
- function isLoggerMeta(arg) {
483
- return typeof arg === "object" && arg !== null && "_meta" in arg;
484
- }
485
-
486
- // src/http/telemetry/pinoLogger.ts
487
- function meta(meta2) {
488
- return meta2;
489
- }
490
- function mapSeverity(level) {
491
- switch (level) {
492
- case "silent":
493
- return 0;
494
- case "trace":
495
- return 1;
496
- case "debug":
497
- return 5;
498
- case "info":
499
- return 9;
500
- case "warn":
501
- return 13;
502
- case "error":
503
- return 17;
504
- case "fatal":
505
- return 21;
506
- default:
507
- isNever(level);
508
- return 0;
509
- }
510
- }
511
- function normalizeLogArgs(args) {
512
- let message = "";
513
- const metaObjects = [];
514
- for (const arg of args) {
515
- if (typeof arg === "string" && message === "") {
516
- message = arg;
517
- } else if (arg instanceof Error) {
518
- metaObjects.push({
519
- err: {
520
- message: arg.message,
521
- name: arg.name,
522
- stack: arg.stack,
523
- ...Object.keys(arg).length > 0 ? arg : {}
524
- }
525
- });
526
- } else if (arg && typeof arg === "object" && !Array.isArray(arg)) {
527
- metaObjects.push(arg);
528
- } else {
529
- message += ` ${String(arg)}`;
530
- }
531
- }
532
- const metadata = Object.assign({}, ...metaObjects);
533
- return [metadata, message.trim()];
534
- }
535
- function safePrettyFormat(level, args, timestamp) {
536
- try {
537
- const [metadata, message] = normalizeLogArgs(args);
538
- const formattedTimestamp = timestamp || (/* @__PURE__ */ new Date()).toISOString();
539
- return `[${formattedTimestamp}] ${level.toUpperCase()}: ${message}${Object.keys(metadata).length > 0 ? `
540
- ${JSON.stringify(metadata, null, 2)}` : ""}`;
541
- } catch (error) {
542
- const fallbackMessage = args.map((arg) => {
543
- try {
544
- if (typeof arg === "string") return arg;
545
- if (arg === null) return "null";
546
- if (arg === void 0) return "undefined";
547
- return JSON.stringify(arg);
548
- } catch {
549
- return "[Circular/Non-serializable Object]";
550
- }
551
- }).join(" ");
552
- return `[${(/* @__PURE__ */ new Date()).toISOString()}] ${level.toUpperCase()}: ${fallbackMessage} [Pretty Print Error: ${error instanceof Error ? error.message : "Unknown error"}]`;
553
- }
554
- }
555
- var PinoLogger = class _PinoLogger {
556
- _pinoLogger;
557
- _meta;
558
- constructor(level, meta2 = {}) {
559
- this._pinoLogger = pino({
560
- level: level || "info",
561
- formatters: {
562
- level(label) {
563
- return { level: label };
564
- }
565
- },
566
- timestamp: pino.stdTimeFunctions.isoTime,
567
- transport: {
568
- target: "pino-pretty",
569
- options: {
570
- colorize: true,
571
- errorLikeObjectKeys: ["err", "error"],
572
- ignore: "pid,hostname",
573
- translateTime: "SYS:standard"
574
- }
575
- }
576
- });
577
- this._meta = meta2;
578
- }
579
- log(level, ...args) {
580
- let meta2 = {};
581
- const filteredArgs = args.filter((arg) => {
582
- if (isLoggerMeta(arg)) {
583
- Object.assign(meta2, arg);
584
- return false;
585
- }
586
- return true;
587
- });
588
- const [errorMetadata] = normalizeLogArgs(filteredArgs);
589
- Object.assign(meta2, errorMetadata);
590
- const activeSpan = trace2.getActiveSpan();
591
- if (activeSpan) {
592
- const activeSpanContext = activeSpan.spanContext();
593
- meta2.trace_id = activeSpanContext.traceId;
594
- meta2.span_id = activeSpanContext.spanId;
595
- meta2.trace_flags = activeSpanContext.traceFlags;
596
- meta2 = {
597
- // @ts-expect-error accessing private property
598
- ...activeSpan.attributes,
599
- ...meta2
730
+ if ("jwksPublicKeyUrl" in jwt) {
731
+ jwks = await getCachedJwks(jwt.jwksPublicKeyUrl);
732
+ } else if ("jwksPublicKey" in jwt) {
733
+ jwks = [jwt.jwksPublicKey];
734
+ }
735
+ verificationFunction = async (token) => {
736
+ for (const key of jwks) {
737
+ try {
738
+ const { payload } = await jwtVerify(token, key);
739
+ return payload;
740
+ } catch {
741
+ cachedJwks.value = null;
742
+ cachedJwks.lastUpdated = null;
743
+ cachedJwks.ttl = DEFAULT_TTL;
744
+ continue;
745
+ }
746
+ }
600
747
  };
601
748
  }
602
- meta2 = {
603
- "api.name": "none",
604
- "correlation.id": "none",
605
- ...meta2
749
+ authMethod = {
750
+ type: "jwt",
751
+ auth: {
752
+ decodeResource: auth.decodeResource,
753
+ verificationFunction
754
+ }
755
+ };
756
+ } else if (isHmacMethod(auth)) {
757
+ authMethod = {
758
+ type: "hmac",
759
+ auth: {
760
+ secretKeys: auth.hmac.secretKeys,
761
+ verificationFunction: async ({
762
+ method,
763
+ path,
764
+ body,
765
+ timestamp,
766
+ nonce,
767
+ signature,
768
+ secretKey
769
+ }) => {
770
+ const computedSignature = createHmacToken({
771
+ method,
772
+ path,
773
+ body,
774
+ timestamp,
775
+ nonce,
776
+ secretKey
777
+ });
778
+ const isValid = computedSignature === signature;
779
+ if (!isValid) {
780
+ const errorInfo = {
781
+ method,
782
+ path,
783
+ timestamp: timestamp.toISOString(),
784
+ nonce,
785
+ receivedSignature: signature,
786
+ computedSignature
787
+ };
788
+ openTelemetryCollector?.debug("[HMAC Verification Failed]", {
789
+ ...errorInfo,
790
+ bodyType: body ? typeof body : "undefined",
791
+ body: body ? safeStringify2(body) : "undefined"
792
+ });
793
+ }
794
+ return isValid;
795
+ }
796
+ }
606
797
  };
607
- this._pinoLogger[level](...normalizeLogArgs(filteredArgs));
608
- const formattedBody = safePrettyFormat(level, filteredArgs);
609
- try {
610
- logs.getLogger(process.env.OTEL_SERVICE_NAME ?? "unknown").emit({
611
- severityText: level,
612
- severityNumber: mapSeverity(level),
613
- body: formattedBody,
614
- attributes: { ...this._meta, ...meta2 }
615
- });
616
- } catch (error) {
617
- console.error("Failed to emit OpenTelemetry log:", error);
618
- console.log(
619
- `[${(/* @__PURE__ */ new Date()).toISOString()}] ${level.toUpperCase()}:`,
620
- ...filteredArgs
621
- );
622
- }
623
- }
624
- error = (msg, ...args) => this.log("error", msg, ...args);
625
- info = (msg, ...args) => this.log("info", msg, ...args);
626
- debug = (msg, ...args) => this.log("debug", msg, ...args);
627
- warn = (msg, ...args) => this.log("warn", msg, ...args);
628
- trace = (msg, ...args) => this.log("trace", msg, ...args);
629
- child(meta2 = {}) {
630
- return new _PinoLogger(this._pinoLogger.level, { ...this._meta, ...meta2 });
631
798
  }
632
- getBaseLogger() {
633
- return this._pinoLogger;
799
+ if (authMethod == null) {
800
+ throw new Error("Invalid auth method");
634
801
  }
635
- };
636
- function logger(level, meta2 = {}) {
637
- return new PinoLogger(level, meta2);
802
+ return authMethod;
803
+ }
804
+
805
+ // src/http/guards/hasFeatureChecks.ts
806
+ function hasFeatureChecks(maybeFeatureAuth) {
807
+ return typeof maybeFeatureAuth === "object" && maybeFeatureAuth !== null && "requiredFeatures" in maybeFeatureAuth && Array.isArray(maybeFeatureAuth.requiredFeatures) && maybeFeatureAuth.requiredFeatures.length > 0;
808
+ }
809
+
810
+ // src/http/guards/hasSubscriptionChecks.ts
811
+ function hasSubscriptionChecks(maybeSubscriptionAuth) {
812
+ return typeof maybeSubscriptionAuth === "object" && maybeSubscriptionAuth !== null && "requireActiveSubscription" in maybeSubscriptionAuth && maybeSubscriptionAuth.requireActiveSubscription === true;
638
813
  }
639
814
 
640
815
  // src/http/middleware/request/auth.middleware.ts
@@ -927,159 +1102,6 @@ async function parseRequestAuth(req, res, next) {
927
1102
 
928
1103
  // src/http/middleware/request/enrichDetails.middleware.ts
929
1104
  import { getEnvVar as getEnvVar3 } from "@forklaunch/common";
930
-
931
- // src/http/telemetry/openTelemetryCollector.ts
932
- import { getEnvVar as getEnvVar2 } from "@forklaunch/common";
933
- import { HyperExpressInstrumentation } from "@forklaunch/opentelemetry-instrumentation-hyper-express";
934
- import {
935
- metrics
936
- } from "@opentelemetry/api";
937
- import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
938
- import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
939
- import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
940
- import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";
941
- import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
942
- import { resourceFromAttributes } from "@opentelemetry/resources";
943
- import { BatchLogRecordProcessor } from "@opentelemetry/sdk-logs";
944
- import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
945
- import { NodeSDK } from "@opentelemetry/sdk-node";
946
- import {
947
- ATTR_SERVICE_NAME as ATTR_SERVICE_NAME2
948
- } from "@opentelemetry/semantic-conventions";
949
- import dotenv from "dotenv";
950
-
951
- // src/http/guards/isForklaunchRequest.ts
952
- function isForklaunchRequest(request) {
953
- return request != null && typeof request === "object" && "contractDetails" in request;
954
- }
955
-
956
- // src/http/telemetry/openTelemetryCollector.ts
957
- var OpenTelemetryCollector = class {
958
- _logger;
959
- _serviceName;
960
- _metrics;
961
- // scoped creation and create this in middleware when api execute. Also add correlation id
962
- constructor(serviceName, level, metricDefinitions) {
963
- this._serviceName = serviceName;
964
- this._logger = logger(level || "info");
965
- this._metrics = {};
966
- for (const [metricId, metricType] of Object.entries(
967
- metricDefinitions ?? {}
968
- )) {
969
- switch (metricType) {
970
- case "counter":
971
- this._metrics[metricId] = metrics.getMeter(this._serviceName).createCounter(metricId);
972
- break;
973
- case "gauge":
974
- this._metrics[metricId] = metrics.getMeter(this._serviceName).createGauge(metricId);
975
- break;
976
- case "histogram":
977
- this._metrics[metricId] = metrics.getMeter(this._serviceName).createHistogram(metricId);
978
- break;
979
- case "upDownCounter":
980
- this._metrics[metricId] = metrics.getMeter(this._serviceName).createUpDownCounter(metricId);
981
- break;
982
- case "observableCounter":
983
- this._metrics[metricId] = metrics.getMeter(this._serviceName).createObservableCounter(metricId);
984
- break;
985
- case "observableGauge":
986
- this._metrics[metricId] = metrics.getMeter(this._serviceName).createObservableGauge(metricId);
987
- break;
988
- case "observableUpDownCounter":
989
- this._metrics[metricId] = metrics.getMeter(this._serviceName).createObservableUpDownCounter(metricId);
990
- break;
991
- }
992
- }
993
- this.log(
994
- "info",
995
- "OpenTelemetry Collector (Traces + Logs + Metrics) started"
996
- );
997
- }
998
- log(level, ...args) {
999
- this._logger.log(level, ...args);
1000
- }
1001
- info = (msg, ...args) => {
1002
- this._logger.log("info", msg, ...args);
1003
- };
1004
- error = (msg, ...args) => {
1005
- this._logger.log("error", msg, ...args);
1006
- };
1007
- warn = (msg, ...args) => {
1008
- this._logger.log("warn", msg, ...args);
1009
- };
1010
- debug = (msg, ...args) => {
1011
- this._logger.log("debug", msg, ...args);
1012
- };
1013
- trace = (msg, ...args) => {
1014
- this._logger.log("trace", msg, ...args);
1015
- };
1016
- getMetric(metricId) {
1017
- return this._metrics[metricId];
1018
- }
1019
- };
1020
- dotenv.config({ path: getEnvVar2("DOTENV_FILE_PATH") });
1021
- function parseOtelHeaders() {
1022
- const headersEnv = getEnvVar2("OTEL_EXPORTER_OTLP_HEADERS");
1023
- if (!headersEnv) return void 0;
1024
- const headers = {};
1025
- for (const pair of headersEnv.split(",")) {
1026
- const [key, ...valueParts] = pair.split("=");
1027
- if (key && valueParts.length > 0) {
1028
- headers[key.trim()] = valueParts.join("=").trim();
1029
- }
1030
- }
1031
- return Object.keys(headers).length > 0 ? headers : void 0;
1032
- }
1033
- var otelHeaders = parseOtelHeaders();
1034
- new NodeSDK({
1035
- resource: resourceFromAttributes({
1036
- [ATTR_SERVICE_NAME2]: getEnvVar2("OTEL_SERVICE_NAME")
1037
- }),
1038
- traceExporter: new OTLPTraceExporter({
1039
- url: `${getEnvVar2("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/traces`,
1040
- headers: otelHeaders
1041
- }),
1042
- metricReader: new PeriodicExportingMetricReader({
1043
- exporter: new OTLPMetricExporter({
1044
- url: `${getEnvVar2("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/metrics`,
1045
- headers: otelHeaders
1046
- }),
1047
- exportIntervalMillis: 5e3
1048
- }),
1049
- logRecordProcessors: [
1050
- new BatchLogRecordProcessor(
1051
- new OTLPLogExporter({
1052
- url: `${getEnvVar2("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/logs`,
1053
- headers: otelHeaders
1054
- })
1055
- )
1056
- ],
1057
- instrumentations: [
1058
- new HttpInstrumentation({
1059
- applyCustomAttributesOnSpan: (span, request) => {
1060
- span.setAttribute(
1061
- ATTR_SERVICE_NAME2,
1062
- getEnvVar2("OTEL_SERVICE_NAME") ?? "unknown"
1063
- );
1064
- if (isForklaunchRequest(request)) {
1065
- span.setAttribute(ATTR_API_NAME, request.contractDetails?.name);
1066
- span.setAttribute(ATTR_CORRELATION_ID, request.context.correlationId);
1067
- }
1068
- }
1069
- }),
1070
- new ExpressInstrumentation(),
1071
- new HyperExpressInstrumentation()
1072
- ]
1073
- }).start();
1074
- var httpRequestsTotalCounter = metrics.getMeter(getEnvVar2("OTEL_SERVICE_NAME") || "unknown").createCounter("http_requests_total", {
1075
- description: "Number of HTTP requests"
1076
- });
1077
- var httpServerDurationHistogram = metrics.getMeter(getEnvVar2("OTEL_SERVICE_NAME") || "unknown").createHistogram("http_server_duration", {
1078
- description: "Duration of HTTP server requests",
1079
- unit: "s"
1080
- });
1081
-
1082
- // src/http/middleware/request/enrichDetails.middleware.ts
1083
1105
  function enrichDetails(path, contractDetails, requestSchema, responseSchemas, openTelemetryCollector, globalOptions) {
1084
1106
  return (req, res, next) => {
1085
1107
  req.originalPath = path;
@@ -3789,14 +3811,21 @@ function recordMetric(req, res) {
3789
3811
  if (res.metricRecorded) {
3790
3812
  return;
3791
3813
  }
3792
- httpRequestsTotalCounter.add(1, {
3793
- [ATTR_SERVICE_NAME3]: getEnvVar4("OTEL_SERVICE_NAME"),
3814
+ const serviceName = getEnvVar4("OTEL_SERVICE_NAME") || "unknown";
3815
+ const attrs = {
3816
+ [ATTR_SERVICE_NAME3]: serviceName,
3794
3817
  [ATTR_APPLICATION_ID]: getEnvVar4("OTEL_APPLICATION_ID"),
3795
3818
  [ATTR_API_NAME]: req.contractDetails?.name,
3796
3819
  [ATTR_HTTP_REQUEST_METHOD3]: req.method,
3797
3820
  [ATTR_HTTP_ROUTE3]: req.originalPath,
3798
3821
  [ATTR_HTTP_RESPONSE_STATUS_CODE3]: Number(res.statusCode) || 0
3799
- });
3822
+ };
3823
+ httpRequestsTotalCounter.add(1, attrs);
3824
+ const durationMs = req.context?.requestStartTime != null ? Date.now() - req.context.requestStartTime : 0;
3825
+ httpRequestDurationMsHistogram.record(durationMs, attrs);
3826
+ if (Number(res.statusCode) >= 400) {
3827
+ httpErrorsTotalCounter.add(1, attrs);
3828
+ }
3800
3829
  res.metricRecorded = true;
3801
3830
  }
3802
3831
 
@@ -4438,6 +4467,9 @@ export {
4438
4467
  getCachedJwks,
4439
4468
  getCodeForStatus,
4440
4469
  head,
4470
+ httpErrorsTotalCounter,
4471
+ httpRequestDurationMsHistogram,
4472
+ httpRequestsInFlightCounter,
4441
4473
  httpRequestsTotalCounter,
4442
4474
  httpServerDurationHistogram,
4443
4475
  isClientError,