diff --git a/frontend/Dockerfile b/frontend/Dockerfile
index 9957c0e9..9bc69038 100644
--- a/frontend/Dockerfile
+++ b/frontend/Dockerfile
@@ -75,7 +75,6 @@ COPY --chown=node:node --from=builder /home/node/public ./public
COPY --chown=node:node --from=builder /home/node/.next ./.next
COPY --chown=node:node --from=builder /home/node/next.config.js ./next.config.js
COPY --chown=node:node --from=builder /home/node/next-i18next.config.js ./next-i18next.config.js
-COPY --chown=node:node --from=builder /home/node/open-telemetry.config.js ./open-telemetry.config.js
COPY --chown=node:node --from=builder /home/node/package*.json ./
USER node
diff --git a/frontend/next.config.js b/frontend/next.config.js
index 13458b5e..664ca1b9 100644
--- a/frontend/next.config.js
+++ b/frontend/next.config.js
@@ -1,7 +1,5 @@
// @ts-check
-require('./open-telemetry.config')
-
const { i18n } = require('./next-i18next.config')
const { statSync } = require('fs')
@@ -26,6 +24,9 @@ const nextConfig = {
NEXT_PUBLIC_BUILD_VERSION: process.env.BUILD_VERSION ?? '00000000-0000-00000000',
LOGGING_LEVEL: process.env.LOGGING_LEVEL ?? 'info',
},
+ experimental: {
+ instrumentationHook: true
+ },
generateBuildId: async () => (process.env.BUILD_ID ?? '0000'),
headers: async () => ([{ source: '/:path*', headers: securityHeaders }]),
i18n: { ...i18n, localeDetection: false },
diff --git a/frontend/open-telemetry.config.js b/frontend/src/instrumentation.node.ts
similarity index 67%
rename from frontend/open-telemetry.config.js
rename to frontend/src/instrumentation.node.ts
index e4cbe143..41ebd980 100644
--- a/frontend/open-telemetry.config.js
+++ b/frontend/src/instrumentation.node.ts
@@ -32,18 +32,18 @@
*
https://nextjs.org/docs/api-reference/edge-runtime
*
*/
+import { ExportResultCode } from '@opentelemetry/core'
+import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-proto'
+import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'
+import { CompressionAlgorithm } from '@opentelemetry/otlp-exporter-base'
+import { Resource, envDetector, hostDetector, osDetector, processDetector } from '@opentelemetry/resources'
+import { AggregationTemporality, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'
+import { NodeSDK } from '@opentelemetry/sdk-node'
+import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
-const log = require('next/dist/build/output/log')
+import { getLogger } from './logging/log-util'
-const { ExportResultCode } = require('@opentelemetry/core')
-const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-proto')
-const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-proto')
-const { CompressionAlgorithm } = require('@opentelemetry/otlp-exporter-base')
-const { envDetector, hostDetector, osDetector, processDetector, Resource } = require('@opentelemetry/resources')
-const { AggregationTemporality, MeterProvider, PeriodicExportingMetricReader, PushMetricExporter } = require('@opentelemetry/sdk-metrics')
-const { SpanExporter } = require('@opentelemetry/sdk-trace-base')
-const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions')
-const { NodeSDK } = require('@opentelemetry/sdk-node')
+const logger = getLogger('instrumentation.node')
/** @returns {PushMetricExporter} */
function getMetricExporter() {
@@ -54,23 +54,24 @@ function getMetricExporter() {
throw new Error('OTEL_API_KEY must be configured when OTEL_METRICS_ENDPOINT is set')
}
- log.info(`Exporting metrics to ${process.env.OTEL_METRICS_ENDPOINT} every ${getMetricExportInterval()} ms`)
+ logger.info(`Exporting metrics to ${process.env.OTEL_METRICS_ENDPOINT} every ${getMetricExportInterval()} ms`)
return new OTLPMetricExporter({
compression: CompressionAlgorithm.GZIP,
- headers: { 'Authorization': `Api-Token ${process.env.OTEL_API_KEY}` },
+ headers: { Authorization: `Api-Token ${process.env.OTEL_API_KEY}` },
temporalityPreference: AggregationTemporality.DELTA,
- url: process.env.OTEL_METRICS_ENDPOINT
+ url: process.env.OTEL_METRICS_ENDPOINT,
})
}
- log.info('Metrics exporting is disabled; set OTEL_METRICS_ENDPOINT to enable.')
+ logger.info('Metrics exporting is disabled; set OTEL_METRICS_ENDPOINT to enable.')
return {
// a no-op PushMetricExporter implementation
- export: (metrics, resultCallback) => resultCallback({ code: ExportResultCode.SUCCESS }),
+ export: (_: any, resultCallback: (arg0: { code: ExportResultCode }) => any) =>
+ resultCallback({ code: ExportResultCode.SUCCESS }),
forceFlush: async () => {},
- shutdown: async () => {}
+ shutdown: async () => {},
}
}
@@ -93,31 +94,32 @@ function getTraceExporter() {
throw new Error('OTEL_API_KEY must be configured when OTEL_TRACES_ENDPOINT is set')
}
- log.info(`Exporting traces to ${process.env.OTEL_TRACES_ENDPOINT} every 30000 ms`)
+ logger.info(`Exporting traces to ${process.env.OTEL_TRACES_ENDPOINT} every 30000 ms`)
return new OTLPTraceExporter({
compression: CompressionAlgorithm.GZIP,
- headers: { 'Authorization': `Api-Token ${process.env.OTEL_API_KEY}` },
+ headers: { Authorization: `Api-Token ${process.env.OTEL_API_KEY}` },
url: process.env.OTEL_TRACES_ENDPOINT,
})
}
- log.info('Traces exporting is disabled; set OTEL_TRACES_ENDPOINT to enable.')
+ logger.info('Traces exporting is disabled; set OTEL_TRACES_ENDPOINT to enable.')
return {
// a no-op SpanExporter implementation
- export: (spans, resultCallback) => resultCallback({ code: ExportResultCode.SUCCESS }),
- shutdown: async () => {}
+ export: (_: any, resultCallback: (arg0: { code: ExportResultCode }) => any) =>
+ resultCallback({ code: ExportResultCode.SUCCESS }),
+ shutdown: async () => {},
}
}
-log.info(`Initializing OpenTelemetry SDK...`)
+logger.info(`Initializing OpenTelemetry SDK...`)
new NodeSDK({
metricReader: new PeriodicExportingMetricReader({
exporter: getMetricExporter(),
exportIntervalMillis: getMetricExportInterval(),
- exportTimeoutMillis: getMetricTimeout()
+ exportTimeoutMillis: getMetricTimeout(),
}),
resource: new Resource({
// Note: any attributes added here must be configured in Dynatrace under
@@ -127,7 +129,7 @@ new NodeSDK({
// see: node_modules/@opentelemetry/semantic-conventions/build/src/trace/SemanticResourceAttributes.js
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: process.env.OTEL_ENVIRONMENT ?? 'local',
[SemanticResourceAttributes.SERVICE_NAME]: process.env.OTEL_SERVICE_NAME ?? 'seniors-journey',
- [SemanticResourceAttributes.SERVICE_VERSION]: process.env.BUILD_VERSION ?? '00000000-0000-00000000'
+ [SemanticResourceAttributes.SERVICE_VERSION]: process.env.BUILD_VERSION ?? '00000000-0000-00000000',
}),
resourceDetectors: [envDetector, hostDetector, osDetector, processDetector],
traceExporter: getTraceExporter(),
diff --git a/frontend/src/instrumentation.ts b/frontend/src/instrumentation.ts
new file mode 100644
index 00000000..d50abd7a
--- /dev/null
+++ b/frontend/src/instrumentation.ts
@@ -0,0 +1,5 @@
+export async function register() {
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
+ await import('./instrumentation.node')
+ }
+}