From ffc2fadc209e1fa3986c0a29ac0bef45c5bc7b75 Mon Sep 17 00:00:00 2001 From: evanpelle Date: Thu, 1 May 2025 11:22:56 -0700 Subject: [PATCH] use otel for observability (#635) ## Description: ## Please complete the following: - [ ] I have added screenshots for all UI updates - [ ] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced - [ ] I understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors ## Please put your Discord username so you can be contacted if a bug or regression is found: Co-authored-by: evan --- Dockerfile | 6 - deploy.sh | 5 +- metric-exporter.sh | 103 -- package-lock.json | 1583 ++++++++++++++++++++++- package.json | 15 +- setup.sh | 14 - src/core/configuration/Config.ts | 4 + src/core/configuration/DefaultConfig.ts | 14 + src/server/Logger.ts | 56 +- src/server/Master.ts | 14 +- src/server/MasterMetrics.ts | 242 +--- src/server/OtelResource.ts | 27 + src/server/Worker.ts | 28 +- src/server/WorkerMetrics.ts | 114 +- supervisord.conf | 17 +- tests/util/TestServerConfig.ts | 12 + update.sh | 35 - 17 files changed, 1859 insertions(+), 430 deletions(-) delete mode 100755 metric-exporter.sh create mode 100644 src/server/OtelResource.ts diff --git a/Dockerfile b/Dockerfile index b9c991dec..c63c4066d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,12 +13,6 @@ RUN apt-get update && apt-get install -y \ wget \ && rm -rf /var/lib/apt/lists/* -# Install Node Exporter -RUN mkdir -p /opt/node_exporter && \ - wget -qO- https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz | \ - tar xvz --strip-components=1 -C /opt/node_exporter && \ - ln -s /opt/node_exporter/node_exporter /usr/local/bin/ - # Install cloudflared RUN curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb > cloudflared.deb \ && dpkg -i cloudflared.deb \ diff --git a/deploy.sh b/deploy.sh index 6d52cc2b7..ccc077948 100755 --- a/deploy.sh +++ b/deploy.sh @@ -147,8 +147,9 @@ R2_BUCKET=$R2_BUCKET CF_API_TOKEN=$CF_API_TOKEN DOMAIN=$DOMAIN SUBDOMAIN=$SUBDOMAIN -MON_USERNAME=$MON_USERNAME -MON_PASSWORD=$MON_PASSWORD +OTEL_USERNAME=$OTEL_USERNAME +OTEL_PASSWORD=$OTEL_PASSWORD +OTEL_ENDPOINT=$OTEL_ENDPOINT EOL chmod 600 $REMOTE_UPDATE_PATH/.env && \ $REMOTE_UPDATE_SCRIPT" diff --git a/metric-exporter.sh b/metric-exporter.sh deleted file mode 100755 index 4943c7999..000000000 --- a/metric-exporter.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/bash - -# Metric Collector for Prometheus Pushgateway -# This script collects metrics from Node Exporter and application sources -# and pushes them to a Prometheus Pushgateway with custom labels. - -# Configuration -NODE_EXPORTER_URL="http://localhost:9100/metrics" -APP_METRICS_URL="http://localhost:9090/metrics" -PUSHGATEWAY_BASE_URL="https://mon.openfront.io/pushgateway/metrics" -AUTH=$MON_USERNAME:$MON_PASSWORD -INTERVAL=15 # seconds - -# Function to fetch metrics from Node Exporter -fetch_node_exporter_metrics() { - curl -s --connect-timeout 5 --max-time 10 "$NODE_EXPORTER_URL" || - echo "# Error fetching Node Exporter metrics" -} - -# Function to fetch metrics from your application -fetch_app_metrics() { - curl -s --connect-timeout 5 --max-time 10 "$APP_METRICS_URL" || - echo "# Error fetching application metrics" -} - -# Function to push metrics to Pushgateway -push_metrics() { - local metrics=$1 - local job_name=$2 - - echo "Pushing $job_name metrics to Pushgateway..." - - # Create a temporary file for the metrics - TEMP_FILE=$(mktemp) - echo "$metrics" > "$TEMP_FILE" - - # Push to Pushgateway with instance label - curl -s -u "$AUTH" --data-binary @"$TEMP_FILE" \ - "$PUSHGATEWAY_BASE_URL/job/$job_name/instance/$HOSTNAME" - - # Check if push was successful - if [ $? -eq 0 ]; then - echo "$job_name metrics pushed successfully" - else - echo "Error pushing $job_name metrics" - fi - - # Remove temporary file - rm "$TEMP_FILE" -} - -# Function to add labels to metrics -add_labels() { - local metrics=$1 - - # First, handle metrics with existing labels - metrics=$(echo "$metrics" | sed -E 's/(\{[^}]*)\}/\1,env="'$ENV'",host="'$HOST'",subdomain="'$SUBDOMAIN'"}/g') - - # Then, handle metrics with no existing labels - metrics=$(echo "$metrics" | sed -E 's/^([a-zA-Z0-9_:]+)[ \t]+([0-9.e+-]+)$/\1{env="'$ENV'",host="'$HOST'",subdomain="'$SUBDOMAIN'"} \2/g') - - echo "$metrics" -} - -# Main function to collect and push metrics -collect_and_push_metrics() { - echo "Starting metrics collection cycle at $(date)" - - # Get metrics from both sources - NODE_METRICS=$(fetch_node_exporter_metrics) - APP_METRICS=$(fetch_app_metrics) - - # Clean up metrics (remove headers etc.) - NODE_METRICS=$(echo "$NODE_METRICS" | grep -v "^Fetching") - APP_METRICS=$(echo "$APP_METRICS" | grep -v "^Fetching") - - # Add labels to metrics - NODE_METRICS=$(add_labels "$NODE_METRICS") - APP_METRICS=$(add_labels "$APP_METRICS") - - # Push to Pushgateway separately - push_metrics "$NODE_METRICS" "node_exporter" - push_metrics "$APP_METRICS" "app_metrics" - - echo "Metrics collection cycle completed at $(date)" -} - -# Main execution -echo "===== Starting metrics collector =====" -echo "Environment: $ENV, HOST: $HOST, Subdomain: $SUBDOMAIN" -echo "Collecting and pushing metrics every $INTERVAL seconds" -echo "Node Exporter URL: $NODE_EXPORTER_URL" -echo "App Metrics URL: $APP_METRICS_URL" -echo "Pushgateway URL: $PUSHGATEWAY_BASE_URL" - -# Wait for app to be ready. -sleep 30 - -# Then set up interval loop -while true; do - sleep $INTERVAL - collect_and_push_metrics -done \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0fadc421a..3a1621df7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,18 @@ "@aws-sdk/client-s3": "^3.758.0", "@datastructures-js/priority-queue": "^6.3.1", "@google-cloud/secret-manager": "^5.6.0", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/api-logs": "^0.200.0", + "@opentelemetry/auto-instrumentations-node": "^0.58.0", + "@opentelemetry/exporter-metrics-otlp-http": "^0.200.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.200.0", + "@opentelemetry/host-metrics": "^0.36.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/sdk-logs": "^0.200.0", + "@opentelemetry/sdk-metrics": "^2.0.0", + "@opentelemetry/sdk-node": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.32.0", + "@opentelemetry/winston-transport": "^0.11.0", "@types/dompurify": "^3.0.5", "@types/express": "^4.17.21", "@types/google-protobuf": "^3.15.12", @@ -25,7 +37,7 @@ "d3": "^7.9.0", "discord.js": "^14.16.3", "dompurify": "^3.1.7", - "dotenv": "^16.4.7", + "dotenv": "^16.5.0", "express": "^4.21.1", "express-rate-limit": "^7.5.0", "google-auth-library": "^9.14.0", @@ -58,6 +70,7 @@ "webpack-dev-server": "^5.0.4", "wheelnav": "^1.7.1", "winston": "^3.17.0", + "winston-transport": "^4.9.0", "ws": "^8.18.0", "zod": "^3.23.8" }, @@ -5287,6 +5300,1458 @@ "node": ">=8.0.0" } }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.200.0.tgz", + "integrity": "sha512-IKJBQxh91qJ+3ssRly5hYEJ8NDHu9oY/B1PXVSCWf7zytmYO9RNLB0Ox9XQ/fJ8m6gY6Q6NtBWlmXfaXt5Uc4Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node": { + "version": "0.58.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.58.0.tgz", + "integrity": "sha512-gtqPqkXp8TG6vrmbzAJUKjJm3nrCiVGgImlV1tj8lsVqpnKDCB1Kl7bCcXod36+Tq/O4rCeTDmW90dCHeuv9jQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/instrumentation-amqplib": "^0.47.0", + "@opentelemetry/instrumentation-aws-lambda": "^0.51.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.51.0", + "@opentelemetry/instrumentation-bunyan": "^0.46.0", + "@opentelemetry/instrumentation-cassandra-driver": "^0.46.0", + "@opentelemetry/instrumentation-connect": "^0.44.0", + "@opentelemetry/instrumentation-cucumber": "^0.15.0", + "@opentelemetry/instrumentation-dataloader": "^0.17.0", + "@opentelemetry/instrumentation-dns": "^0.44.0", + "@opentelemetry/instrumentation-express": "^0.48.1", + "@opentelemetry/instrumentation-fastify": "^0.45.0", + "@opentelemetry/instrumentation-fs": "^0.20.0", + "@opentelemetry/instrumentation-generic-pool": "^0.44.0", + "@opentelemetry/instrumentation-graphql": "^0.48.0", + "@opentelemetry/instrumentation-grpc": "^0.200.0", + "@opentelemetry/instrumentation-hapi": "^0.46.0", + "@opentelemetry/instrumentation-http": "^0.200.0", + "@opentelemetry/instrumentation-ioredis": "^0.48.0", + "@opentelemetry/instrumentation-kafkajs": "^0.9.1", + "@opentelemetry/instrumentation-knex": "^0.45.0", + "@opentelemetry/instrumentation-koa": "^0.48.0", + "@opentelemetry/instrumentation-lru-memoizer": "^0.45.0", + "@opentelemetry/instrumentation-memcached": "^0.44.0", + "@opentelemetry/instrumentation-mongodb": "^0.53.0", + "@opentelemetry/instrumentation-mongoose": "^0.47.0", + "@opentelemetry/instrumentation-mysql": "^0.46.0", + "@opentelemetry/instrumentation-mysql2": "^0.46.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.46.0", + "@opentelemetry/instrumentation-net": "^0.44.0", + "@opentelemetry/instrumentation-pg": "^0.52.0", + "@opentelemetry/instrumentation-pino": "^0.47.0", + "@opentelemetry/instrumentation-redis": "^0.47.0", + "@opentelemetry/instrumentation-redis-4": "^0.47.0", + "@opentelemetry/instrumentation-restify": "^0.46.0", + "@opentelemetry/instrumentation-router": "^0.45.0", + "@opentelemetry/instrumentation-runtime-node": "^0.14.0", + "@opentelemetry/instrumentation-socket.io": "^0.47.0", + "@opentelemetry/instrumentation-tedious": "^0.19.0", + "@opentelemetry/instrumentation-undici": "^0.11.0", + "@opentelemetry/instrumentation-winston": "^0.45.0", + "@opentelemetry/resource-detector-alibaba-cloud": "^0.31.0", + "@opentelemetry/resource-detector-aws": "^2.0.0", + "@opentelemetry/resource-detector-azure": "^0.7.0", + "@opentelemetry/resource-detector-container": "^0.7.0", + "@opentelemetry/resource-detector-gcp": "^0.34.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/sdk-node": "^0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.4.1", + "@opentelemetry/core": "^2.0.0" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.0.0.tgz", + "integrity": "sha512-IEkJGzK1A9v3/EHjXh3s2IiFc6L4jfK+lNgKVgUjeUJQRRhnVFMIO3TAvKwonm9O1HebCuoOt98v8bZW7oVQHA==", + "license": "Apache-2.0", + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.0.tgz", + "integrity": "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.200.0.tgz", + "integrity": "sha512-+3MDfa5YQPGM3WXxW9kqGD85Q7s9wlEMVNhXXG7tYFLnIeaseUt9YtCeFhEDFzfEktacdFpOtXmJuNW8cHbU5A==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.0.0", + "@opentelemetry/otlp-exporter-base": "0.200.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.200.0", + "@opentelemetry/otlp-transformer": "0.200.0", + "@opentelemetry/sdk-logs": "0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-http": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.200.0.tgz", + "integrity": "sha512-KfWw49htbGGp9s8N4KI8EQ9XuqKJ0VG+yVYVYFiCYSjEV32qpQ5qZ9UZBzOZ6xRb+E16SXOSCT3RkqBVSABZ+g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.200.0", + "@opentelemetry/core": "2.0.0", + "@opentelemetry/otlp-exporter-base": "0.200.0", + "@opentelemetry/otlp-transformer": "0.200.0", + "@opentelemetry/sdk-logs": "0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-proto": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.200.0.tgz", + "integrity": "sha512-GmahpUU/55hxfH4TP77ChOfftADsCq/nuri73I/AVLe2s4NIglvTsaACkFVZAVmnXXyPS00Fk3x27WS3yO07zA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.200.0", + "@opentelemetry/core": "2.0.0", + "@opentelemetry/otlp-exporter-base": "0.200.0", + "@opentelemetry/otlp-transformer": "0.200.0", + "@opentelemetry/resources": "2.0.0", + "@opentelemetry/sdk-logs": "0.200.0", + "@opentelemetry/sdk-trace-base": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-grpc": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.200.0.tgz", + "integrity": "sha512-uHawPRvKIrhqH09GloTuYeq2BjyieYHIpiklOvxm9zhrCL2eRsnI/6g9v2BZTVtGp8tEgIa7rCQ6Ltxw6NBgew==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.0.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.200.0", + "@opentelemetry/otlp-exporter-base": "0.200.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.200.0", + "@opentelemetry/otlp-transformer": "0.200.0", + "@opentelemetry/resources": "2.0.0", + "@opentelemetry/sdk-metrics": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-http": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.200.0.tgz", + "integrity": "sha512-5BiR6i8yHc9+qW7F6LqkuUnIzVNA7lt0qRxIKcKT+gq3eGUPHZ3DY29sfxI3tkvnwMgtnHDMNze5DdxW39HsAw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0", + "@opentelemetry/otlp-exporter-base": "0.200.0", + "@opentelemetry/otlp-transformer": "0.200.0", + "@opentelemetry/resources": "2.0.0", + "@opentelemetry/sdk-metrics": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-proto": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.200.0.tgz", + "integrity": "sha512-E+uPj0yyvz81U9pvLZp3oHtFrEzNSqKGVkIViTQY1rH3TOobeJPSpLnTVXACnCwkPR5XeTvPnK3pZ2Kni8AFMg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.200.0", + "@opentelemetry/otlp-exporter-base": "0.200.0", + "@opentelemetry/otlp-transformer": "0.200.0", + "@opentelemetry/resources": "2.0.0", + "@opentelemetry/sdk-metrics": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-prometheus": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.200.0.tgz", + "integrity": "sha512-ZYdlU9r0USuuYppiDyU2VFRA0kFl855ylnb3N/2aOlXrbA4PMCznen7gmPbetGQu7pz8Jbaf4fwvrDnVdQQXSw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0", + "@opentelemetry/resources": "2.0.0", + "@opentelemetry/sdk-metrics": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.200.0.tgz", + "integrity": "sha512-hmeZrUkFl1YMsgukSuHCFPYeF9df0hHoKeHUthRKFCxiURs+GwF1VuabuHmBMZnjTbsuvNjOB+JSs37Csem/5Q==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.0.0", + "@opentelemetry/otlp-exporter-base": "0.200.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.200.0", + "@opentelemetry/otlp-transformer": "0.200.0", + "@opentelemetry/resources": "2.0.0", + "@opentelemetry/sdk-trace-base": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-http": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.200.0.tgz", + "integrity": "sha512-Goi//m/7ZHeUedxTGVmEzH19NgqJY+Bzr6zXo1Rni1+hwqaksEyJ44gdlEMREu6dzX1DlAaH/qSykSVzdrdafA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0", + "@opentelemetry/otlp-exporter-base": "0.200.0", + "@opentelemetry/otlp-transformer": "0.200.0", + "@opentelemetry/resources": "2.0.0", + "@opentelemetry/sdk-trace-base": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-proto": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.200.0.tgz", + "integrity": "sha512-V9TDSD3PjK1OREw2iT9TUTzNYEVWJk4Nhodzhp9eiz4onDMYmPy3LaGbPv81yIR6dUb/hNp/SIhpiCHwFUq2Vg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0", + "@opentelemetry/otlp-exporter-base": "0.200.0", + "@opentelemetry/otlp-transformer": "0.200.0", + "@opentelemetry/resources": "2.0.0", + "@opentelemetry/sdk-trace-base": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-zipkin": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.0.0.tgz", + "integrity": "sha512-icxaKZ+jZL/NHXX8Aru4HGsrdhK0MLcuRXkX5G5IRmCgoRLw+Br6I/nMVozX2xjGGwV7hw2g+4Slj8K7s4HbVg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0", + "@opentelemetry/resources": "2.0.0", + "@opentelemetry/sdk-trace-base": "2.0.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/host-metrics": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/host-metrics/-/host-metrics-0.36.0.tgz", + "integrity": "sha512-14lNY57qa21V3ZOl6xrqLMHR0HGlnPIApR6hr3oCw/Dqs5IzxhTwt2X8Stn82vWJJis7j/ezn11oODsizHj2dQ==", + "license": "Apache-2.0", + "dependencies": { + "systeminformation": "5.23.8" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/host-metrics/node_modules/systeminformation": { + "version": "5.23.8", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.8.tgz", + "integrity": "sha512-Osd24mNKe6jr/YoXLLK3k8TMdzaxDffhpCxgkfgBHcapykIkd50HXThM3TCEuHO2pPuCsSx2ms/SunqhU5MmsQ==", + "license": "MIT", + "os": [ + "darwin", + "linux", + "win32", + "freebsd", + "openbsd", + "netbsd", + "sunos", + "android" + ], + "bin": { + "systeminformation": "lib/cli.js" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "Buy me a coffee", + "url": "https://www.buymeacoffee.com/systeminfo" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.200.0.tgz", + "integrity": "sha512-pmPlzfJd+vvgaZd/reMsC8RWgTXn2WY1OWT5RT42m3aOn5532TozwXNDhg1vzqJ+jnvmkREcdLr27ebJEQt0Jg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.200.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "shimmer": "^1.2.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-amqplib": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.47.0.tgz", + "integrity": "sha512-bQboBxolOVDcD4l5QAwqKYpJVKQ8BW82+8tiD5uheu0hDuYgdmDziSAByc8yKS7xpkJw4AYocVP7JwSpQ1hgjg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-lambda": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.51.0.tgz", + "integrity": "sha512-yPtnDum6vykhxA1xZ2kKc3DGmrLdbRAkJG0HiQUcOas47j716wmtqsLCctHyXgO0NpmS/BCzbUnOxxPG6kln7A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/aws-lambda": "8.10.147" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-sdk": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.51.0.tgz", + "integrity": "sha512-NfmdJqrgJyAPGzPJk2bNl8vBn2kbDIHyTmKVNWhcQWh0VCA5aspi75Gsp5tHmLqk26VAtVtUEDZwK3nApFEtzw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/propagation-utils": "^0.31.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-bunyan": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.46.0.tgz", + "integrity": "sha512-7ERXBAMIVi1rtFG5odsLTLVy6IJZnLLB74fFlPstV7/ZZG04UZ8YFOYVS14jXArcPohY8HFYLbm56dIFCXYI9w==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "^0.200.0", + "@opentelemetry/instrumentation": "^0.200.0", + "@types/bunyan": "1.8.11" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-cassandra-driver": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.46.0.tgz", + "integrity": "sha512-ItT2C32afignjHQosleI/iBjzlHhF+F7tJIK9ty47/CceVNlA9oK39ss9f7o9jmnKvQfhNWffvkXdjc0afwnSQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-connect": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.44.0.tgz", + "integrity": "sha512-eChFPViU/nkHsCYSp2PCnHnxt/ZmI/N5reHcwmjXbKhEj6TRNJcjLpI+OQksP8lLu0CS9DlDosHEhknCsxLdjQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/connect": "3.4.38" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-cucumber": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.15.0.tgz", + "integrity": "sha512-MOHDzttn5TSBqt4j3/XjBhYNH0iLQP7oX2pumIzXP7dJFTcUtaq6PVakKPtIaqBTTabOKqCJhrF240XGwWefPQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dataloader": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.17.0.tgz", + "integrity": "sha512-JqovxOo7a65+3A/W+eiqUv7DrDsSvsY0NemHJ4uyVrzD4bpDYofVRdnz/ehYcNerlxVIKU+HcybDmiaoj41DPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dns": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.44.0.tgz", + "integrity": "sha512-+tAFXkFPldOpIba2akqKQ1ukqHET1pZ4pqhrr5x0p+RJ+1a1pPmTt1vCyvSSr634WOY8qMSmzZps++16yxnMbA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-express": { + "version": "0.48.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.48.1.tgz", + "integrity": "sha512-j8NYOf9DRWtchbWor/zA0poI42TpZG9tViIKA0e1lC+6MshTqSJYtgNv8Fn1sx1Wn/TRyp+5OgSXiE4LDfvpEg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fastify": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.45.0.tgz", + "integrity": "sha512-m94anTFZ6jpvK0G5fXIiq1sB0gCgY2rAL7Cg7svuOh9Roya2RIQz2E5KfCsO1kWCmnHNeTo7wIofoGN7WLPvsA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fs": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.20.0.tgz", + "integrity": "sha512-30l45ovjwHb16ImCGVjKCvw5U7X1zKuYY26ii5S+goV8BZ4a/TCpBf2kQxteQjWD05Gl3fzPMZI5aScfPI6Rjw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-generic-pool": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.44.0.tgz", + "integrity": "sha512-bY7locZDqmQLEtY2fIJbSnAbHilxfhflaEQHjevFGkaiXc9UMtOvITOy5JKHhYQISpgrvY2WGXKG7YlVyI7uMg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.48.0.tgz", + "integrity": "sha512-w1sbf9F9bQTpIWGnKWhH1A+9N9rKxS4eM+AzczgMWp272ZM9lQv4zLTrH5NRST2ltY3nmZ72wkfFrSR0rECi0g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-grpc": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.200.0.tgz", + "integrity": "sha512-iaPHlO1qb1WlGUq0oTx0rJND/BtBeTAtyEfflu2VwKDe8XZeia7UEOfiSQxnGqVSTwW5F0P1S5UzqeDJotreWQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "0.200.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-hapi": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.46.0.tgz", + "integrity": "sha512-573y+ZxywEcq+3+Z3KqcbV45lrVwUKvQiP9OhABVFNX8wHbtM6DPRBmYfqiUkSbIBcOEihm5qH6Gs73Xq0RBEA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.200.0.tgz", + "integrity": "sha512-9tqGbCJikhYU68y3k9mi6yWsMyMeCcwoQuHvIXan5VvvPPQ5WIZaV6Mxu/MCVe4swRNoFs8Th+qyj0TZV5ELvw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0", + "@opentelemetry/instrumentation": "0.200.0", + "@opentelemetry/semantic-conventions": "^1.29.0", + "forwarded-parse": "2.1.2" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.48.0.tgz", + "integrity": "sha512-kQhdrn/CAfJIObqbyyGtagWNxPvglJ9FwnWmsfXKodaGskJv/nyvdC9yIcgwzjbkG1pokVUROrvJ0mizqm29Tg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/redis-common": "^0.37.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-kafkajs": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.9.1.tgz", + "integrity": "sha512-eGl5WKBqd0unOKm7PJKjEa1G+ac9nvpDjyv870nUYuSnUkyDc/Fag5keddIjHixTJwRp3FmyP7n+AadAjh52Vw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.30.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-knex": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.45.0.tgz", + "integrity": "sha512-2kkyTDUzK/3G3jxTc+NqHSdgi1Mjw2irZ98T/cSyNdlbsnDOMSTHjbm0AxJCV4QYQ4cKW7a8W/BBgxDGlu+mXQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-koa": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.48.0.tgz", + "integrity": "sha512-LV63v3pxFpjKC0IJO+y5nsGdcH+9Y8Wnn0fhu673XZ5auxqJk2t4nIHuSmls08oRKaX+5q1e+h70XmP/45NJsw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.45.0.tgz", + "integrity": "sha512-W2MNx7hPtvSIgEFxFrqdBykdfN0UrShCbJxvMU9fwgqbOdxIrcubPt0i1vmy3Ap6QwSi+HmsRNQD2w3ucbLG3A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-memcached": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.44.0.tgz", + "integrity": "sha512-1zABdJlF9Tk0yUv2ELpF6Mk2kw81k+bnB3Sw+D/ssRDcGGCnCNbz+fKJE8dwAPkDP+OcTmiKm6ySREbcyRFzCg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/memcached": "^2.2.6" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.53.0.tgz", + "integrity": "sha512-zS2gQJQuG7RZw5yaNG/TnxsOtv1fFkn3ypuDrVLJtJLZtcOr4GYn31jbIA8od+QW/ChZLVcH364iDs+z/xS9wA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongoose": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.47.0.tgz", + "integrity": "sha512-zg4ixMNmuACda75eOFa1m5h794zC9wp397stX0LAZvOylSb6dWT52P6ElkVQMV42C/27liEdQWxpabsamB+XPQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.46.0.tgz", + "integrity": "sha512-Z1NDAv07suIukgL7kxk9cAQX1t/smRMLNOU+q5Aqnhnf/0FIF/N4cX2wg+25IWy0m2PoaPbAVYCKB0aOt5vzAw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/mysql": "2.15.26" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.46.0.tgz", + "integrity": "sha512-JsmIA+aTfHqy2tahjnVWChRipYpYrTy+XFAuUPia9CTaspCx8ZrirPUqYnbnaPEtnzYff2a4LX0B2LT1hKlOiA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.41.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-nestjs-core": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.46.0.tgz", + "integrity": "sha512-5cYnBIMZuTSLFUt0pMH+NQNdI5/2YeCVuz29Mo2lkudbBUOvzGmzl/Y6LG1JEw2j6zuJx5IgO5CKNrJqAIzTWA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.30.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-net": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.44.0.tgz", + "integrity": "sha512-SmAbOKTi0lgdTN9XMXOaf+4jw670MpiK3pw9/to/kRlTvNWwWA4RD34trCcoL7Gf2IYoXuj56Oo4Z5C7N98ukw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.52.0.tgz", + "integrity": "sha512-OBpqlxTqmFkZGHaHV4Pzd95HkyKVS+vf0N5wVX3BSb8uqsvOrW62I1qt+2jNsZ13dtG5eOzvcsQTMGND76wizA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.41.0", + "@types/pg": "8.6.1", + "@types/pg-pool": "2.0.6" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg/node_modules/@types/pg": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", + "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg/node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@opentelemetry/instrumentation-pg/node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@opentelemetry/instrumentation-pg/node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg/node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg/node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pino": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.47.0.tgz", + "integrity": "sha512-OFOy/TGtGXMYWrF4xPKhLN1evdqUpbuoKODzeh3GSjFkcooZZf4m/Hpzu12FV+s0wDBf43oAjXbNJWeCJQMrug==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "^0.200.0", + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-redis": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.47.0.tgz", + "integrity": "sha512-T2YvuX/LaJEQKgKvIQJlbSMSzxp6oBm+9PMgfn7QcBXzSY9tyeyDF6QjLAKNvxs+BJeQzFmDlahjoEyatzxRWA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/redis-common": "^0.37.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-redis-4": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.47.0.tgz", + "integrity": "sha512-9LywJGp1fmmLj6g1+Rv91pVE3ATle1C/qIya9ZLwPywXTOdFIARI/gvvvlI7uFABoLojj2dSaI/5JQrq4C1HSg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/redis-common": "^0.37.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-restify": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.46.0.tgz", + "integrity": "sha512-du1FjKsTGQH6q8QjG0Bxlg0L79Co/Ey0btKKb2sg7fvg0YX6LKdR2N1fzfne/A9k+WjQ5v28JuUXOk2cEPYU/Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-router": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.45.0.tgz", + "integrity": "sha512-CGEeT73Wy/nLQw+obG/mBCIgMbZQKrGG6hzbEdtQ4G2jqI97w7pLWdM4DvkpWVBNcxMpO13dX1nn2OiyZXND3Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-runtime-node": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-runtime-node/-/instrumentation-runtime-node-0.14.0.tgz", + "integrity": "sha512-y78dGoFMKwHSz0SD113Gt1dFTcfunpPZXIJh2SzJN27Lyb9FIzuMfjc3Iu3+s/N6qNOLuS9mKnPe3/qVGG4Waw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-socket.io": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.47.0.tgz", + "integrity": "sha512-qAc+XCcRmZYjs8KJIPv+MMR2wPPPOppwoarzKRR4G+yvOBs1xMwbbkqNHifKga0XcfFX4KVr7Z5QQ6ZZzWyLtg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-tedious": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.19.0.tgz", + "integrity": "sha512-hNC/Bz+g4RvwaKsbA1VD+9x8X2Ml+fN2uba4dniIdQIrAItLdet4xx/7TEoWYtyVJQozphvpnIsUp52Rw4djCA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/tedious": "^4.0.14" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.11.0.tgz", + "integrity": "sha512-H6ijJnKVZBB0Lhm6NsaBt0rUz+i52LriLhrpGAE8SazB0jCIVY4MrL2dNib/4w8zA+Fw9zFwERJvKXUIbSD1ew==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" + } + }, + "node_modules/@opentelemetry/instrumentation-winston": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.45.0.tgz", + "integrity": "sha512-LZz3/6QvzoneSqD/xnB8wq/g1fy8oe2PwfZ15zS2YA5mnjuSqlqgl+k3sib7wfIYHMP1D3ajfbDB6UOJBALj/w==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "^0.200.0", + "@opentelemetry/instrumentation": "^0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.200.0.tgz", + "integrity": "sha512-IxJgA3FD7q4V6gGq4bnmQM5nTIyMDkoGFGrBrrDjB6onEiq1pafma55V+bHvGYLWvcqbBbRfezr1GED88lacEQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0", + "@opentelemetry/otlp-transformer": "0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.200.0.tgz", + "integrity": "sha512-CK2S+bFgOZ66Bsu5hlDeOX6cvW5FVtVjFFbWuaJP0ELxJKBB6HlbLZQ2phqz/uLj1cWap5xJr/PsR3iGoB7Vqw==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.0.0", + "@opentelemetry/otlp-exporter-base": "0.200.0", + "@opentelemetry/otlp-transformer": "0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.200.0.tgz", + "integrity": "sha512-+9YDZbYybOnv7sWzebWOeK6gKyt2XE7iarSyBFkwwnP559pEevKOUD8NyDHhRjCSp13ybh9iVXlMfcj/DwF/yw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.200.0", + "@opentelemetry/core": "2.0.0", + "@opentelemetry/resources": "2.0.0", + "@opentelemetry/sdk-logs": "0.200.0", + "@opentelemetry/sdk-metrics": "2.0.0", + "@opentelemetry/sdk-trace-base": "2.0.0", + "protobufjs": "^7.3.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/propagation-utils": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.31.0.tgz", + "integrity": "sha512-Gnxes8Mwm7BwLCDobUD1A5YoFWIKDch6WQWvO+jc0uvfI4vujDExVghbGg5sTJhHc2Sg2cU0+ANgV/jUjdS79w==", + "license": "Apache-2.0", + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/propagator-b3": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.0.0.tgz", + "integrity": "sha512-blx9S2EI49Ycuw6VZq+bkpaIoiJFhsDuvFGhBIoH3vJ5oYjJ2U0s3fAM5jYft99xVIAv6HqoPtlP9gpVA2IZtA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/propagator-jaeger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.0.0.tgz", + "integrity": "sha512-Mbm/LSFyAtQKP0AQah4AfGgsD+vsZcyreZoQ5okFBk33hU7AquU4TltgyL9dvaO8/Zkoud8/0gEvwfOZ5d7EPA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/redis-common": { + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.37.0.tgz", + "integrity": "sha512-tJwgE6jt32bLs/9J6jhQRKU2EZnsD8qaO13aoFyXwF6s4LhpT7YFHf3Z03MqdILk6BA2BFUhoyh7k9fj9i032A==", + "license": "Apache-2.0", + "engines": { + "node": "^18.19.0 || >=20.6.0" + } + }, + "node_modules/@opentelemetry/resource-detector-alibaba-cloud": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.31.0.tgz", + "integrity": "sha512-Ty3GkSnht10UySMdHC1ngwGEYMbTBxt0/PMpjwbM6ibxkgf57apx04cSeHVm9TwBE/vm9+4/zt4RciCqyWQwtA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-aws": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-2.0.0.tgz", + "integrity": "sha512-jvHvLAXzFPJJhj0AdbMOpup+Fchef32sHM1Suj4NgJGKxTO47T84i5OjKiG/81YEoCaKmlTefezNbuaGCrPd3w==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-azure": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.7.0.tgz", + "integrity": "sha512-aR2ALsK+b/+5lLDhK9KTK8rcuKg7+sqa/Cg+QCeasqoy7qby70FRtAbQcZGljJ5BLBcVPYjl1hcTYIUyL3Laww==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-container": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.7.0.tgz", + "integrity": "sha512-B6DmocHE6bCJt6Iy6z7p+ESjrp7WI4MJN2jWa2MBj9UEZ60Mj/q4BZ8qv0NSmcOYuJhjykNqCUmA+dAOnQn/Kw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-gcp": { + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.34.0.tgz", + "integrity": "sha512-Mug9Oing1nVQE8pYT33UKuPSEa/wjQTMk3feS9F84h4U7oZIx5Mz3yddj3OHOPgrW/7d1Ve/mG7jmYqBI9tpTg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "gcp-metadata": "^6.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", + "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.200.0.tgz", + "integrity": "sha512-VZG870063NLfObmQQNtCVcdXXLzI3vOjjrRENmU37HYiPFa0ZXpXVDsTD02Nh3AT3xYJzQaWKl2X2lQ2l7TWJA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.200.0", + "@opentelemetry/core": "2.0.0", + "@opentelemetry/resources": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.0.tgz", + "integrity": "sha512-Bvy8QDjO05umd0+j+gDeWcTaVa1/R2lDj/eOvjzpm8VQj1K1vVZJuyjThpV5/lSHyYW2JaHF2IQ7Z8twJFAhjA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0", + "@opentelemetry/resources": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.9.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-node": { + "version": "0.200.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.200.0.tgz", + "integrity": "sha512-S/YSy9GIswnhYoDor1RusNkmRughipvTCOQrlF1dzI70yQaf68qgf5WMnzUxdlCl3/et/pvaO75xfPfuEmCK5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.200.0", + "@opentelemetry/core": "2.0.0", + "@opentelemetry/exporter-logs-otlp-grpc": "0.200.0", + "@opentelemetry/exporter-logs-otlp-http": "0.200.0", + "@opentelemetry/exporter-logs-otlp-proto": "0.200.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "0.200.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.200.0", + "@opentelemetry/exporter-metrics-otlp-proto": "0.200.0", + "@opentelemetry/exporter-prometheus": "0.200.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.200.0", + "@opentelemetry/exporter-trace-otlp-http": "0.200.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.200.0", + "@opentelemetry/exporter-zipkin": "2.0.0", + "@opentelemetry/instrumentation": "0.200.0", + "@opentelemetry/propagator-b3": "2.0.0", + "@opentelemetry/propagator-jaeger": "2.0.0", + "@opentelemetry/resources": "2.0.0", + "@opentelemetry/sdk-logs": "0.200.0", + "@opentelemetry/sdk-metrics": "2.0.0", + "@opentelemetry/sdk-trace-base": "2.0.0", + "@opentelemetry/sdk-trace-node": "2.0.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.0.tgz", + "integrity": "sha512-qQnYdX+ZCkonM7tA5iU4fSRsVxbFGml8jbxOgipRGMFHKaXKHQ30js03rTobYjKjIfnOsZSbHKWF0/0v0OQGfw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.0", + "@opentelemetry/resources": "2.0.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-node": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.0.0.tgz", + "integrity": "sha512-omdilCZozUjQwY3uZRBwbaRMJ3p09l4t187Lsdf0dGMye9WKD4NGcpgZRvqhI1dwcH6og+YXQEtoO9Wx3ykilg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/context-async-hooks": "2.0.0", + "@opentelemetry/core": "2.0.0", + "@opentelemetry/sdk-trace-base": "2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.32.0.tgz", + "integrity": "sha512-s0OpmpQFSfMrmedAn9Lhg4KWJELHCU6uU9dtIJ28N8UGhf9Y55im5X8fEzwhwDwiSqN+ZPSNrDJF7ivf/AuRPQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sql-common": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.41.0.tgz", + "integrity": "sha512-pmzXctVbEERbqSfiAgdes9Y63xjoOyXcD7B6IXBkVb+vbM7M9U98mn33nGXxPf4dfYR0M+vhcKRZmbSJ7HfqFA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0" + } + }, + "node_modules/@opentelemetry/winston-transport": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/winston-transport/-/winston-transport-0.11.0.tgz", + "integrity": "sha512-A7tku+4svJxYEtwMQaHLl9hEXNwpEf2tyUF1F9VYHK/rhhY5Wq/zUaSFW2iFBF1Wse5IxBang8C8k9ZTy41hwA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "^0.200.0", + "winston-transport": "4.*" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -6234,6 +7699,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/aws-lambda": { + "version": "8.10.147", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.147.tgz", + "integrity": "sha512-nD0Z9fNIZcxYX5Mai2CTmFD7wX7UldCkW2ezCF8D1T5hdiLsnTWDGRpfRYntU6VjTdLQjOvyszru7I1c1oCQew==", + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -6298,6 +7769,15 @@ "@types/node": "*" } }, + "node_modules/@types/bunyan": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.11.tgz", + "integrity": "sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/caseless": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", @@ -6784,6 +8264,15 @@ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", "license": "MIT" }, + "node_modules/@types/memcached": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/@types/memcached/-/memcached-2.2.10.tgz", + "integrity": "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -6801,6 +8290,15 @@ "bl": ">=5.1.0" } }, + "node_modules/@types/mysql": { + "version": "2.15.26", + "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.26.tgz", + "integrity": "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "22.10.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", @@ -6823,7 +8321,6 @@ "version": "8.11.11", "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.11.tgz", "integrity": "sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", @@ -6831,6 +8328,15 @@ "pg-types": "^4.0.1" } }, + "node_modules/@types/pg-pool": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", + "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", + "license": "MIT", + "dependencies": { + "@types/pg": "*" + } + }, "node_modules/@types/qs": { "version": "6.9.16", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", @@ -6907,6 +8413,12 @@ "@types/send": "*" } }, + "node_modules/@types/shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", + "license": "MIT" + }, "node_modules/@types/sinon": { "version": "17.0.3", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", @@ -6954,6 +8466,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/tedious": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", + "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", @@ -8554,7 +10075,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", - "dev": true, "license": "MIT" }, "node_modules/clean-css": { @@ -10064,9 +11584,9 @@ } }, "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -11413,6 +12933,12 @@ "node": ">= 0.6" } }, + "node_modules/forwarded-parse": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "license": "MIT" + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -12399,6 +13925,18 @@ "node": ">=4" } }, + "node_modules/import-in-the-middle": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.13.1.tgz", + "integrity": "sha512-k2V9wNm9B+ysuelDTHjI9d5KPc4l8zAZTGqj+pcynvWkypZd857ryzN8jNC7Pg2YZXNMJcHRPpaDyCBbNyVRpA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -14748,6 +16286,12 @@ "node": ">=10" } }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", + "license": "MIT" + }, "node_modules/mrmime": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", @@ -15653,7 +17197,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true, "license": "ISC", "engines": { "node": ">=4" @@ -15678,7 +17221,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz", "integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==", - "dev": true, "license": "MIT", "dependencies": { "pg-int8": "1.0.1", @@ -16124,7 +17666,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -16134,7 +17675,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, "license": "MIT", "dependencies": { "obuf": "~1.1.2" @@ -16147,7 +17687,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz", "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -16157,7 +17696,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -16167,7 +17705,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz", "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==", - "dev": true, "license": "MIT" }, "node_modules/prelude-ls": { @@ -16756,6 +18293,20 @@ "node": ">=0.10.0" } }, + "node_modules/require-in-the-middle": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", + "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -17314,6 +18865,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause" + }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", diff --git a/package.json b/package.json index 5966cc52e..3dd79f075 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,18 @@ "@aws-sdk/client-s3": "^3.758.0", "@datastructures-js/priority-queue": "^6.3.1", "@google-cloud/secret-manager": "^5.6.0", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/api-logs": "^0.200.0", + "@opentelemetry/auto-instrumentations-node": "^0.58.0", + "@opentelemetry/exporter-metrics-otlp-http": "^0.200.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.200.0", + "@opentelemetry/host-metrics": "^0.36.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/sdk-logs": "^0.200.0", + "@opentelemetry/sdk-metrics": "^2.0.0", + "@opentelemetry/sdk-node": "^0.200.0", + "@opentelemetry/semantic-conventions": "^1.32.0", + "@opentelemetry/winston-transport": "^0.11.0", "@types/dompurify": "^3.0.5", "@types/express": "^4.17.21", "@types/google-protobuf": "^3.15.12", @@ -95,7 +107,7 @@ "d3": "^7.9.0", "discord.js": "^14.16.3", "dompurify": "^3.1.7", - "dotenv": "^16.4.7", + "dotenv": "^16.5.0", "express": "^4.21.1", "express-rate-limit": "^7.5.0", "google-auth-library": "^9.14.0", @@ -128,6 +140,7 @@ "webpack-dev-server": "^5.0.4", "wheelnav": "^1.7.1", "winston": "^3.17.0", + "winston-transport": "^4.9.0", "ws": "^8.18.0", "zod": "^3.23.8" }, diff --git a/setup.sh b/setup.sh index 982f886b1..32aac1d30 100644 --- a/setup.sh +++ b/setup.sh @@ -71,20 +71,6 @@ else echo "UDP buffer sizes configured and applied" fi -# Check if node-exporter container already exists -if docker ps -a | grep -q "node-exporter"; then - echo "Node Exporter is already installed" -else - echo "🔄 Installing Node Exporter..." - docker run -d --name node-exporter --restart=unless-stopped \ - --net="host" \ - --pid="host" \ - -v "/:/host:ro,rslave" \ - prom/node-exporter:latest \ - --path.rootfs=/host - echo "Node Exporter installed successfully" -fi - # Set proper ownership for openfront's home directory chown -R openfront:openfront /home/openfront echo "Set proper ownership for openfront's home directory" diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts index 777ff8ec9..69bfa773f 100644 --- a/src/core/configuration/Config.ts +++ b/src/core/configuration/Config.ts @@ -44,6 +44,10 @@ export interface ServerConfig { r2Endpoint(): string; r2AccessKey(): string; r2SecretKey(): string; + otelEndpoint(): string; + otelUsername(): string; + otelPassword(): string; + otelEnabled(): boolean; } export interface NukeMagnitude { diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 211ade9e6..596d798ae 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -25,6 +25,20 @@ import { pastelTheme } from "./PastelTheme"; import { pastelThemeDark } from "./PastelThemeDark"; export abstract class DefaultServerConfig implements ServerConfig { + otelEnabled(): boolean { + return Boolean( + this.otelEndpoint() && this.otelUsername() && this.otelPassword(), + ); + } + otelEndpoint(): string { + return process.env.OTEL_ENDPOINT; + } + otelUsername(): string { + return process.env.OTEL_USERNAME; + } + otelPassword(): string { + return process.env.OTEL_PASSWORD; + } region(): string { if (this.env() == GameEnv.Dev) { return "dev"; diff --git a/src/server/Logger.ts b/src/server/Logger.ts index b8c9397e1..e629f1fb8 100644 --- a/src/server/Logger.ts +++ b/src/server/Logger.ts @@ -1,4 +1,55 @@ +import * as logsAPI from "@opentelemetry/api-logs"; +import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http"; +import { + LoggerProvider, + SimpleLogRecordProcessor, +} from "@opentelemetry/sdk-logs"; +import { OpenTelemetryTransportV3 } from "@opentelemetry/winston-transport"; +import * as dotenv from "dotenv"; import winston from "winston"; +import { getServerConfigFromServer } from "../core/configuration/ConfigLoader"; +import { getOtelResource } from "./OtelResource"; +dotenv.config(); + +const config = getServerConfigFromServer(); + +const resource = getOtelResource(); + +// Initialize the OpenTelemetry Logger Provider +const loggerProvider = new LoggerProvider({ + resource, +}); + +if (config.otelEnabled()) { + console.log("OTEL enabled"); + // Configure OpenTelemetry endpoint with basic auth (if provided) + const headers = {}; + if (config.otelUsername() && config.otelPassword()) { + headers["Authorization"] = + "Basic " + + Buffer.from(`${config.otelUsername()}:${config.otelPassword()}`).toString( + "base64", + ); + } + + // Add OTLP exporter for logs + const logExporter = new OTLPLogExporter({ + url: `${config.otelEndpoint()}/v1/logs`, + headers, + }); + + // Add a log processor with the exporter + loggerProvider.addLogRecordProcessor( + new SimpleLogRecordProcessor(logExporter), + ); + + // Set as the global logger provider + logsAPI.logs.setGlobalLoggerProvider(loggerProvider); +} else { + console.log( + "No OTLP endpoint and credentials provided, remote logging disabled", + ); +} // Custom format to add severity tag based on log level const addSeverityFormat = winston.format((info) => { @@ -20,7 +71,10 @@ const logger = winston.createLogger({ service: "openfront", environment: process.env.NODE_ENV, }, - transports: [new winston.transports.Console()], + transports: [ + new winston.transports.Console(), + new OpenTelemetryTransportV3(), + ], }); // Export both the main logger and the child logger factory diff --git a/src/server/Master.ts b/src/server/Master.ts index b8695e634..17b2791c8 100644 --- a/src/server/Master.ts +++ b/src/server/Master.ts @@ -11,7 +11,7 @@ import { generateID } from "../core/Util"; import { gatekeeper, LimiterType } from "./Gatekeeper"; import { logger } from "./Logger"; import { MapPlaylist } from "./MapPlaylist"; -import { setupMetricsServer } from "./MasterMetrics"; +import { setupMasterMetrics } from "./MasterMetrics"; const config = getServerConfigFromServer(); const playlist = new MapPlaylist(); @@ -20,12 +20,13 @@ const readyWorkers = new Set(); const app = express(); const server = http.createServer(app); -// Create a separate metrics server on port 9090 -const metricsApp = express(); -const metricsServer = http.createServer(metricsApp); - const log = logger.child({ comp: "m" }); +if (config.otelEnabled()) { + console.log("setting up master metrics"); + setupMasterMetrics(); +} + const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); app.use(express.json()); @@ -146,9 +147,6 @@ export async function startMaster() { server.listen(PORT, () => { log.info(`Master HTTP server listening on port ${PORT}`); }); - - // Setup the metrics server - setupMetricsServer(); } app.get( diff --git a/src/server/MasterMetrics.ts b/src/server/MasterMetrics.ts index 5b6d3c07a..d0dc77057 100644 --- a/src/server/MasterMetrics.ts +++ b/src/server/MasterMetrics.ts @@ -1,189 +1,69 @@ -import express from "express"; -import http from "http"; -import promClient from "prom-client"; +import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http"; +import { HostMetrics } from "@opentelemetry/host-metrics"; +import { + MeterProvider, + PeriodicExportingMetricReader, +} from "@opentelemetry/sdk-metrics"; +import * as dotenv from "dotenv"; import { getServerConfigFromServer } from "../core/configuration/ConfigLoader"; +import { getOtelResource } from "./OtelResource"; +dotenv.config(); + +// Get server configuration const config = getServerConfigFromServer(); -// Create a separate metrics server on port 9090 -const metricsApp = express(); -const metricsServer = http.createServer(metricsApp); +// Create resource with master information +const resource = getOtelResource(); -// Initialize the Prometheus registry for the master's own metrics -const register = new promClient.Registry(); - -// Default Prometheus metrics -promClient.collectDefaultMetrics({ register }); - -// Prometheus metrics endpoint that gathers metrics from workers -export function setupMetricsServer() { - metricsApp.get("/metrics", async (req, res) => { - // Set a timeout for the request to avoid hanging - const timeout = setTimeout(() => { - res.status(500).end("# Error: Request timed out after 30 seconds"); - }, 30000); - console.log("Metrics requested"); - try { - // Get the master's metrics - const masterMetrics = await register.metrics(); - - // Track seen metric names to avoid duplicate metadata - const seenMetrics = new Set(); - const processedLines = []; - const allMetricValues = []; - - // Process all metadata information in the master metrics first - const masterLines = masterMetrics.split("\n"); - - for (let j = 0; j < masterLines.length; j++) { - const line = masterLines[j]; - - if (line.startsWith("# HELP ")) { - const metricName = line.split(" ")[2]; - seenMetrics.add(metricName); - processedLines.push(line); - } else if (line.startsWith("# TYPE ")) { - const metricName = line.split(" ")[2]; - if (seenMetrics.has(metricName)) { - processedLines.push(line); - } - } else if (line.trim() && !line.startsWith("#")) { - // Add worker label to each metric line and collect for later - const processedLine = line.replace( - /^([a-z][a-z0-9_]*)(?:{([^}]*)})?(\s+[0-9.e+-]+.*)/, - (match, metricName, existingLabels, valueAndRest) => { - if (existingLabels) { - return `${metricName}{${existingLabels},worker="master"}${valueAndRest}`; - } else { - return `${metricName}{worker="master"}${valueAndRest}`; - } - }, - ); - allMetricValues.push(processedLine); - } - } - - // Collect metrics from all workers - for (let i = 0; i < config.numWorkers(); i++) { - const workerPort = config.workerPortByIndex(i); - const workerUrl = `http://localhost:${workerPort}/metrics`; - console.log(`Fetching metrics from worker ${i} at ${workerUrl}`); - - try { - const response = await fetch(workerUrl, { - headers: { - [config.adminHeader()]: config.adminToken(), - }, - }); - - if (!response.ok) { - console.error(`Worker ${i} returned status ${response.status}`); - continue; - } - - const metricsText = await response.text(); - const lines = metricsText.split("\n"); - - for (let j = 0; j < lines.length; j++) { - const line = lines[j]; - - // Collect HELP and TYPE info if we haven't seen this metric before - if (line.startsWith("# HELP ")) { - const metricName = line.split(" ")[2]; - if (!seenMetrics.has(metricName)) { - seenMetrics.add(metricName); - processedLines.push(line); - } - } else if (line.startsWith("# TYPE ")) { - const metricName = line.split(" ")[2]; - if ( - seenMetrics.has(metricName) && - !processedLines.some((l) => - l.startsWith(`# TYPE ${metricName}`), - ) - ) { - processedLines.push(line); - } - } else if (line.trim() && !line.startsWith("#")) { - // Process and collect actual metric values - try { - const processedLine = line.replace( - /^([a-z][a-z0-9_]*)(?:{([^}]*)})?(\s+[0-9.e+-]+.*)/, - (match, metricName, existingLabels, valueAndRest) => { - if (existingLabels) { - return `${metricName}{${existingLabels},worker="worker-${i}"}${valueAndRest}`; - } else { - return `${metricName}{worker="worker-${i}"}${valueAndRest}`; - } - }, - ); - - // Make sure the line was actually processed (regex matched) - if (processedLine !== line) { - allMetricValues.push(processedLine); - } else if ( - line.match(/^[a-z][a-z0-9_]*(?:{[^}]*})?\s+[0-9.e+-]+.*/) - ) { - // This looks like a metric line but didn't match our regex, try a more general approach - const parts = line.split(/({|\s+)/); - if (parts.length >= 3) { - const metricName = parts[0]; - if (line.includes("{")) { - // Has labels - const labelEndIndex = line.indexOf("}"); - const valueStartIndex = labelEndIndex + 1; - if (labelEndIndex > 0 && valueStartIndex < line.length) { - const labels = line.substring( - line.indexOf("{") + 1, - labelEndIndex, - ); - const valueAndRest = line.substring(valueStartIndex); - allMetricValues.push( - `${metricName}{${labels},worker="worker-${i}"}${valueAndRest}`, - ); - } - } else { - // No labels - const valueAndRest = line.substring(metricName.length); - allMetricValues.push( - `${metricName}{worker="worker-${i}"}${valueAndRest}`, - ); - } - } - } - } catch (error) { - console.error(`Error processing metric line: ${line}`, error); - // Skip this line if there's an error - } - } - } - } catch (error) { - console.error(`Error fetching metrics from worker ${i}:`, error); - allMetricValues.push( - `# Error fetching metrics from worker ${i}: ${error.message}`, - ); - } - } - - // Combine metadata with all metric values and ensure it ends with a newline - const combinedMetrics = [...processedLines, ...allMetricValues].join( - "\n", +// Configure headers for basic auth if provided +const getAuthHeaders = () => { + const headers = {}; + if (config.otelEnabled()) { + headers["Authorization"] = + "Basic " + + Buffer.from(`${config.otelUsername()}:${config.otelPassword()}`).toString( + "base64", ); + } + return headers; +}; - // Send the combined response with a final newline to prevent unexpected end of input - clearTimeout(timeout); - res.set("Content-Type", register.contentType); - res.end(combinedMetrics + "\n"); - } catch (error) { - console.error("Error collecting metrics:", error); - clearTimeout(timeout); - res.status(500).end(`# Error collecting metrics: ${error.message}`); - } - }); +// Create metrics exporter +const metricExporter = new OTLPMetricExporter({ + // Dummy endpoint if OTEL is not enabled to avoid parsing errors + url: `${config.otelEndpoint() || "https://dummy_endpoint.com"}/v1/metrics`, + headers: getAuthHeaders(), +}); - // Start the metrics server on port 9090 - const METRICS_PORT = 9090; - metricsServer.listen(METRICS_PORT, () => { - console.log(`Metrics server listening on port ${METRICS_PORT}`); - }); -} +// Configure the metric reader +const metricReader = new PeriodicExportingMetricReader({ + exporter: metricExporter, + exportIntervalMillis: 15000, // Export metrics every 15 seconds +}); + +// Create a meter provider +const meterProvider = new MeterProvider({ + resource, + readers: [metricReader], +}); + +// Setup host metrics +const hostMetrics = new HostMetrics({ meterProvider }); + +// Get meter for creating custom metrics +const meter = meterProvider.getMeter("master-metrics"); + +// Export the metrics for use in the master +export const setupMasterMetrics = () => { + console.log("Starting host metrics collection for master..."); + + // Start collecting host metrics + hostMetrics.start(); + + // Return the meter provider and meter for potential additional metrics + return { + meterProvider, + meter, + }; +}; diff --git a/src/server/OtelResource.ts b/src/server/OtelResource.ts new file mode 100644 index 000000000..99d2b155f --- /dev/null +++ b/src/server/OtelResource.ts @@ -0,0 +1,27 @@ +import { resourceFromAttributes } from "@opentelemetry/resources"; +import { + ATTR_SERVICE_NAME, + ATTR_SERVICE_VERSION, +} from "@opentelemetry/semantic-conventions"; +import { getServerConfigFromServer } from "../core/configuration/ConfigLoader"; + +const config = getServerConfigFromServer(); + +export function getOtelResource() { + return resourceFromAttributes({ + [ATTR_SERVICE_NAME]: "openfront", + [ATTR_SERVICE_VERSION]: "1.0.0", + "service.instance.id": process.env.HOSTNAME, + "openfront.environment": config.env(), + "openfront.host": process.env.HOST, + "openfront.domain": process.env.DOMAIN, + "openfront.subdomain": process.env.SUBDOMAIN, + "openfront.component": process.env.WORKER_ID + ? "Worker " + process.env.WORKER_ID + : "Master", + // The comma-separated list tells OpenTelemetry which resource attributes + // should be converted to Loki labels + "loki.resource.labels": + "service.name,service.instance.id,openfront.environment,openfront.host,openfront.domain,openfront.subdomain,openfront.component", + }); +} diff --git a/src/server/Worker.ts b/src/server/Worker.ts index 9285886a5..cc4f970ea 100644 --- a/src/server/Worker.ts +++ b/src/server/Worker.ts @@ -33,10 +33,12 @@ export function startWorker() { const gm = new GameManager(config, log); - // Set up periodic metrics updates - setInterval(() => { - metrics.updateGameMetrics(gm); - }, 15000); // Update every 15 seconds + if (config.otelEnabled()) { + // Set up periodic metrics updates + setInterval(() => { + metrics.updateGameMetrics(gm); + }, 15000); // Update every 15 seconds + } // Middleware to handle /wX path prefix app.use((req, res, next) => { @@ -251,24 +253,6 @@ export function startWorker() { }), ); - app.get( - "/metrics", - gatekeeper.httpHandler(LimiterType.Get, async (req, res) => { - if (req.headers[config.adminHeader()] !== config.adminToken()) { - return res.status(403).end("Access denied"); - } - log.info(`metrics requested on worker ${workerId}`); - - try { - const metricsData = await metrics.register.metrics(); - res.set("Content-Type", metrics.register.contentType); - res.end(metricsData); - } catch (error) { - res.status(500).end(error.message); - } - }), - ); - // WebSocket handling wss.on("connection", (ws: WebSocket, req) => { ws.on( diff --git a/src/server/WorkerMetrics.ts b/src/server/WorkerMetrics.ts index 5f209e87b..2f402a694 100644 --- a/src/server/WorkerMetrics.ts +++ b/src/server/WorkerMetrics.ts @@ -1,45 +1,103 @@ -import promClient from "prom-client"; +import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http"; +import { + MeterProvider, + PeriodicExportingMetricReader, +} from "@opentelemetry/sdk-metrics"; +import * as dotenv from "dotenv"; +import { getServerConfigFromServer } from "../core/configuration/ConfigLoader"; import { GameManager } from "./GameManager"; +import { getOtelResource } from "./OtelResource"; -// Initialize the Prometheus registry -const register = new promClient.Registry(); +dotenv.config(); -// Enable default Node.js metrics collection -promClient.collectDefaultMetrics({ register }); +// Get server configuration +const config = getServerConfigFromServer(); -// Add worker-specific metrics -const activeGamesGauge = new promClient.Gauge({ - name: "openfront_active_games_count", - help: "Number of active games on this worker", - registers: [register], +// Create resource with worker information +const resource = getOtelResource(); + +// Configure headers for basic auth if provided +const getAuthHeaders = () => { + const headers = {}; + if (config.otelEnabled()) { + headers["Authorization"] = + "Basic " + + Buffer.from(`${config.otelUsername()}:${config.otelPassword()}`).toString( + "base64", + ); + } + return headers; +}; + +// Create metrics exporter +const metricExporter = new OTLPMetricExporter({ + // Dummy endpoint if OTEL is not enabled to avoid parsing errors + url: `${config.otelEndpoint() || "https://dummy_endpoint.com"}/v1/metrics`, + headers: getAuthHeaders(), }); -const connectedClientsGauge = new promClient.Gauge({ - name: "openfront_connected_clients_count", - help: "Number of connected clients on this worker", - registers: [register], +// Configure the metric reader +const metricReader = new PeriodicExportingMetricReader({ + exporter: metricExporter, + exportIntervalMillis: 15000, // Export metrics every 15 seconds }); -const memoryUsageGauge = new promClient.Gauge({ - name: "openfront_memory_usage_bytes", - help: "Current memory usage of the worker process in bytes", - registers: [register], +// Create a meter provider +const meterProvider = new MeterProvider({ + resource, + readers: [metricReader], +}); + +// Get meter for creating metrics +const meter = meterProvider.getMeter("worker-metrics"); + +// Create OpenTelemetry metrics +const activeGamesCounter = meter.createUpDownCounter( + "openfront.active_games.count", + { + description: "Number of active games on this worker", + }, +); + +const connectedClientsCounter = meter.createUpDownCounter( + "openfront.connected_clients.count", + { + description: "Number of connected clients on this worker", + }, +); + +const memoryUsageObservable = meter.createObservableGauge( + "openfront.memory_usage.bytes", + { + description: "Current memory usage of the worker process in bytes", + }, +); + +// Register callback for the memory usage observable +memoryUsageObservable.addCallback((result) => { + const memoryUsage = process.memoryUsage(); + result.observe(memoryUsage.heapUsed); }); // Export the metrics for use in the worker export const metrics = { - register, - activeGamesGauge, - connectedClientsGauge, - memoryUsageGauge, - // Function to update game-related metrics updateGameMetrics: (gameManager: GameManager) => { - activeGamesGauge.set(gameManager.activeGames()); - connectedClientsGauge.set(gameManager.activeClients()); + console.log("Updating game metrics"); + // Get the current counts + const currentActiveGames = gameManager.activeGames(); + const currentActiveClients = gameManager.activeClients(); - // Update memory usage metrics - const memoryUsage = process.memoryUsage(); - memoryUsageGauge.set(memoryUsage.heapUsed); + // Set the absolute values (createUpDownCounter allows setting absolute values) + activeGamesCounter.add(currentActiveGames); + connectedClientsCounter.add(currentActiveClients); + + // Memory metrics are automatically collected by the observable }, + + // Expose the meter provider for potential additional metrics + meterProvider, + + // Expose the meter for creating additional metrics + meter, }; diff --git a/supervisord.conf b/supervisord.conf index 16c3eb212..61b2aec3a 100644 --- a/supervisord.conf +++ b/supervisord.conf @@ -29,19 +29,4 @@ command=cloudflared tunnel run --token %(ENV_CLOUDFLARE_TUNNEL_TOKEN)s autostart=true autorestart=true stdout_logfile=/var/log/cloudflared.log -stderr_logfile=/var/log/cloudflared-err.log - -[program:node_exporter] -command=/usr/local/bin/node_exporter -autostart=true -autorestart=true -stdout_logfile=/var/log/node_exporter.log -stderr_logfile=/var/log/node_exporter-err.log - - -[program:metrics_exporter] -command=/usr/src/app/metric-exporter.sh -autostart=true -autorestart=true -stdout_logfile=/var/log/metrics-exporter.log -stderr_logfile=/var/log/metrics-exporter-err.log +stderr_logfile=/var/log/cloudflared-err.log \ No newline at end of file diff --git a/tests/util/TestServerConfig.ts b/tests/util/TestServerConfig.ts index 3d075e0c7..6921c6dc6 100644 --- a/tests/util/TestServerConfig.ts +++ b/tests/util/TestServerConfig.ts @@ -3,6 +3,18 @@ import { GameMapType } from "../../src/core/game/Game"; import { GameID } from "../../src/core/Schemas"; export class TestServerConfig implements ServerConfig { + otelEnabled(): boolean { + throw new Error("Method not implemented."); + } + otelEndpoint(): string { + throw new Error("Method not implemented."); + } + otelUsername(): string { + throw new Error("Method not implemented."); + } + otelPassword(): string { + throw new Error("Method not implemented."); + } region(): string { return "test"; } diff --git a/update.sh b/update.sh index 840b278bf..c483dbba0 100755 --- a/update.sh +++ b/update.sh @@ -16,19 +16,6 @@ echo "======================================================" # Container and image configuration CONTAINER_NAME="openfront-${ENV}-${SUBDOMAIN}" -# Install Loki Docker plugin if not already installed -if ! docker plugin ls | grep -q "loki"; then - echo "Installing Loki Docker plugin..." - docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions - if [ $? -ne 0 ]; then - echo "Failed to install Loki Docker plugin. Continuing anyway..." - else - echo "Loki Docker plugin installed successfully." - fi -else - echo "Loki Docker plugin already installed." -fi - echo "Pulling ${DOCKER_IMAGE} from Docker Hub..." docker pull $DOCKER_IMAGE @@ -52,31 +39,10 @@ if [ -n "$STOPPED_CONTAINER" ]; then echo "Container $STOPPED_CONTAINER removed." fi -# Check if port 80 is still in use -echo "Checking if port 80 is still in use..." -if command -v lsof >/dev/null 2>&1; then - PORT_CHECK=$(lsof -i :80 | grep LISTEN) -elif command -v netstat >/dev/null 2>&1; then - PORT_CHECK=$(netstat -tuln | grep ":80 ") -else - PORT_CHECK="" - echo "Warning: Cannot check if port is in use (neither lsof nor netstat found)" -fi - -if [ -n "$PORT_CHECK" ]; then - echo "Warning: Port 80 is still in use by another process:" - echo "$PORT_CHECK" - echo "Attempting to proceed anyway..." -fi - echo "Starting new container for ${HOST} environment..." docker run -d \ --restart=always \ $VOLUME_MOUNTS \ - --log-driver=loki \ - --log-opt loki-url="https://${MON_USERNAME}:${MON_PASSWORD}@mon.openfront.io/loki/loki/api/v1/push" \ - --log-opt loki-batch-size="400" \ - --log-opt loki-external-labels="job=docker,environment=${ENV},host=${HOST},subdomain=${SUBDOMAIN}" \ --env-file /home/openfront/.env \ --name ${CONTAINER_NAME} \ $DOCKER_IMAGE @@ -99,5 +65,4 @@ echo "======================================================" echo "✅ SERVER UPDATE COMPLETED SUCCESSFULLY" echo "Container name: ${CONTAINER_NAME}" echo "Image: ${FULL_IMAGE_NAME}" -echo "Logs: Configured to send to Loki on port 3100" echo "======================================================" \ No newline at end of file