Skip to content

Commit 4e9caec

Browse files
Support per-signal OTLP exporter endpoints for Hyperdx internal telemetry (#2098)
## Summary This change allows for more granular control over OpenTelemetry data routing by enabling independent configuration of traces, metrics, and logs endpoints. This is particularly useful for complex networking environments or when using different backends for different telemetry types. Additionally, the browser instrumentation has been updated to a local wrapper to better manage these signal-specific configurations and improve internal consistency. ### How to test locally or on Vercel #### 1. Verify default behavior (no per-signal env vars set) 1. Start HyperDX 2. Confirm the app loads and works as before (login, search, navigate). 3. `curl http://localhost:8080/api/config | jq .` -- verify `collectorUrl` is present and `collectorTracesUrl` / `collectorMetricsUrl` / `collectorLogsUrl` are absent (undefined values are omitted from JSON). #### 2. Verify per-signal env vars are exposed via the config API 1. Stop the app. Set per-signal env vars and restart: ```bash export NEXT_PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://localhost:4318/v1/traces" export NEXT_PUBLIC_OTEL_EXPORTER_OTLP_LOGS_ENDPOINT="http://localhost:4318/v1/logs" yarn dev ``` 2. `curl http://localhost:8080/api/config | jq .` -- confirm `collectorTracesUrl` and `collectorLogsUrl` now appear with the values set above. #### 3. Verify browser telemetry routes to separate endpoints 1. Set the per-signal env vars to two _different_ ports: ```bash export NEXT_PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://localhost:4318/v1/traces" export NEXT_PUBLIC_OTEL_EXPORTER_OTLP_LOGS_ENDPOINT="http://localhost:4319/v1/logs" yarn dev ``` 2. Open the app in a browser with DevTools -> Network tab open. 3. Navigate around, then filter requests by `v1/traces` and `v1/logs`. Confirm trace exports hit `:4318` and session replay log exports hit `:4319`. #### 4. Verify server-side Node.js telemetry (API + Next.js server) 1. `@hyperdx/node-opentelemetry` natively reads per-signal env vars. Set them and start: ```bash export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://localhost:4318/v1/traces" export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT="http://localhost:4319/v1/logs" export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT="http://localhost:4320/v1/metrics" yarn dev ``` 2. Confirm in otel-collector logs that each signal arrives at its respective endpoint. ### References - Linear Issue: #2076 Co-authored-by: Alex Fedotyev <61838744+alex-fedotyev@users.noreply.github.com>
1 parent 9cad6ed commit 4e9caec

11 files changed

Lines changed: 56 additions & 13 deletions

File tree

‎.changeset/deep-years-see.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@hyperdx/app': patch
3+
---
4+
5+
Support per-signal OTLP exporter endpoints for Hyperdx internal telemetry

‎docker-compose.yml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ services:
6262
SERVER_URL: http://127.0.0.1:${HYPERDX_API_PORT}
6363
OPAMP_PORT: ${HYPERDX_OPAMP_PORT}
6464
OTEL_EXPORTER_OTLP_ENDPOINT: 'http://otel-collector:4318'
65+
# Per-signal OTLP endpoints (override OTEL_EXPORTER_OTLP_ENDPOINT for individual signals)
66+
# OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: 'http://otel-collector:4318/v1/traces'
67+
# OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: 'http://otel-collector:4318/v1/metrics'
68+
# OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: 'http://otel-collector:4318/v1/logs'
6569
OTEL_SERVICE_NAME: 'hdx-oss-app'
6670
USAGE_STATS_ENABLED: ${USAGE_STATS_ENABLED:-true}
6771
DEFAULT_CONNECTIONS:

‎packages/api/.env.development‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ NODE_ENV=development
1111
OTEL_SERVICE_NAME="hdx-oss-dev-api"
1212
OTEL_RESOURCE_ATTRIBUTES="service.version=dev"
1313
OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:${HDX_DEV_OTEL_HTTP_PORT}"
14+
# Per-signal OTLP endpoints (override the base endpoint for individual signals)
15+
# OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=
16+
# OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=
17+
# OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=
1418
PORT=${HYPERDX_API_PORT}
1519
OPAMP_PORT=${HYPERDX_OPAMP_PORT}
1620
REDIS_URL=redis://localhost:6379

‎packages/app/.env.development‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,8 @@ PORT=${HYPERDX_APP_PORT}
88
NODE_OPTIONS="--max-http-header-size=131072"
99
NEXT_PUBLIC_HYPERDX_BASE_PATH=
1010
NEXT_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:${HDX_DEV_OTEL_HTTP_PORT:-4318}"
11-
NEXT_PUBLIC_IS_DASHBOARD_LINKING_ENABLED=true
11+
NEXT_PUBLIC_IS_DASHBOARD_LINKING_ENABLED=true
12+
# Per-signal OTLP endpoints (override the base endpoint for individual signals)
13+
# NEXT_PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=
14+
# NEXT_PUBLIC_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=
15+
# NEXT_PUBLIC_OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=

‎packages/app/Dockerfile‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,15 @@ COPY --from=common-utils-builder /app/packages/common-utils ./packages/common-ut
4343
# Expose custom env variables to the browser (needs NEXT_PUBLIC_ prefix)
4444
# doc: https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables#bundling-environment-variables-for-the-browser
4545
ARG OTEL_EXPORTER_OTLP_ENDPOINT
46+
ARG OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
47+
ARG OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
48+
ARG OTEL_EXPORTER_OTLP_LOGS_ENDPOINT
4649
ARG OTEL_SERVICE_NAME
4750
ARG IS_LOCAL_MODE
4851
ENV NEXT_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT $OTEL_EXPORTER_OTLP_ENDPOINT
52+
ENV NEXT_PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT $OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
53+
ENV NEXT_PUBLIC_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT $OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
54+
ENV NEXT_PUBLIC_OTEL_EXPORTER_OTLP_LOGS_ENDPOINT $OTEL_EXPORTER_OTLP_LOGS_ENDPOINT
4955
ENV NEXT_PUBLIC_OTEL_SERVICE_NAME $OTEL_SERVICE_NAME
5056
ENV NEXT_PUBLIC_IS_LOCAL_MODE $IS_LOCAL_MODE
5157

‎packages/app/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"@dnd-kit/sortable": "^10.0.0",
3737
"@dnd-kit/utilities": "^3.2.2",
3838
"@hookform/resolvers": "^3.9.0",
39-
"@hyperdx/browser": "^0.22.0",
39+
"@hyperdx/browser": "^0.22.1",
4040
"@hyperdx/common-utils": "^0.18.1",
4141
"@hyperdx/node-opentelemetry": "^0.9.0",
4242
"@mantine/core": "^9.0.0",

‎packages/app/pages/_app.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
155155
service: _jsonData.serviceName,
156156
// tracePropagationTargets: [new RegExp(hostname ?? 'localhost', 'i')],
157157
url: _jsonData.collectorUrl,
158+
tracesUrl: _jsonData.collectorTracesUrl,
159+
logsUrl: _jsonData.collectorLogsUrl,
158160
});
159161
} else {
160162
console.warn('No API key found to enable OTEL exporter');

‎packages/app/pages/api/config.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import {
44
HDX_API_KEY,
55
HDX_COLLECTOR_URL,
66
HDX_EXPORTER_ENABLED,
7+
HDX_LOGS_COLLECTOR_URL,
8+
HDX_METRICS_COLLECTOR_URL,
79
HDX_SERVICE_NAME,
10+
HDX_TRACES_COLLECTOR_URL,
811
} from '@/config';
912
import type { NextApiConfigResponseData } from '@/types';
1013

@@ -15,6 +18,9 @@ export default function handler(
1518
res.status(200).json({
1619
apiKey: HDX_EXPORTER_ENABLED ? HDX_API_KEY : undefined,
1720
collectorUrl: HDX_COLLECTOR_URL,
21+
collectorTracesUrl: HDX_TRACES_COLLECTOR_URL,
22+
collectorMetricsUrl: HDX_METRICS_COLLECTOR_URL,
23+
collectorLogsUrl: HDX_LOGS_COLLECTOR_URL,
1824
serviceName: HDX_SERVICE_NAME,
1925
appVersion: process.env.NEXT_PUBLIC_APP_VERSION,
2026
});

‎packages/app/src/config.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ export const HDX_COLLECTOR_URL =
3737
process.env.NEXT_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT ??
3838
process.env.OTEL_EXPORTER_OTLP_ENDPOINT ??
3939
'http://localhost:4318';
40+
export const HDX_TRACES_COLLECTOR_URL =
41+
process.env.NEXT_PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ??
42+
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT;
43+
export const HDX_METRICS_COLLECTOR_URL =
44+
process.env.NEXT_PUBLIC_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT ??
45+
process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT;
46+
export const HDX_LOGS_COLLECTOR_URL =
47+
process.env.NEXT_PUBLIC_OTEL_EXPORTER_OTLP_LOGS_ENDPOINT ??
48+
process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT;
4049
export const IS_DEV = NODE_ENV === 'development';
4150

4251
export const IS_OSS = process.env.NEXT_PUBLIC_IS_OSS ?? 'true' === 'true';

‎packages/app/src/types.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ export enum KubePhase {
139139
export type NextApiConfigResponseData = {
140140
apiKey?: string;
141141
collectorUrl: string;
142+
collectorTracesUrl?: string;
143+
collectorMetricsUrl?: string;
144+
collectorLogsUrl?: string;
142145
serviceName: string;
143146
appVersion?: string;
144147
};

0 commit comments

Comments
 (0)