Skip to content

Commit d29e2bc

Browse files
authored
fix: handle the case when CUSTOM_OTELCOL_CONFIG_FILE is not specified (#1080)
plus fixing startup issue when the team isn't created yet
1 parent 5eeee5c commit d29e2bc

File tree

5 files changed

+155
-145
lines changed

5 files changed

+155
-145
lines changed

.changeset/happy-tips-cough.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@hyperdx/api": patch
3+
"@hyperdx/app": patch
4+
"@hyperdx/common-utils": patch
5+
---
6+
7+
fix: handle the case when `CUSTOM_OTELCOL_CONFIG_FILE` is not specified

docker/otel-collector/Dockerfile

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ FROM alpine:latest@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff45
88
ARG USER_UID=10001
99
ARG USER_GID=10001
1010

11-
# Install certs, create user/group, and make the writable data dir
11+
# Install certs, gomplate for templating, create user/group, and make the writable data dir
1212
RUN apk add --no-cache ca-certificates && \
13+
wget -O /usr/local/bin/gomplate https://github.com/hairyhenderson/gomplate/releases/download/v4.3.3/gomplate_linux-amd64 && \
14+
chmod +x /usr/local/bin/gomplate && \
1315
addgroup -S -g ${USER_GID} otel && \
1416
adduser -S -u ${USER_UID} -G otel otel && \
1517
install -d -m 0777 -o ${USER_UID} -g ${USER_GID} /etc/otel/supervisor-data
@@ -27,7 +29,7 @@ COPY --chmod=755 ./log-rotator.sh /log-rotator.sh
2729
FROM base AS dev
2830

2931
COPY ./config.yaml /etc/otelcol-contrib/config.yaml
30-
COPY ./supervisor_docker.yaml /etc/otel/supervisor.yaml
32+
COPY ./supervisor_docker.yaml.tmpl /etc/otel/supervisor.yaml.tmpl
3133

3234
EXPOSE 4317 4318 13133
3335

@@ -38,7 +40,7 @@ CMD ["--config", "/etc/otel/supervisor.yaml"]
3840
FROM base AS prod
3941

4042
COPY ./config.yaml /etc/otelcol-contrib/config.yaml
41-
COPY ./supervisor_docker.yaml /etc/otel/supervisor.yaml
43+
COPY ./supervisor_docker.yaml.tmpl /etc/otel/supervisor.yaml.tmpl
4244

4345
EXPOSE 4317 4318 13133
4446

docker/otel-collector/entrypoint.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,19 @@ set -e
55
# Arguments: log_file_path [max_size_mb] [max_archives] [check_interval_seconds]
66
/log-rotator.sh /etc/otel/supervisor-data/agent.log 16 1 60 &
77

8+
# Render the supervisor config template using gomplate
9+
# Write to supervisor-data directory which has proper permissions for otel user
10+
gomplate -f /etc/otel/supervisor.yaml.tmpl -o /etc/otel/supervisor-data/supervisor-runtime.yaml
11+
12+
# Log the configuration being used
13+
if [ -n "$CUSTOM_OTELCOL_CONFIG_FILE" ]; then
14+
echo "Using custom OTEL config file: $CUSTOM_OTELCOL_CONFIG_FILE"
15+
else
16+
echo "CUSTOM_OTELCOL_CONFIG_FILE not set, using default configuration"
17+
fi
18+
19+
# Update the command arguments to use the rendered config file
20+
set -- "$1" --config /etc/otel/supervisor-data/supervisor-runtime.yaml
21+
822
# Execute the supervisor with all passed arguments
923
exec "$@"

docker/otel-collector/supervisor_docker.yaml renamed to docker/otel-collector/supervisor_docker.yaml.tmpl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/cmd/opampsupervisor/specification/README.md#supervisor-configuration
22
server:
3-
endpoint: ${OPAMP_SERVER_URL}/v1/opamp
3+
endpoint: {{ getenv "OPAMP_SERVER_URL" }}/v1/opamp
44
tls:
55
# Disable verification to test locally.
66
# Don't do this in production.
@@ -20,10 +20,14 @@ agent:
2020
executable: /otelcontribcol
2121
config_files:
2222
- /etc/otelcol-contrib/config.yaml
23-
- ${env:CUSTOM_OTELCOL_CONFIG_FILE}
23+
{{- if getenv "CUSTOM_OTELCOL_CONFIG_FILE" }}
24+
- {{ getenv "CUSTOM_OTELCOL_CONFIG_FILE" }}
25+
{{- end }}
2426
args:
25-
- ${env:OTEL_AGENT_FEATURE_GATE_ARG}
26-
passthrough_logs: ${env:OTEL_SUPERVISOR_PASSTHROUGH_LOGS}
27+
{{- if getenv "OTEL_AGENT_FEATURE_GATE_ARG" }}
28+
- {{ getenv "OTEL_AGENT_FEATURE_GATE_ARG" }}
29+
{{- end }}
30+
passthrough_logs: {{ getenv "OTEL_SUPERVISOR_PASSTHROUGH_LOGS" | default "false" }}
2731

2832
storage:
2933
directory: /etc/otel/supervisor-data/

packages/api/src/opamp/controllers/opampController.ts

Lines changed: 121 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ type CollectorConfig = {
106106
extensions: string[];
107107
pipelines: {
108108
[key: string]: {
109-
receivers?: string[];
109+
receivers: string[];
110110
processors?: string[];
111-
exporters?: string[];
111+
exporters: string[];
112112
};
113113
};
114114
};
@@ -119,129 +119,139 @@ export const buildOtelCollectorConfig = (teams: ITeam[]): CollectorConfig => {
119119
const collectorAuthenticationEnforced =
120120
teams[0]?.collectorAuthenticationEnforced;
121121

122-
if (apiKeys && apiKeys.length > 0) {
123-
// Build full configuration with all team API keys
124-
const otelCollectorConfig: CollectorConfig = {
125-
extensions: {},
126-
receivers: {
127-
'otlp/hyperdx': {
128-
protocols: {
129-
grpc: {
130-
endpoint: '0.0.0.0:4317',
131-
include_metadata: true,
132-
},
133-
http: {
134-
endpoint: '0.0.0.0:4318',
135-
cors: {
136-
allowed_origins: ['*'],
137-
allowed_headers: ['*'],
138-
},
139-
include_metadata: true,
140-
},
122+
const otelCollectorConfig: CollectorConfig = {
123+
extensions: {},
124+
receivers: {
125+
nop: null,
126+
'otlp/hyperdx': {
127+
protocols: {
128+
grpc: {
129+
endpoint: '0.0.0.0:4317',
130+
include_metadata: true,
141131
},
142-
},
143-
prometheus: {
144-
config: {
145-
scrape_configs: [
146-
{
147-
job_name: 'otelcol',
148-
scrape_interval: '30s',
149-
static_configs: [
150-
{
151-
targets: [
152-
'0.0.0.0:8888',
153-
'${env:CLICKHOUSE_PROMETHEUS_METRICS_ENDPOINT}',
154-
],
155-
},
156-
],
157-
},
158-
],
132+
http: {
133+
endpoint: '0.0.0.0:4318',
134+
cors: {
135+
allowed_origins: ['*'],
136+
allowed_headers: ['*'],
137+
},
138+
include_metadata: true,
159139
},
160140
},
161-
fluentforward: {
162-
endpoint: '0.0.0.0:24225',
163-
},
164141
},
165-
connectors: {
166-
'routing/logs': {
167-
default_pipelines: ['logs/out-default'],
168-
error_mode: 'ignore',
169-
table: [
142+
prometheus: {
143+
config: {
144+
scrape_configs: [
170145
{
171-
context: 'log',
172-
statement:
173-
'route() where IsMatch(attributes["rr-web.event"], ".*")',
174-
pipelines: ['logs/out-rrweb'],
146+
job_name: 'otelcol',
147+
scrape_interval: '30s',
148+
static_configs: [
149+
{
150+
targets: [
151+
'0.0.0.0:8888',
152+
'${env:CLICKHOUSE_PROMETHEUS_METRICS_ENDPOINT}',
153+
],
154+
},
155+
],
175156
},
176157
],
177158
},
178159
},
179-
exporters: {
180-
debug: {
181-
verbosity: 'detailed',
182-
sampling_initial: 5,
183-
sampling_thereafter: 200,
184-
},
185-
'clickhouse/rrweb': {
186-
endpoint: '${env:CLICKHOUSE_ENDPOINT}',
187-
database: '${env:HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE}',
188-
username: '${env:CLICKHOUSE_USER}',
189-
password: '${env:CLICKHOUSE_PASSWORD}',
190-
ttl: '720h',
191-
logs_table_name: 'hyperdx_sessions',
192-
timeout: '5s',
193-
retry_on_failure: {
194-
enabled: true,
195-
initial_interval: '5s',
196-
max_interval: '30s',
197-
max_elapsed_time: '300s',
160+
fluentforward: {
161+
endpoint: '0.0.0.0:24225',
162+
},
163+
},
164+
connectors: {
165+
'routing/logs': {
166+
default_pipelines: ['logs/out-default'],
167+
error_mode: 'ignore',
168+
table: [
169+
{
170+
context: 'log',
171+
statement:
172+
'route() where IsMatch(attributes["rr-web.event"], ".*")',
173+
pipelines: ['logs/out-rrweb'],
198174
},
175+
],
176+
},
177+
},
178+
exporters: {
179+
debug: {
180+
verbosity: 'detailed',
181+
sampling_initial: 5,
182+
sampling_thereafter: 200,
183+
},
184+
'clickhouse/rrweb': {
185+
endpoint: '${env:CLICKHOUSE_ENDPOINT}',
186+
database: '${env:HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE}',
187+
username: '${env:CLICKHOUSE_USER}',
188+
password: '${env:CLICKHOUSE_PASSWORD}',
189+
ttl: '720h',
190+
logs_table_name: 'hyperdx_sessions',
191+
timeout: '5s',
192+
retry_on_failure: {
193+
enabled: true,
194+
initial_interval: '5s',
195+
max_interval: '30s',
196+
max_elapsed_time: '300s',
199197
},
200-
clickhouse: {
201-
endpoint: '${env:CLICKHOUSE_ENDPOINT}',
202-
database: '${env:HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE}',
203-
username: '${env:CLICKHOUSE_USER}',
204-
password: '${env:CLICKHOUSE_PASSWORD}',
205-
ttl: '720h',
206-
timeout: '5s',
207-
retry_on_failure: {
208-
enabled: true,
209-
initial_interval: '5s',
210-
max_interval: '30s',
211-
max_elapsed_time: '300s',
212-
},
198+
},
199+
clickhouse: {
200+
endpoint: '${env:CLICKHOUSE_ENDPOINT}',
201+
database: '${env:HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE}',
202+
username: '${env:CLICKHOUSE_USER}',
203+
password: '${env:CLICKHOUSE_PASSWORD}',
204+
ttl: '720h',
205+
timeout: '5s',
206+
retry_on_failure: {
207+
enabled: true,
208+
initial_interval: '5s',
209+
max_interval: '30s',
210+
max_elapsed_time: '300s',
213211
},
214212
},
215-
service: {
216-
extensions: [],
217-
pipelines: {
218-
traces: {
219-
receivers: ['otlp/hyperdx'],
220-
processors: ['memory_limiter', 'batch'],
221-
exporters: ['clickhouse'],
222-
},
223-
metrics: {
224-
receivers: ['otlp/hyperdx', 'prometheus'],
225-
processors: ['memory_limiter', 'batch'],
226-
exporters: ['clickhouse'],
227-
},
228-
'logs/in': {
229-
receivers: ['otlp/hyperdx', 'fluentforward'],
230-
exporters: ['routing/logs'],
231-
},
232-
'logs/out-default': {
233-
receivers: ['routing/logs'],
234-
processors: ['memory_limiter', 'transform', 'batch'],
235-
exporters: ['clickhouse'],
236-
},
237-
'logs/out-rrweb': {
238-
receivers: ['routing/logs'],
239-
processors: ['memory_limiter', 'batch'],
240-
exporters: ['clickhouse/rrweb'],
241-
},
213+
},
214+
service: {
215+
extensions: [],
216+
pipelines: {
217+
traces: {
218+
receivers: ['nop'],
219+
processors: ['memory_limiter', 'batch'],
220+
exporters: ['clickhouse'],
221+
},
222+
metrics: {
223+
// TODO: prometheus needs to be authenticated
224+
receivers: ['prometheus'],
225+
processors: ['memory_limiter', 'batch'],
226+
exporters: ['clickhouse'],
227+
},
228+
'logs/in': {
229+
// TODO: fluentforward needs to be authenticated
230+
receivers: ['fluentforward'],
231+
exporters: ['routing/logs'],
232+
},
233+
'logs/out-default': {
234+
receivers: ['routing/logs'],
235+
processors: ['memory_limiter', 'transform', 'batch'],
236+
exporters: ['clickhouse'],
237+
},
238+
'logs/out-rrweb': {
239+
receivers: ['routing/logs'],
240+
processors: ['memory_limiter', 'batch'],
241+
exporters: ['clickhouse/rrweb'],
242242
},
243243
},
244-
};
244+
},
245+
};
246+
if (apiKeys && apiKeys.length > 0) {
247+
// attach otlp/hyperdx receiver
248+
otelCollectorConfig.service.pipelines.traces.receivers.push('otlp/hyperdx');
249+
otelCollectorConfig.service.pipelines.metrics.receivers.push(
250+
'otlp/hyperdx',
251+
);
252+
otelCollectorConfig.service.pipelines['logs/in'].receivers.push(
253+
'otlp/hyperdx',
254+
);
245255

246256
if (collectorAuthenticationEnforced) {
247257
if (otelCollectorConfig.receivers['otlp/hyperdx'] == null) {
@@ -261,36 +271,9 @@ export const buildOtelCollectorConfig = (teams: ITeam[]): CollectorConfig => {
261271
};
262272
otelCollectorConfig.service.extensions = ['bearertokenauth/hyperdx'];
263273
}
264-
265-
return otelCollectorConfig;
266274
}
267275

268-
// If no apiKeys are found, return NOP config
269-
// This is later merged with otel-collector/config.yaml
270-
// we need to instantiate a valid config so the collector
271-
// can at least start up
272-
return {
273-
extensions: {},
274-
receivers: {
275-
nop: null,
276-
},
277-
connectors: {},
278-
exporters: {},
279-
service: {
280-
extensions: [],
281-
pipelines: {
282-
traces: {
283-
receivers: ['nop'],
284-
},
285-
metrics: {
286-
receivers: ['nop'],
287-
},
288-
logs: {
289-
receivers: ['nop'],
290-
},
291-
},
292-
},
293-
};
276+
return otelCollectorConfig;
294277
};
295278

296279
export class OpampController {

0 commit comments

Comments
 (0)