Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/old-lobsters-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hyperdx/node-opentelemetry': patch
---

fix: add loadContext to fix pino trace linking issue
16 changes: 16 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"mode": "pre",
"tag": "next",
"initialVersions": {
"@hyperdx/browser": "0.21.2",
"@hyperdx/cli": "0.1.0",
"@hyperdx/deno": "0.0.2",
"@hyperdx/instrumentation-exception": "0.1.0",
"@hyperdx/instrumentation-sentry-node": "0.1.0",
"@hyperdx/node-logger": "0.4.0",
"@hyperdx/node-opentelemetry": "0.8.2",
"@hyperdx/otel-web": "0.16.3",
"@hyperdx/otel-web-session-recorder": "0.16.2"
},
"changesets": ["old-lobsters-rule", "real-dryers-melt"]
}
5 changes: 5 additions & 0 deletions .changeset/real-dryers-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hyperdx/node-opentelemetry': minor
---

chore: bump otel core to v2 + api to v1.9.0
4 changes: 2 additions & 2 deletions packages/browser/rollup.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import replace from 'rollup-plugin-re';
import resolve from '@rollup/plugin-node-resolve';
import terser from '@rollup/plugin-terser';
import typescript from '@rollup/plugin-typescript';
import replace from 'rollup-plugin-re';
import { visualizer } from 'rollup-plugin-visualizer';

export default {
Expand Down Expand Up @@ -31,11 +31,11 @@ export default {
commonjs(),
resolve({
mainFields: ['module', 'browser', 'main'],
preferBuiltins: false,
dedupe: [
'@opentelemetry/semantic-conventions',
'@opentelemetry/sdk-trace-web',
'@opentelemetry/instrumentation',
'@opentelemetry/core',
'@opentelemetry/api',
],
}),
Expand Down
10 changes: 10 additions & 0 deletions packages/node-opentelemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# @hyperdx/node-opentelemetry

## 0.9.0-next.0

### Minor Changes

- 1907f5b: chore: bump otel core to v2 + api to v1.9.0

### Patch Changes

- 1907f5b: fix: add loadContext to fix pino trace linking issue

## 0.8.2

### Patch Changes
Expand Down
34 changes: 17 additions & 17 deletions packages/node-opentelemetry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@hyperdx/node-opentelemetry",
"author": "Warren <[email protected]>",
"license": "MIT",
"version": "0.8.2",
"version": "0.9.0-next.0",
"homepage": "https://www.hyperdx.io",
"repository": {
"type": "git",
Expand Down Expand Up @@ -34,22 +34,22 @@
"dependencies": {
"@hyperdx/instrumentation-exception": "^0.1.0",
"@hyperdx/instrumentation-sentry-node": "^0.1.0",
"@opentelemetry/api": "^1.8.0",
"@opentelemetry/api-logs": "^0.57.2",
"@opentelemetry/auto-instrumentations-node": "^0.56.1",
"@opentelemetry/core": "^1.30.1",
"@opentelemetry/exporter-logs-otlp-http": "^0.57.2",
"@opentelemetry/exporter-metrics-otlp-proto": "^0.57.2",
"@opentelemetry/exporter-trace-otlp-proto": "^0.57.2",
"@opentelemetry/instrumentation": "^0.57.2",
"@opentelemetry/instrumentation-http": "^0.57.2",
"@opentelemetry/instrumentation-runtime-node": "^0.12.2",
"@opentelemetry/resources": "^1.30.1",
"@opentelemetry/sdk-logs": "^0.57.2",
"@opentelemetry/sdk-metrics": "^1.30.1",
"@opentelemetry/sdk-node": "^0.57.2",
"@opentelemetry/sdk-trace-base": "^1.30.1",
"@opentelemetry/semantic-conventions": "^1.30.0",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/api-logs": "^0.206.0",
"@opentelemetry/auto-instrumentations-node": "^0.65.0",
"@opentelemetry/core": "^2.1.0",
"@opentelemetry/exporter-logs-otlp-http": "^0.206.0",
"@opentelemetry/exporter-metrics-otlp-proto": "^0.206.0",
"@opentelemetry/exporter-trace-otlp-proto": "^0.206.0",
"@opentelemetry/instrumentation": "^0.206.0",
"@opentelemetry/instrumentation-http": "^0.206.0",
"@opentelemetry/instrumentation-runtime-node": "^0.20.0",
"@opentelemetry/resources": "^2.1.0",
"@opentelemetry/sdk-logs": "^0.206.0",
"@opentelemetry/sdk-metrics": "^2.1.0",
"@opentelemetry/sdk-node": "^0.206.0",
"@opentelemetry/sdk-trace-base": "^2.1.0",
"@opentelemetry/semantic-conventions": "^1.37.0",
"cli-spinners": "^2.9.2",
"json-stringify-safe": "^5.0.1",
"lodash.isobject": "^3.0.2",
Expand Down
58 changes: 33 additions & 25 deletions packages/node-opentelemetry/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,52 @@
import { getEnv, getEnvWithoutDefaults } from '@opentelemetry/core';
import { DiagLogLevel } from '@opentelemetry/api';
import {
diagLogLevelFromString,
getNumberFromEnv,
getStringFromEnv,
} from '@opentelemetry/core';
import { defaultServiceName } from '@opentelemetry/resources';

import { stringToBoolean } from './utils';

const env = process.env;

// enable otel debug mode if HDX_DEBUG_MODE_ENABLED is set
const otelEnv = getEnvWithoutDefaults();
const otelEnvWithDefaults = getEnv();

// TO EXTRACT ENV VARS [https://github.com/open-telemetry/opentelemetry-js/blob/3ab4f765d8d696327b7d139ae6a45e7bd7edd924/experimental/packages/sdk-logs/src/export/BatchLogRecordProcessorBase.ts#L50]
// TO EXTRACT DEFAULTS [https://github.com/open-telemetry/opentelemetry-js/blob/3ab4f765d8d696327b7d139ae6a45e7bd7edd924/experimental/packages/sdk-logs/src/types.ts#L49]
export const DEFAULT_EXPORTER_BATCH_SIZE =
otelEnv.OTEL_BLRP_MAX_EXPORT_BATCH_SIZE ?? 512;
getNumberFromEnv('OTEL_BLRP_MAX_EXPORT_BATCH_SIZE') ?? 512;
export const DEFAULT_EXPORTER_TIMEOUT_MS =
otelEnv.OTEL_BLRP_EXPORT_TIMEOUT ?? 30000;
export const DEFAULT_MAX_QUEUE_SIZE = otelEnv.OTEL_BLRP_MAX_QUEUE_SIZE ?? 2048;
export const DEFAULT_OTEL_TRACES_EXPORTER = otelEnv.OTEL_TRACES_EXPORTER;
getNumberFromEnv('OTEL_BLRP_EXPORT_TIMEOUT') ?? 30000;
export const DEFAULT_MAX_QUEUE_SIZE =
getNumberFromEnv('OTEL_BLRP_MAX_QUEUE_SIZE') ?? 2048;
export const DEFAULT_OTEL_TRACES_EXPORTER = getStringFromEnv(
'OTEL_TRACES_EXPORTER',
);
const otlpEndpoint = getStringFromEnv('OTEL_EXPORTER_OTLP_ENDPOINT');
export const DEFAULT_OTEL_TRACES_EXPORTER_URL =
otelEnv.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ??
(otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT
? `${otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/traces`
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') ??
(otlpEndpoint
? `${otlpEndpoint}/v1/traces`
: 'https://in-otel.hyperdx.io/v1/traces');
export const DEFAULT_OTEL_TRACES_SAMPLER =
otelEnv.OTEL_TRACES_SAMPLER ?? 'parentbased_always_on';
getStringFromEnv('OTEL_TRACES_SAMPLER') ?? 'parentbased_always_on';
export const DEFAULT_OTEL_TRACES_SAMPLER_ARG =
otelEnv.OTEL_TRACES_SAMPLER_ARG ?? '1';
getStringFromEnv('OTEL_TRACES_SAMPLER_ARG') ?? '1';
export const DEFAULT_OTEL_EXPORTER_OTLP_TRACES_TIMEOUT =
otelEnv.OTEL_EXPORTER_OTLP_TRACES_TIMEOUT ?? 60000;
getNumberFromEnv('OTEL_EXPORTER_OTLP_TRACES_TIMEOUT') ?? 60000;
export const DEFAULT_SEND_INTERVAL_MS =
otelEnv.OTEL_BLRP_SCHEDULE_DELAY ?? 2000;
export const DEFAULT_OTEL_LOGS_EXPORTER = otelEnv.OTEL_LOGS_EXPORTER;
getNumberFromEnv('OTEL_BLRP_SCHEDULE_DELAY') ?? 2000;
export const DEFAULT_OTEL_LOGS_EXPORTER =
getStringFromEnv('OTEL_LOGS_EXPORTER');
export const DEFAULT_OTEL_LOGS_EXPORTER_URL =
otelEnv.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT ??
(otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT
? `${otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/logs`
getStringFromEnv('OTEL_EXPORTER_OTLP_LOGS_ENDPOINT') ??
(otlpEndpoint
? `${otlpEndpoint}/v1/logs`
: 'https://in-otel.hyperdx.io/v1/logs');
export const DEFAULT_OTEL_METRICS_EXPORTER = env.OTEL_METRICS_EXPORTER; // not exist yet
export const DEFAULT_OTEL_METRICS_EXPORTER_URL =
otelEnv.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT ??
(otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT
? `${otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/metrics`
getStringFromEnv('OTEL_EXPORTER_OTLP_METRICS_ENDPOINT') ??
(otlpEndpoint
? `${otlpEndpoint}/v1/metrics`
: 'https://in-otel.hyperdx.io/v1/metrics');
export const DEFAULT_OTEL_METRIC_EXPORT_INTERVAL =
env.OTEL_METRIC_EXPORT_INTERVAL
Expand All @@ -50,8 +56,10 @@ export const DEFAULT_OTEL_METRIC_EXPORT_TIMEOUT = env.OTEL_METRIC_EXPORT_TIMEOUT
? Number(env.OTEL_METRIC_EXPORT_TIMEOUT)
: 30000; // not exist yet
export const DEFAULT_SERVICE_NAME = () =>
getEnvWithoutDefaults().OTEL_SERVICE_NAME ?? defaultServiceName();
export const DEFAULT_OTEL_LOG_LEVEL = otelEnvWithDefaults.OTEL_LOG_LEVEL;
getStringFromEnv('OTEL_SERVICE_NAME') ?? defaultServiceName();
export const DEFAULT_OTEL_LOG_LEVEL = diagLogLevelFromString(
getStringFromEnv('OTEL_LOG_LEVEL'),
);

// HyperDX SDK specific configuration
export const DEFAULT_HDX_API_KEY = () => env.HYPERDX_API_KEY;
Expand Down
96 changes: 72 additions & 24 deletions packages/node-opentelemetry/src/otel-logger/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { Attributes, diag } from '@opentelemetry/api';
import { Logger as OtelLogger, logs } from '@opentelemetry/api-logs';
import { getEnvWithoutDefaults } from '@opentelemetry/core';
import {
Attributes,
context as apiContext,
diag,
trace,
} from '@opentelemetry/api';
import { Logger as OtelLogger, LogRecord, logs } from '@opentelemetry/api-logs';
import { getStringFromEnv } from '@opentelemetry/core';
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
import {
detectResourcesSync,
envDetectorSync,
hostDetectorSync,
osDetectorSync,
detectResources,
envDetector,
hostDetector,
osDetector,
processDetector,
Resource,
resourceFromAttributes,
} from '@opentelemetry/resources';
import {
BatchLogRecordProcessor,
Expand All @@ -29,6 +34,47 @@ import {

const LOG_PREFIX = `⚠️ [LOGGER]`;

/**
* Load context from attributes and set it to logRecord.context
*
* @param {LogRecord} logRecord
* @returns {LogRecord}
*/
function loadContext(logRecord: LogRecord): LogRecord {
let context = apiContext.active();
let attributes = logRecord.attributes;

if (typeof attributes !== 'undefined') {
const { trace_id, span_id, trace_flags, ...otherAttributes } =
logRecord.attributes as Attributes & {
trace_id?: string;
span_id?: string;
trace_flags?: number;
};

if (
typeof trace_id !== 'undefined' &&
typeof span_id !== 'undefined' &&
typeof trace_flags !== 'undefined'
) {
context = trace.setSpanContext(context, {
traceId: trace_id,
spanId: span_id,
traceFlags: trace_flags,
isRemote: true,
});
}

attributes = otherAttributes;
}

return {
...logRecord,
attributes,
context,
};
}

export type LoggerOptions = {
baseUrl?: string;
bufferSize?: number;
Expand All @@ -53,7 +99,7 @@ export class Logger {
constructor({
baseUrl,
bufferSize,
detectResources,
detectResources: shouldDetectResources,
headers,
queueSize,
resourceAttributes,
Expand All @@ -76,9 +122,9 @@ export class Logger {
maxQueueSize = maxExportBatchSize;
}

const detectedResource = detectResourcesSync({
detectors: detectResources
? [envDetectorSync, hostDetectorSync, osDetectorSync, processDetector]
const detectedResource = detectResources({
detectors: shouldDetectResources
? [envDetector, hostDetector, osDetector, processDetector]
: [],
});

Expand All @@ -102,15 +148,15 @@ export class Logger {
});
this.provider = new LoggerProvider({
resource: detectedResource.merge(
new Resource({
resourceFromAttributes({
// TODO: should use otel semantic conventions
'hyperdx.distro.version': PKG_VERSION,
[SEMRESATTRS_SERVICE_NAME]: service ?? _serviceName,
...resourceAttributes,
}),
),
processors: [this.processor],
});
this.provider.addLogRecordProcessor(this.processor);

this.logger = this.provider.getLogger('node-logger');
}
Expand All @@ -125,7 +171,7 @@ export class Logger {
}

isDisabled() {
return getEnvWithoutDefaults().OTEL_LOGS_EXPORTER === 'none';
return getStringFromEnv('OTEL_LOGS_EXPORTER') === 'none';
}

setGlobalLoggerProvider() {
Expand Down Expand Up @@ -156,14 +202,16 @@ export class Logger {
}

postMessage(level: string, body: string, attributes: Attributes = {}): void {
this.logger.emit({
// TODO: should map to otel severity number
severityNumber: 0,
// TODO: set up the mapping between different downstream log levels
severityText: level,
body,
attributes,
timestamp: this.parseTimestamp(attributes),
});
this.logger.emit(
loadContext({
// TODO: should map to otel severity number
severityNumber: 0,
// TODO: set up the mapping between different downstream log levels
severityText: level,
body,
attributes,
timestamp: this.parseTimestamp(attributes),
}),
);
}
}
4 changes: 2 additions & 2 deletions packages/node-opentelemetry/src/otel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
InstrumentationModuleDefinition,
} from '@opentelemetry/instrumentation';
import { RuntimeNodeInstrumentation } from '@opentelemetry/instrumentation-runtime-node';
import { Resource } from '@opentelemetry/resources';
import { resourceFromAttributes } from '@opentelemetry/resources';
import { MetricReader } from '@opentelemetry/sdk-metrics';
import { NodeSDK } from '@opentelemetry/sdk-node';
import cliSpinners from 'cli-spinners';
Expand Down Expand Up @@ -329,7 +329,7 @@ export const initSDK = (config: SDKConfig) => {
];

sdk = new NodeSDK({
resource: new Resource({
resource: resourceFromAttributes({
// https://opentelemetry.io/docs/specs/semconv/resource/#telemetry-sdk-experimental
'telemetry.distro.name': 'hyperdx',
'telemetry.distro.version': PKG_VERSION,
Expand Down
Loading