@forklaunch/core 0.5.2 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/http/index.js CHANGED
@@ -47,6 +47,7 @@ __export(http_exports, {
47
47
  getCodeForStatus: () => getCodeForStatus,
48
48
  head: () => head,
49
49
  httpRequestsTotalCounter: () => httpRequestsTotalCounter,
50
+ httpServerDurationHistogram: () => httpServerDurationHistogram,
50
51
  isClientError: () => isClientError,
51
52
  isForklaunchRequest: () => isForklaunchRequest,
52
53
  isForklaunchRouter: () => isForklaunchRouter,
@@ -56,6 +57,7 @@ __export(http_exports, {
56
57
  isSuccessful: () => isSuccessful,
57
58
  isValidStatusCode: () => isValidStatusCode,
58
59
  logger: () => logger,
60
+ meta: () => meta,
59
61
  metricsDefinitions: () => metricsDefinitions,
60
62
  middleware: () => middleware,
61
63
  options: () => options,
@@ -63,7 +65,7 @@ __export(http_exports, {
63
65
  post: () => post,
64
66
  put: () => put,
65
67
  recordMetric: () => recordMetric,
66
- trace: () => trace2,
68
+ trace: () => trace3,
67
69
  typedHandler: () => typedHandler
68
70
  });
69
71
  module.exports = __toCommonJS(http_exports);
@@ -201,7 +203,7 @@ async function checkAuthorizationToken(authorizationMethod, authorizationToken,
201
203
  }
202
204
  resourceId = decodedJwt.payload.sub;
203
205
  } catch (error) {
204
- console.error(error);
206
+ req.openTelemetryCollector.error(error);
205
207
  return invalidAuthorizationToken;
206
208
  }
207
209
  break;
@@ -282,14 +284,267 @@ async function parseRequestAuth(req, res, next) {
282
284
  next?.();
283
285
  }
284
286
 
287
+ // src/services/getEnvVar.ts
288
+ function getEnvVar(name) {
289
+ const value = process.env[name];
290
+ return value;
291
+ }
292
+
293
+ // src/http/telemetry/openTelemetryCollector.ts
294
+ var import_opentelemetry_instrumentation_hyper_express = require("@forklaunch/opentelemetry-instrumentation-hyper-express");
295
+ var import_api3 = require("@opentelemetry/api");
296
+ var import_exporter_logs_otlp_http = require("@opentelemetry/exporter-logs-otlp-http");
297
+ var import_exporter_metrics_otlp_http = require("@opentelemetry/exporter-metrics-otlp-http");
298
+ var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
299
+ var import_instrumentation_express = require("@opentelemetry/instrumentation-express");
300
+ var import_instrumentation_http = require("@opentelemetry/instrumentation-http");
301
+ var import_resources = require("@opentelemetry/resources");
302
+ var import_sdk_logs = require("@opentelemetry/sdk-logs");
303
+ var import_sdk_metrics = require("@opentelemetry/sdk-metrics");
304
+ var import_sdk_node = require("@opentelemetry/sdk-node");
305
+ var import_semantic_conventions2 = require("@opentelemetry/semantic-conventions");
306
+ var import_dotenv = __toESM(require("dotenv"));
307
+
308
+ // src/http/guards/isForklaunchRequest.ts
309
+ function isForklaunchRequest(request) {
310
+ return request != null && typeof request === "object" && "contractDetails" in request;
311
+ }
312
+
313
+ // src/http/telemetry/pinoLogger.ts
314
+ var import_common2 = require("@forklaunch/common");
315
+ var import_api2 = require("@opentelemetry/api");
316
+ var import_api_logs = require("@opentelemetry/api-logs");
317
+ var import_pino = __toESM(require("pino"));
318
+
319
+ // src/http/guards/isLoggerMeta.ts
320
+ function isLoggerMeta(arg) {
321
+ return typeof arg === "object" && arg !== null && "_meta" in arg;
322
+ }
323
+
324
+ // src/http/telemetry/pinoLogger.ts
325
+ var import_pino_pretty = __toESM(require("pino-pretty"));
326
+ function meta(meta2) {
327
+ return meta2;
328
+ }
329
+ function mapSeverity(level) {
330
+ switch (level) {
331
+ case "silent":
332
+ return 0;
333
+ case "trace":
334
+ return 1;
335
+ case "debug":
336
+ return 5;
337
+ case "info":
338
+ return 9;
339
+ case "warn":
340
+ return 13;
341
+ case "error":
342
+ return 17;
343
+ case "fatal":
344
+ return 21;
345
+ default:
346
+ (0, import_common2.isNever)(level);
347
+ return 0;
348
+ }
349
+ }
350
+ var PinoLogger = class _PinoLogger {
351
+ pinoLogger;
352
+ meta;
353
+ prettyPrinter = import_pino_pretty.default.prettyFactory({
354
+ colorize: true
355
+ });
356
+ constructor(level, meta2 = {}) {
357
+ this.pinoLogger = (0, import_pino.default)({
358
+ level: level || "info",
359
+ formatters: {
360
+ level(label) {
361
+ return { level: label };
362
+ }
363
+ },
364
+ timestamp: import_pino.default.stdTimeFunctions.isoTime,
365
+ transport: {
366
+ target: "pino-pretty",
367
+ options: { colorize: true }
368
+ }
369
+ });
370
+ this.meta = meta2;
371
+ }
372
+ log(level, ...args) {
373
+ let meta2 = {};
374
+ const filteredArgs = args.filter((arg) => {
375
+ if (isLoggerMeta(arg)) {
376
+ Object.assign(meta2, arg);
377
+ return false;
378
+ }
379
+ return true;
380
+ });
381
+ const activeSpan = import_api2.trace.getActiveSpan();
382
+ if (activeSpan) {
383
+ const activeSpanContext = activeSpan.spanContext();
384
+ meta2.trace_id = activeSpanContext.traceId;
385
+ meta2.span_id = activeSpanContext.spanId;
386
+ meta2.trace_flags = activeSpanContext.traceFlags;
387
+ meta2 = {
388
+ // @ts-expect-error accessing private property
389
+ ...activeSpan.attributes,
390
+ ...meta2
391
+ };
392
+ }
393
+ meta2 = {
394
+ "api.name": "none",
395
+ "correlation.id": "none",
396
+ ...meta2
397
+ };
398
+ this.pinoLogger[level](...filteredArgs);
399
+ import_api_logs.logs.getLogger(process.env.OTEL_SERVICE_NAME ?? "unknown").emit({
400
+ severityText: level,
401
+ severityNumber: mapSeverity(level),
402
+ body: this.prettyPrinter(filteredArgs),
403
+ attributes: { ...this.meta, ...meta2 }
404
+ });
405
+ }
406
+ error = (msg, ...args) => this.log("error", msg, ...args);
407
+ info = (msg, ...args) => this.log("info", msg, ...args);
408
+ debug = (msg, ...args) => this.log("debug", msg, ...args);
409
+ warn = (msg, ...args) => this.log("warn", msg, ...args);
410
+ trace = (msg, ...args) => this.log("trace", msg, ...args);
411
+ child(meta2 = {}) {
412
+ return new _PinoLogger(this.pinoLogger.level, { ...this.meta, ...meta2 });
413
+ }
414
+ getBaseLogger() {
415
+ return this.pinoLogger;
416
+ }
417
+ };
418
+ function logger(level, meta2 = {}) {
419
+ return new PinoLogger(level, meta2);
420
+ }
421
+
422
+ // src/http/telemetry/openTelemetryCollector.ts
423
+ var OpenTelemetryCollector = class {
424
+ // scoped creation and create this in middleware when api execute. Also add correlation id
425
+ constructor(serviceName, level, metricDefinitions) {
426
+ this.serviceName = serviceName;
427
+ this.logger = logger(level || "info");
428
+ this.metrics = {};
429
+ for (const [metricId, metricType] of Object.entries(
430
+ metricDefinitions ?? {}
431
+ )) {
432
+ switch (metricType) {
433
+ case "counter":
434
+ this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createCounter(metricId);
435
+ break;
436
+ case "gauge":
437
+ this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createGauge(metricId);
438
+ break;
439
+ case "histogram":
440
+ this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createHistogram(metricId);
441
+ break;
442
+ case "upDownCounter":
443
+ this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createUpDownCounter(metricId);
444
+ break;
445
+ case "observableCounter":
446
+ this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createObservableCounter(metricId);
447
+ break;
448
+ case "observableGauge":
449
+ this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createObservableGauge(metricId);
450
+ break;
451
+ case "observableUpDownCounter":
452
+ this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createObservableUpDownCounter(metricId);
453
+ break;
454
+ }
455
+ }
456
+ this.log("info", "OpenTelemetry (Traces + Logs + Metrics) started");
457
+ }
458
+ logger;
459
+ metrics;
460
+ log(level, ...args) {
461
+ this.logger.log(level, ...args);
462
+ }
463
+ info = (msg, ...args) => {
464
+ this.logger.log("info", msg, ...args);
465
+ };
466
+ error = (msg, ...args) => {
467
+ this.logger.log("error", msg, ...args);
468
+ };
469
+ warn = (msg, ...args) => {
470
+ this.logger.log("warn", msg, ...args);
471
+ };
472
+ debug = (msg, ...args) => {
473
+ this.logger.log("debug", msg, ...args);
474
+ };
475
+ trace = (msg, ...args) => {
476
+ this.logger.log("trace", msg, ...args);
477
+ };
478
+ getMetric(metricId) {
479
+ return this.metrics[metricId];
480
+ }
481
+ };
482
+ import_dotenv.default.config({ path: getEnvVar("ENV_FILE_PATH") });
483
+ new import_sdk_node.NodeSDK({
484
+ resource: new import_resources.Resource({
485
+ [import_semantic_conventions2.ATTR_SERVICE_NAME]: getEnvVar("OTEL_SERVICE_NAME")
486
+ }),
487
+ traceExporter: new import_exporter_trace_otlp_http.OTLPTraceExporter({
488
+ url: `${getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/traces`
489
+ }),
490
+ metricReader: new import_sdk_metrics.PeriodicExportingMetricReader({
491
+ exporter: new import_exporter_metrics_otlp_http.OTLPMetricExporter({
492
+ url: `${getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/metrics`
493
+ }),
494
+ exportIntervalMillis: 5e3
495
+ }),
496
+ logRecordProcessors: [
497
+ new import_sdk_logs.BatchLogRecordProcessor(
498
+ new import_exporter_logs_otlp_http.OTLPLogExporter({
499
+ url: `${getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/logs`
500
+ })
501
+ )
502
+ ],
503
+ instrumentations: [
504
+ new import_instrumentation_http.HttpInstrumentation({
505
+ applyCustomAttributesOnSpan: (span, request) => {
506
+ span.setAttribute(
507
+ "service.name",
508
+ getEnvVar("OTEL_SERVICE_NAME") ?? "unknown"
509
+ );
510
+ if (isForklaunchRequest(request)) {
511
+ span.setAttribute("api.name", request.contractDetails?.name);
512
+ }
513
+ }
514
+ }),
515
+ new import_instrumentation_express.ExpressInstrumentation(),
516
+ new import_opentelemetry_instrumentation_hyper_express.HyperExpressInstrumentation()
517
+ ]
518
+ }).start();
519
+ var httpRequestsTotalCounter = import_api3.metrics.getMeter(getEnvVar("OTEL_SERVICE_NAME") || "unknown").createCounter("http_requests_total", {
520
+ description: "Number of HTTP requests"
521
+ });
522
+ var httpServerDurationHistogram = import_api3.metrics.getMeter(getEnvVar("OTEL_SERVICE_NAME") || "unknown").createHistogram("http_server_duration", {
523
+ description: "Duration of HTTP server requests",
524
+ unit: "s"
525
+ });
526
+
285
527
  // src/http/middleware/request/enrichDetails.middleware.ts
286
- function enrichDetails(path, contractDetails, requestSchema, responseSchemas) {
528
+ function enrichDetails(path, contractDetails, requestSchema, responseSchemas, openTelemetryCollector) {
287
529
  return (req, res, next) => {
288
530
  req.originalPath = path;
289
531
  req.contractDetails = contractDetails;
290
532
  req.requestSchema = requestSchema;
291
533
  res.responseSchemas = responseSchemas;
534
+ req.openTelemetryCollector = openTelemetryCollector;
292
535
  req.context.span?.setAttribute(ATTR_API_NAME, req.contractDetails?.name);
536
+ const startTime = process.hrtime();
537
+ res.on("finish", () => {
538
+ const [seconds, nanoseconds] = process.hrtime(startTime);
539
+ const durationMs = seconds + nanoseconds / 1e9;
540
+ httpServerDurationHistogram.record(durationMs, {
541
+ [import_semantic_conventions.ATTR_SERVICE_NAME]: getEnvVar("OTEL_SERVICE_NAME") || "unknown",
542
+ [ATTR_API_NAME]: req.contractDetails?.name || "unknown",
543
+ [import_semantic_conventions.ATTR_HTTP_REQUEST_METHOD]: req.method,
544
+ [import_semantic_conventions.ATTR_HTTP_ROUTE]: req.originalPath || "unknown",
545
+ [import_semantic_conventions.ATTR_HTTP_RESPONSE_STATUS_CODE]: res.statusCode
546
+ });
547
+ });
293
548
  next?.();
294
549
  };
295
550
  }
@@ -329,7 +584,9 @@ function parse(req, _res, next) {
329
584
  );
330
585
  break;
331
586
  case "warning":
332
- console.warn((0, import_validator.prettyPrintParseErrors)(parsedRequest.errors, "Request"));
587
+ req.openTelemetryCollector.warn(
588
+ (0, import_validator.prettyPrintParseErrors)(parsedRequest.errors, "Request")
589
+ );
333
590
  break;
334
591
  case "none":
335
592
  break;
@@ -340,9 +597,10 @@ function parse(req, _res, next) {
340
597
 
341
598
  // src/http/router/expressLikeRouter.ts
342
599
  var ForklaunchExpressLikeRouter = class {
343
- constructor(basePath, schemaValidator, internal) {
600
+ constructor(basePath, schemaValidator, internal, openTelemetryCollector) {
344
601
  this.schemaValidator = schemaValidator;
345
602
  this.internal = internal;
603
+ this.openTelemetryCollector = openTelemetryCollector;
346
604
  this.basePath = basePath;
347
605
  }
348
606
  requestHandler;
@@ -361,7 +619,8 @@ var ForklaunchExpressLikeRouter = class {
361
619
  `${this.basePath}${path}`,
362
620
  contractDetails,
363
621
  requestSchema,
364
- responseSchemas
622
+ responseSchemas,
623
+ this.openTelemetryCollector
365
624
  ),
366
625
  parse,
367
626
  parseRequestAuth
@@ -922,20 +1181,16 @@ var ForklaunchExpressLikeApplication = class extends ForklaunchExpressLikeRouter
922
1181
  *
923
1182
  * @param {SV} schemaValidator - The schema validator.
924
1183
  */
925
- constructor(schemaValidator, internal) {
926
- super("/", schemaValidator, internal);
1184
+ constructor(schemaValidator, internal, openTelemetryCollector) {
1185
+ super("/", schemaValidator, internal, openTelemetryCollector);
927
1186
  this.schemaValidator = schemaValidator;
928
1187
  this.internal = internal;
1188
+ this.openTelemetryCollector = openTelemetryCollector;
929
1189
  this.internal.use(createContext(this.schemaValidator));
930
1190
  this.internal.use(cors);
931
1191
  }
932
1192
  };
933
1193
 
934
- // src/http/guards/isForklaunchRequest.ts
935
- function isForklaunchRequest(request) {
936
- return request != null && typeof request === "object" && "contractDetails" in request;
937
- }
938
-
939
1194
  // src/http/guards/isPath.ts
940
1195
  function isPath(path) {
941
1196
  return path.startsWith("/");
@@ -1009,7 +1264,7 @@ var put = (_schemaValidator, path, contractDetails, ...handlers) => {
1009
1264
  };
1010
1265
 
1011
1266
  // src/http/handlers/trace.ts
1012
- var trace2 = (_schemaValidator, path, contractDetails, ...handlers) => {
1267
+ var trace3 = (_schemaValidator, path, contractDetails, ...handlers) => {
1013
1268
  return typedHandler(_schemaValidator, path, "trace", contractDetails, ...handlers);
1014
1269
  };
1015
1270
 
@@ -2032,8 +2287,10 @@ function parse2(req, res, next) {
2032
2287
  ${parseErrors.join("\n\n")}`));
2033
2288
  break;
2034
2289
  case "warning":
2035
- console.warn(`Invalid response:
2036
- ${parseErrors.join("\n\n")}`);
2290
+ req.openTelemetryCollector.warn(
2291
+ `Invalid response:
2292
+ ${parseErrors.join("\n\n")}`
2293
+ );
2037
2294
  break;
2038
2295
  case "none":
2039
2296
  break;
@@ -2042,96 +2299,6 @@ ${parseErrors.join("\n\n")}`);
2042
2299
  next?.();
2043
2300
  }
2044
2301
 
2045
- // src/http/telemetry/pinoLogger.ts
2046
- var import_common2 = require("@forklaunch/common");
2047
- var import_api2 = require("@opentelemetry/api");
2048
- var import_api_logs = require("@opentelemetry/api-logs");
2049
- var import_pino = __toESM(require("pino"));
2050
- function mapSeverity(level) {
2051
- switch (level) {
2052
- case "silent":
2053
- return 0;
2054
- case "trace":
2055
- return 1;
2056
- case "debug":
2057
- return 5;
2058
- case "info":
2059
- return 9;
2060
- case "warn":
2061
- return 13;
2062
- case "error":
2063
- return 17;
2064
- case "fatal":
2065
- return 21;
2066
- default:
2067
- (0, import_common2.isNever)(level);
2068
- return 0;
2069
- }
2070
- }
2071
- var PinoLogger = class _PinoLogger {
2072
- pinoLogger;
2073
- meta;
2074
- constructor(level, meta = {}) {
2075
- this.pinoLogger = (0, import_pino.default)({
2076
- level: level || "info",
2077
- formatters: {
2078
- level(label) {
2079
- return { level: label };
2080
- }
2081
- },
2082
- timestamp: import_pino.default.stdTimeFunctions.isoTime,
2083
- transport: {
2084
- target: "pino-pretty",
2085
- options: { colorize: true }
2086
- }
2087
- });
2088
- this.meta = meta;
2089
- }
2090
- log(level, msg, meta = {}) {
2091
- const activeSpan = import_api2.trace.getActiveSpan();
2092
- if (activeSpan) {
2093
- const activeSpanContext = activeSpan.spanContext();
2094
- meta.trace_id = activeSpanContext.traceId;
2095
- meta.span_id = activeSpanContext.spanId;
2096
- meta.trace_flags = activeSpanContext.traceFlags;
2097
- if (!meta.api_name) {
2098
- meta = { ...meta, ...activeSpan?.attributes };
2099
- }
2100
- }
2101
- this.pinoLogger[level](msg);
2102
- import_api_logs.logs.getLogger(process.env.OTEL_SERVICE_NAME ?? "unknown").emit({
2103
- severityText: level,
2104
- severityNumber: mapSeverity(level),
2105
- body: msg,
2106
- attributes: { ...this.meta, ...meta }
2107
- });
2108
- }
2109
- error(msg, meta = {}) {
2110
- this.log("error", msg, meta);
2111
- }
2112
- info(msg, meta = {}) {
2113
- this.log("info", msg, meta);
2114
- }
2115
- debug(msg, meta = {}) {
2116
- this.log("debug", msg, meta);
2117
- }
2118
- warn(msg, meta = {}) {
2119
- this.log("warn", msg, meta);
2120
- }
2121
- trace(msg, meta = {}) {
2122
- this.log("trace", msg, meta);
2123
- }
2124
- child(meta = {}) {
2125
- return new _PinoLogger(this.pinoLogger.level, { ...this.meta, ...meta });
2126
- }
2127
- getBaseLogger() {
2128
- return this.pinoLogger;
2129
- }
2130
- };
2131
- function logger(level, meta = {}) {
2132
- return new PinoLogger(level, meta);
2133
- }
2134
-
2135
2302
  // src/http/telemetry/recordMetric.ts
2136
2303
  var import_semantic_conventions3 = require("@opentelemetry/semantic-conventions");
2137
2304
 
@@ -2139,126 +2306,6 @@ var import_semantic_conventions3 = require("@opentelemetry/semantic-conventions"
2139
2306
  var import_common3 = require("@forklaunch/common");
2140
2307
  var import_validator3 = require("@forklaunch/validator");
2141
2308
 
2142
- // src/services/getEnvVar.ts
2143
- function getEnvVar(name) {
2144
- const value = process.env[name];
2145
- return value;
2146
- }
2147
-
2148
- // src/http/telemetry/openTelemetryCollector.ts
2149
- var import_opentelemetry_instrumentation_hyper_express = require("@forklaunch/opentelemetry-instrumentation-hyper-express");
2150
- var import_api3 = require("@opentelemetry/api");
2151
- var import_exporter_logs_otlp_http = require("@opentelemetry/exporter-logs-otlp-http");
2152
- var import_exporter_metrics_otlp_http = require("@opentelemetry/exporter-metrics-otlp-http");
2153
- var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
2154
- var import_instrumentation_express = require("@opentelemetry/instrumentation-express");
2155
- var import_instrumentation_http = require("@opentelemetry/instrumentation-http");
2156
- var import_resources = require("@opentelemetry/resources");
2157
- var import_sdk_logs = require("@opentelemetry/sdk-logs");
2158
- var import_sdk_metrics = require("@opentelemetry/sdk-metrics");
2159
- var import_sdk_node = require("@opentelemetry/sdk-node");
2160
- var import_semantic_conventions2 = require("@opentelemetry/semantic-conventions");
2161
- var import_dotenv = __toESM(require("dotenv"));
2162
- var OpenTelemetryCollector = class {
2163
- // scoped creation and create this in middleware when api execute. Also add correlation id
2164
- constructor(serviceName, level, metricDefinitions) {
2165
- this.serviceName = serviceName;
2166
- this.logger = logger(level ?? "info");
2167
- this.metrics = {};
2168
- for (const [metricId, metricType] of Object.entries(
2169
- metricDefinitions ?? {}
2170
- )) {
2171
- switch (metricType) {
2172
- case "counter":
2173
- this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createCounter(metricId);
2174
- break;
2175
- case "gauge":
2176
- this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createGauge(metricId);
2177
- break;
2178
- case "histogram":
2179
- this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createHistogram(metricId);
2180
- break;
2181
- case "upDownCounter":
2182
- this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createUpDownCounter(metricId);
2183
- break;
2184
- case "observableCounter":
2185
- this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createObservableCounter(metricId);
2186
- break;
2187
- case "observableGauge":
2188
- this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createObservableGauge(metricId);
2189
- break;
2190
- case "observableUpDownCounter":
2191
- this.metrics[metricId] = import_api3.metrics.getMeter(this.serviceName).createObservableUpDownCounter(metricId);
2192
- break;
2193
- }
2194
- }
2195
- this.log("info", "OpenTelemetry (Traces + Logs + Metrics) started");
2196
- }
2197
- logger;
2198
- metrics;
2199
- log(level, msg, meta = {}) {
2200
- this.logger.log(level, msg, meta);
2201
- }
2202
- info(msg, meta = {}) {
2203
- this.logger.info(msg, meta);
2204
- }
2205
- error(msg, meta = {}) {
2206
- this.logger.error(msg, meta);
2207
- }
2208
- warn(msg, meta = {}) {
2209
- this.logger.warn(msg, meta);
2210
- }
2211
- debug(msg, meta = {}) {
2212
- this.logger.debug(msg, meta);
2213
- }
2214
- trace(msg, meta = {}) {
2215
- this.logger.trace(msg, meta);
2216
- }
2217
- getMetric(metricId) {
2218
- return this.metrics[metricId];
2219
- }
2220
- };
2221
- import_dotenv.default.config({ path: getEnvVar("ENV_FILE_PATH") });
2222
- new import_sdk_node.NodeSDK({
2223
- resource: new import_resources.Resource({
2224
- [import_semantic_conventions2.ATTR_SERVICE_NAME]: getEnvVar("OTEL_SERVICE_NAME")
2225
- }),
2226
- traceExporter: new import_exporter_trace_otlp_http.OTLPTraceExporter({
2227
- url: `${getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/traces`
2228
- }),
2229
- metricReader: new import_sdk_metrics.PeriodicExportingMetricReader({
2230
- exporter: new import_exporter_metrics_otlp_http.OTLPMetricExporter({
2231
- url: `${getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/metrics`
2232
- }),
2233
- exportIntervalMillis: 5e3
2234
- }),
2235
- logRecordProcessors: [
2236
- new import_sdk_logs.BatchLogRecordProcessor(
2237
- new import_exporter_logs_otlp_http.OTLPLogExporter({
2238
- url: `${getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/logs`
2239
- })
2240
- )
2241
- ],
2242
- instrumentations: [
2243
- new import_instrumentation_http.HttpInstrumentation({
2244
- applyCustomAttributesOnSpan: (span, request) => {
2245
- span.setAttribute(
2246
- "service.name",
2247
- getEnvVar("OTEL_SERVICE_NAME") ?? "unknown"
2248
- );
2249
- if (isForklaunchRequest(request)) {
2250
- span.setAttribute("api.name", request.contractDetails?.name);
2251
- }
2252
- }
2253
- }),
2254
- new import_instrumentation_express.ExpressInstrumentation(),
2255
- new import_opentelemetry_instrumentation_hyper_express.HyperExpressInstrumentation()
2256
- ]
2257
- }).start();
2258
- var httpRequestsTotalCounter = import_api3.metrics.getMeter(getEnvVar("OTEL_SERVICE_NAME") || "unknown").createCounter("http_requests_total", {
2259
- description: "Number of HTTP requests"
2260
- });
2261
-
2262
2309
  // src/http/telemetry/recordMetric.ts
2263
2310
  function recordMetric(req, res) {
2264
2311
  httpRequestsTotalCounter.add(1, {
@@ -2277,6 +2324,7 @@ function enrichExpressLikeSend(instance, req, res, originalSend, data, shouldEnr
2277
2324
  if (shouldEnrich) {
2278
2325
  recordMetric(req, res);
2279
2326
  if (res.statusCode === 404) {
2327
+ res.type("text/plain");
2280
2328
  res.status(404);
2281
2329
  logger("error").error("Not Found");
2282
2330
  originalSend.call(instance, "Not Found");
@@ -2290,6 +2338,7 @@ function enrichExpressLikeSend(instance, req, res, originalSend, data, shouldEnr
2290
2338
  ${res.locals.errorMessage}`;
2291
2339
  }
2292
2340
  logger("error").error(errorString);
2341
+ res.type("text/plain");
2293
2342
  res.status(500);
2294
2343
  originalSend.call(instance, errorString);
2295
2344
  parseErrorSent = true;
@@ -2467,6 +2516,7 @@ function metricsDefinitions(metrics2) {
2467
2516
  getCodeForStatus,
2468
2517
  head,
2469
2518
  httpRequestsTotalCounter,
2519
+ httpServerDurationHistogram,
2470
2520
  isClientError,
2471
2521
  isForklaunchRequest,
2472
2522
  isForklaunchRouter,
@@ -2476,6 +2526,7 @@ function metricsDefinitions(metrics2) {
2476
2526
  isSuccessful,
2477
2527
  isValidStatusCode,
2478
2528
  logger,
2529
+ meta,
2479
2530
  metricsDefinitions,
2480
2531
  middleware,
2481
2532
  options,