diff --git a/docs/advanced-config.md b/docs/advanced-config.md
index 3dc3a782..5a21d3e5 100644
--- a/docs/advanced-config.md
+++ b/docs/advanced-config.md
@@ -55,7 +55,7 @@ This distribution supports all the configuration options supported by the compon
| --------------------------------------------------------------- | ----------------------- | ------- | ---
| `OTEL_ATTRIBUTE_COUNT_LIMIT` | | Stable | Maximum allowed span attribute count
| `OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT` | `12000`\* | Stable | Maximum allowed attribute value size
-| `OTEL_EXPORTER_OTLP_ENDPOINT`
`endpoint` | `http://localhost:4317` | Stable | The OTLP endpoint to export to.
+| `OTEL_EXPORTER_OTLP_ENDPOINT`
`endpoint` | `http://localhost:4318` | Stable | The OTLP endpoint to export to.
| `OTEL_LOG_LEVEL` | | Stable | Log level to use in diagnostics logging. **Does not set the logger.**
| `OTEL_PROPAGATORS`
`tracing.propagators` | `tracecontext,baggage` | Stable | Comma-delimited list of propagators to use. Valid keys: `baggage`, `tracecontext`, `b3multi`, `b3`.
| `OTEL_RESOURCE_ATTRIBUTES` | | Stable | Comma-separated list of resource attributes added to every reported span. Example
`key1=val1,key2=val2`
@@ -97,10 +97,10 @@ The following config options can be set by passing them as tracing arguments to
| Environment variable
``start()`` argument | Default value | Support | Notes
| --------------------------------------------------------------- | ----------------------- | ------- | ---
| `OTEL_SERVICE_NAME`
`serviceName` | `unnamed-node-service` | Stable | The service name of this Node service.
-| `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`
`endpoint` | `http://localhost:4317` | Stable | The OTLP endpoint to export to.
+| `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`
`endpoint` | `http://localhost:4318` | Stable | The OTLP endpoint to export to.
| `OTEL_METRIC_EXPORT_INTERVAL`
`metrics.exportIntervalMillis` | `30000` | Stable | The interval, in milliseconds, of metrics collection and exporting.
| `OTEL_METRICS_EXPORTER`
`metrics.metricReaderFactory` | `otlp` | Stable | Chooses the metric exporters. Comma-delimited list of exporters. Currently supported values: `otlp`, `console`, `none`.
-| `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL`
`metrics.metricReaderFactory` | `grpc` | Stable | Chooses the metric exporter protocol. Currently supported values: `grpc`, `http/protobuf`.
+| `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL`
`metrics.metricReaderFactory` | `http/protobuf` | Stable | Chooses the metric exporter protocol. Currently supported values: `grpc`, `http/protobuf`.
| `OTEL_RESOURCE_ATTRIBUTES` | | Stable | The resource attributes to metric data. Environment variable example
`key1=val1,key2=val2`
| `SPLUNK_METRICS_ENABLED`
n/a (enabled by calling `start`) | `false` | Experimental | Sets up the metrics pipeline (global meter provider, exporters).
| n/a
`metrics.resourceFactory` | | Experimental | Callback which allows to filter the default resource or provide a custom one. The function takes one argument of type `Resource` which is the resource pre-filled by the SDK containing the `service.name`, environment, host and process attributes. |
@@ -114,7 +114,7 @@ The following config options can be set by passing them as tracing arguments to
| --------------------------------------------------------------- | ----------------------- | ------- | ---
| `SPLUNK_PROFILER_ENABLED` | `false` | Experimental | Enable continuous profiling.
| `SPLUNK_PROFILER_MEMORY_ENABLED`
`profiling.memoryProfilingEnabled` | `false` | Experimental | Enable continuous memory profiling.
-| `SPLUNK_PROFILER_LOGS_ENDPOINT`
`endpoint` | `http://localhost:4317` | Experimental | The OTLP logs receiver endpoint used for profiling data.
+| `SPLUNK_PROFILER_LOGS_ENDPOINT`
`endpoint` | `http://localhost:4318` | Experimental | The OTLP logs receiver endpoint used for profiling data.
| `OTEL_SERVICE_NAME`
`serviceName` | `unnamed-node-service` | Stable | Service name of the application.
| `OTEL_RESOURCE_ATTRIBUTES` | | Stable | Comma-separated list of resource attributes. Example
`deployment.environment=demo,key2=val2`
diff --git a/examples/profiling/README.md b/examples/profiling/README.md
index 56e85f44..e9f75116 100644
--- a/examples/profiling/README.md
+++ b/examples/profiling/README.md
@@ -1,7 +1,7 @@
# Profiling Example
This example showcases enabling profiling for Splunk APM. There's no official support for profiling in OTel, so profiling requires working with some Splunk-specific components.
-By default, the example requires the OTel Collector to run with the OTLP receiver listening for logs on `localhost:4317`. To export profiling data to APM, you must set up `splunk_hec` exporter in the Collector. See [the example collector config](./collector-config.yml).
+By default, the example requires the OTel Collector to run with the OTLP receiver listening for logs on `localhost:4318`. To export profiling data to APM, you must set up `splunk_hec` exporter in the Collector. See [the example collector config](./collector-config.yml).
```shell
# Replace <...> with the correct values
@@ -17,7 +17,7 @@ Then run the script in a separate terminal:
# Optional. To set the environment:
export OTEL_SERVICE_NAME='profiling-example'
export OTEL_RESOURCE_ATTRIBUTES='deployment.environment=dev'
-export OTEL_LOG_LEVEL='DEBUG'
+export OTEL_LOG_LEVEL=debug
# Run the example:
npm start
```
diff --git a/examples/profiling/collector-config.yml b/examples/profiling/collector-config.yml
index 96730b77..eabcfd26 100644
--- a/examples/profiling/collector-config.yml
+++ b/examples/profiling/collector-config.yml
@@ -2,7 +2,9 @@ receivers:
otlp:
protocols:
grpc:
- signalfx:
+ endpoint: 0.0.0.0:4317
+ http:
+ endpoint: 0.0.0.0:4318
exporters:
otlphttp:
@@ -12,22 +14,19 @@ exporters:
splunk_hec:
token: "${SPLUNK_ACCESS_TOKEN}"
endpoint: "https://ingest.${SPLUNK_REALM}.signalfx.com/v1/log"
- logging/debug:
- loglevel: debug
+ debug:
+ verbosity: detailed
processors:
batch:
service:
- telemetry:
- logs:
- level: "debug"
pipelines:
traces:
receivers: [otlp]
processors: [batch]
- exporters: [logging/debug, otlphttp]
+ exporters: [debug, otlphttp]
logs/profiling:
receivers: [otlp]
processors: [batch]
- exporters: [logging/debug, splunk_hec]
+ exporters: [debug, splunk_hec]
diff --git a/examples/profiling/docker-compose.yml b/examples/profiling/docker-compose.yml
index 0abccb7b..63736535 100644
--- a/examples/profiling/docker-compose.yml
+++ b/examples/profiling/docker-compose.yml
@@ -1,13 +1,11 @@
-version: "3"
services:
otel-collector:
- image: otel/opentelemetry-collector-contrib:0.50.0
+ image: quay.io/signalfx/splunk-otel-collector:0.111.0
environment:
+ - SPLUNK_CONFIG: /etc/otel/config.yml
- SPLUNK_ACCESS_TOKEN
- SPLUNK_REALM
- command: ["--config=/etc/otel-collector-config.yml"]
volumes:
- - ./collector-config.yml:/etc/otel-collector-config.yml
+ - ./collector.config.yml:/etc/otel/config.yml
ports:
- - "9943:9943" # signalfx
- - "4317:4317" # otlp
+ - "4318:4318" # otlp
diff --git a/examples/profiling/index.js b/examples/profiling/index.js
index 7a723863..705e26d8 100644
--- a/examples/profiling/index.js
+++ b/examples/profiling/index.js
@@ -1,10 +1,5 @@
const { start, stop } = require('@splunk/otel');
-const { diag, DiagConsoleLogger, DiagLogLevel, trace, context } = require('@opentelemetry/api');
-
-// If OTEL_LOG_LEVEL env var is set, configure logger
-if (process.env.OTEL_LOG_LEVEL) {
- diag.setLogger(new DiagConsoleLogger(), DiagLogLevel[process.env.OTEL_LOG_LEVEL]);
-}
+const { trace, context } = require('@opentelemetry/api');
start({
// Tracing is enabled by default and is required for profiling
@@ -21,7 +16,7 @@ const doWork = () => {
// setTimeout has to be here because profiling is currently started asyncronously to avoid blocking the runtime.
// If we didn't we'd run stop before the profiling has started in the background.
-setTimeout(() => {
+setTimeout(async () => {
const tracer = trace.getTracer('splunk-otel-example-profiling');
const span = tracer.startSpan('main');
const spanContext = trace.setSpan(context.active(), span);
@@ -34,5 +29,5 @@ setTimeout(() => {
span.end();
// Stop profiling to flush the collected samples
- stop();
+ await stop();
}, 10);
diff --git a/package-lock.json b/package-lock.json
index b9bae26f..fa9cb511 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,12 +11,12 @@
"license": "Apache-2.0",
"dependencies": {
"@grpc/grpc-js": "^1.11.1",
- "@grpc/proto-loader": "^0.7.13",
"@opentelemetry/api": "^1.8.0",
"@opentelemetry/api-logs": "^0.53.0",
"@opentelemetry/context-async-hooks": "1.26.0",
"@opentelemetry/core": "1.26.0",
"@opentelemetry/exporter-logs-otlp-http": "0.53.0",
+ "@opentelemetry/exporter-logs-otlp-proto": "0.53.0",
"@opentelemetry/exporter-metrics-otlp-grpc": "0.53.0",
"@opentelemetry/exporter-metrics-otlp-proto": "0.53.0",
"@opentelemetry/exporter-trace-otlp-grpc": "0.53.0",
@@ -2134,6 +2134,27 @@
"@opentelemetry/api": "^1.0.0"
}
},
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto": {
+ "version": "0.53.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.53.0.tgz",
+ "integrity": "sha512-jhEcVL1deeWNmTUP05UZMriZPSWUBcfg94ng7JuBb1q2NExgnADQFl1VQQ+xo62/JepK+MxQe4xAwlsDQFbISA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.53.0",
+ "@opentelemetry/core": "1.26.0",
+ "@opentelemetry/otlp-exporter-base": "0.53.0",
+ "@opentelemetry/otlp-transformer": "0.53.0",
+ "@opentelemetry/resources": "1.26.0",
+ "@opentelemetry/sdk-logs": "0.53.0",
+ "@opentelemetry/sdk-trace-base": "1.26.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
"node_modules/@opentelemetry/exporter-metrics-otlp-grpc": {
"version": "0.53.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.53.0.tgz",
@@ -9434,6 +9455,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
"integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
"dev": true,
+ "license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -11219,6 +11241,20 @@
"@opentelemetry/sdk-logs": "0.53.0"
}
},
+ "@opentelemetry/exporter-logs-otlp-proto": {
+ "version": "0.53.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.53.0.tgz",
+ "integrity": "sha512-jhEcVL1deeWNmTUP05UZMriZPSWUBcfg94ng7JuBb1q2NExgnADQFl1VQQ+xo62/JepK+MxQe4xAwlsDQFbISA==",
+ "requires": {
+ "@opentelemetry/api-logs": "0.53.0",
+ "@opentelemetry/core": "1.26.0",
+ "@opentelemetry/otlp-exporter-base": "0.53.0",
+ "@opentelemetry/otlp-transformer": "0.53.0",
+ "@opentelemetry/resources": "1.26.0",
+ "@opentelemetry/sdk-logs": "0.53.0",
+ "@opentelemetry/sdk-trace-base": "1.26.0"
+ }
+ },
"@opentelemetry/exporter-metrics-otlp-grpc": {
"version": "0.53.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.53.0.tgz",
diff --git a/package.json b/package.json
index 6d411065..b6275a00 100644
--- a/package.json
+++ b/package.json
@@ -93,12 +93,12 @@
},
"dependencies": {
"@grpc/grpc-js": "^1.11.1",
- "@grpc/proto-loader": "^0.7.13",
"@opentelemetry/api": "^1.8.0",
"@opentelemetry/api-logs": "^0.53.0",
"@opentelemetry/context-async-hooks": "1.26.0",
"@opentelemetry/core": "1.26.0",
"@opentelemetry/exporter-logs-otlp-http": "0.53.0",
+ "@opentelemetry/exporter-logs-otlp-proto": "0.53.0",
"@opentelemetry/exporter-metrics-otlp-grpc": "0.53.0",
"@opentelemetry/exporter-metrics-otlp-proto": "0.53.0",
"@opentelemetry/exporter-trace-otlp-grpc": "0.53.0",
diff --git a/src/metrics/index.ts b/src/metrics/index.ts
index 4bbd8d28..f1a81198 100644
--- a/src/metrics/index.ts
+++ b/src/metrics/index.ts
@@ -158,7 +158,7 @@ export function createOtlpExporter(options: MetricsOptions) {
}
}
- protocol = protocol ?? 'grpc';
+ protocol = protocol ?? 'http/protobuf';
switch (protocol) {
case 'grpc': {
diff --git a/src/profiling/OTLPProfilingExporter.ts b/src/profiling/OTLPProfilingExporter.ts
deleted file mode 100644
index 570a6ec9..00000000
--- a/src/profiling/OTLPProfilingExporter.ts
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright Splunk Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import * as protoLoader from '@grpc/proto-loader';
-import type * as grpc from '@grpc/grpc-js';
-import * as path from 'path';
-import {
- CpuProfile,
- HeapProfile,
- ProfilingExporter,
- ProfilingStacktrace,
-} from './types';
-import { diag } from '@opentelemetry/api';
-import { Resource } from '@opentelemetry/resources';
-import { VERSION } from '@opentelemetry/core';
-import {
- ATTR_TELEMETRY_SDK_LANGUAGE,
- ATTR_TELEMETRY_SDK_VERSION,
-} from '@opentelemetry/semantic-conventions';
-import {
- parseEndpoint,
- serialize,
- serializeHeapProfile,
- encode,
-} from './utils';
-
-export interface OTLPExporterOptions {
- callstackInterval: number;
- endpoint: string;
- resource: Resource;
-}
-
-interface LogsClient extends grpc.Client {
- export: (
- request: unknown,
- metadata: grpc.Metadata,
- callback: Function
- ) => void;
-}
-
-const OTEL_PROFILING_VERSION = '0.1.0';
-
-function commonAttributes(
- profilingType: 'cpu' | 'allocation',
- sampleCount: number
-) {
- return [
- {
- key: 'profiling.data.format',
- value: { stringValue: 'pprof-gzip-base64' },
- },
- {
- key: 'profiling.data.type',
- value: { stringValue: profilingType },
- },
- {
- key: 'com.splunk.sourcetype',
- value: { stringValue: 'otel.profiling' },
- },
- {
- key: 'profiling.data.total.frame.count',
- value: { intValue: sampleCount },
- },
- ];
-}
-
-function countSamples(stacktraces: ProfilingStacktrace[]) {
- let sampleCount = 0;
-
- for (const profilingStacktrace of stacktraces) {
- sampleCount += profilingStacktrace.stacktrace.length;
- }
-
- return sampleCount;
-}
-
-export class OTLPProfilingExporter implements ProfilingExporter {
- protected _client: LogsClient;
- protected _options: OTLPExporterOptions;
- protected _resourceAttributes;
- protected _grpc: typeof grpc;
-
- constructor(options: OTLPExporterOptions) {
- this._options = options;
- const protosDir = path.resolve(__dirname, '..', '..', 'protos');
- const packageDef = protoLoader.loadSync(
- path.join(
- protosDir,
- 'opentelemetry/proto/collector/logs/v1/logs_service.proto'
- ),
- {
- keepCase: false,
- longs: String,
- enums: String,
- defaults: true,
- oneofs: true,
- includeDirs: [protosDir],
- }
- );
-
- this._grpc = require('@grpc/grpc-js');
- const { host, credentials } = parseEndpoint(options.endpoint, this._grpc);
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const packageObject: any = this._grpc.loadPackageDefinition(packageDef);
- this._client =
- new packageObject.opentelemetry.proto.collector.logs.v1.LogsService(
- host,
- credentials
- );
-
- const resource = new Resource({
- [ATTR_TELEMETRY_SDK_LANGUAGE]: 'node',
- [ATTR_TELEMETRY_SDK_VERSION]: VERSION,
- }).merge(options.resource);
-
- this._resourceAttributes = [];
- for (const key in resource.attributes) {
- const value = resource.attributes[key];
-
- if (typeof value === 'string') {
- this._resourceAttributes.push({
- key,
- value: { stringValue: value },
- });
- } else if (typeof value === 'number') {
- if (Number.isInteger(value)) {
- this._resourceAttributes.push({
- key,
- value: { intValue: value },
- });
- } else {
- this._resourceAttributes.push({
- key,
- value: { doubleValue: value },
- });
- }
- } else {
- this._resourceAttributes.push({
- key,
- value: { boolValue: value },
- });
- }
- }
- }
-
- send(profile: CpuProfile) {
- const { stacktraces } = profile;
-
- const sampleCount = countSamples(stacktraces);
-
- diag.debug(`profiling: Exporting ${sampleCount} CPU samples`);
- const { callstackInterval } = this._options;
- const attributes = commonAttributes('cpu', sampleCount);
- encode(serialize(profile, { samplingPeriodMillis: callstackInterval }))
- .then((serializedProfile) => {
- const logs = [serializedProfile].map((st) => {
- return {
- name: 'otel.profiling',
- body: { stringValue: st.toString('base64') },
- attributes,
- };
- });
- const ilLogs = {
- instrumentationLibrary: {
- name: 'otel.profiling',
- version: OTEL_PROFILING_VERSION,
- },
- logs,
- };
- const resourceLogs = [
- {
- resource: {
- attributes: this._resourceAttributes,
- },
- instrumentationLibraryLogs: [ilLogs],
- },
- ];
- const payload = {
- resourceLogs,
- };
- this._client.export(
- payload,
- new this._grpc.Metadata(),
- (err: unknown) => {
- if (err) {
- diag.error('Error exporting profiling data', err);
- }
- }
- );
- })
- .catch((err: unknown) => {
- diag.error('Error exporting profiling data', err);
- });
- }
-
- sendHeapProfile(profile: HeapProfile) {
- const serialized = serializeHeapProfile(profile);
- const sampleCount = profile.samples.length;
- const attributes = commonAttributes('allocation', sampleCount);
- diag.debug(`profiling: Exporting ${sampleCount} heap samples`);
- encode(serialized)
- .then((serializedProfile) => {
- const logs = [serializedProfile].map((st) => {
- return {
- name: 'otel.profiling',
- body: { stringValue: st.toString('base64') },
- attributes,
- };
- });
- const ilLogs = {
- instrumentationLibrary: {
- name: 'otel.profiling',
- version: OTEL_PROFILING_VERSION,
- },
- logs,
- };
- const resourceLogs = [
- {
- resource: {
- attributes: this._resourceAttributes,
- },
- instrumentationLibraryLogs: [ilLogs],
- },
- ];
- const payload = {
- resourceLogs,
- };
- this._client.export(
- payload,
- new this._grpc.Metadata(),
- (err: unknown) => {
- if (err) {
- diag.error('Error exporting profiling data', err);
- }
- }
- );
- })
- .catch((err: unknown) => {
- diag.error('Error exporting profiling data', err);
- });
- }
-}
diff --git a/src/profiling/OtlpHttpProfilingExporter.ts b/src/profiling/OtlpHttpProfilingExporter.ts
new file mode 100644
index 00000000..b8879ff0
--- /dev/null
+++ b/src/profiling/OtlpHttpProfilingExporter.ts
@@ -0,0 +1,185 @@
+/*
+ * Copyright Splunk Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {
+ CpuProfile,
+ HeapProfile,
+ ProfilingExporter,
+ ProfilingStacktrace,
+} from './types';
+import { context, diag } from '@opentelemetry/api';
+import { Resource } from '@opentelemetry/resources';
+import {
+ hrTime,
+ InstrumentationScope,
+ suppressTracing,
+} from '@opentelemetry/core';
+import type { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-proto';
+import { VERSION } from '@opentelemetry/core';
+import {
+ ATTR_TELEMETRY_SDK_LANGUAGE,
+ ATTR_TELEMETRY_SDK_VERSION,
+} from '@opentelemetry/semantic-conventions';
+import { serialize, serializeHeapProfile, encode } from './utils';
+import { ReadableLogRecord } from '@opentelemetry/sdk-logs';
+
+export interface ExporterOptions {
+ callstackInterval: number;
+ endpoint: string;
+ resource: Resource;
+}
+
+function countSamples(stacktraces: ProfilingStacktrace[]) {
+ let sampleCount = 0;
+
+ for (const profilingStacktrace of stacktraces) {
+ sampleCount += profilingStacktrace.stacktrace.length;
+ }
+
+ return sampleCount;
+}
+
+function commonAttributes(
+ profilingType: 'cpu' | 'allocation',
+ sampleCount: number
+) {
+ return {
+ 'profiling.data.format': 'pprof-gzip-base64',
+ 'profiling.data.type': profilingType,
+ 'com.splunk.sourcetype': 'otel.profiling',
+ 'profiling.data.total.frame.count': sampleCount,
+ };
+}
+
+function createEndpoint(endpoint: string) {
+ if (endpoint.includes('/v1/logs')) {
+ return endpoint;
+ }
+
+ return new URL('/v1/logs', endpoint).href;
+}
+
+const OTEL_PROFILING_VERSION = '0.1.0';
+
+export class OtlpHttpProfilingExporter implements ProfilingExporter {
+ _callstackInterval: number;
+ _endpoint: string;
+ _exporter: OTLPLogExporter | undefined;
+ _resource: Resource;
+ _scope: InstrumentationScope;
+
+ constructor(options: ExporterOptions) {
+ this._callstackInterval = options.callstackInterval;
+ this._endpoint = createEndpoint(options.endpoint);
+ this._resource = new Resource({
+ [ATTR_TELEMETRY_SDK_LANGUAGE]: 'node',
+ [ATTR_TELEMETRY_SDK_VERSION]: VERSION,
+ }).merge(options.resource);
+
+ this._scope = {
+ name: 'otel.profiling',
+ version: OTEL_PROFILING_VERSION,
+ };
+ }
+
+ async send(profile: CpuProfile) {
+ const { stacktraces } = profile;
+
+ const sampleCount = countSamples(stacktraces);
+
+ diag.debug(`profiling: Exporting ${sampleCount} CPU samples`);
+ const attributes = commonAttributes('cpu', sampleCount);
+
+ return encode(
+ serialize(profile, { samplingPeriodMillis: this._callstackInterval })
+ )
+ .then((serializedProfile) => {
+ const ts = hrTime();
+
+ const logs: ReadableLogRecord[] = [
+ {
+ hrTime: ts,
+ hrTimeObserved: ts,
+ body: serializedProfile.toString('base64'),
+ resource: this._resource,
+ instrumentationScope: this._scope,
+ attributes,
+ droppedAttributesCount: 0,
+ },
+ ];
+
+ context.with(suppressTracing(context.active()), () => {
+ this._getExporter().export(logs, (result) => {
+ if (result.error !== undefined) {
+ diag.error('Error exporting profiling data', result.error);
+ }
+ });
+ });
+ })
+ .catch((err: unknown) => {
+ diag.error('Error encoding cpu profile', err);
+ });
+ }
+
+ async sendHeapProfile(profile: HeapProfile) {
+ const serialized = serializeHeapProfile(profile);
+ const sampleCount = profile.samples.length;
+ const attributes = commonAttributes('allocation', sampleCount);
+ diag.debug(`profiling: Exporting ${sampleCount} heap samples`);
+ return encode(serialized)
+ .then((serializedProfile) => {
+ const ts = hrTime();
+
+ const logs: ReadableLogRecord[] = [
+ {
+ hrTime: ts,
+ hrTimeObserved: ts,
+ body: serializedProfile.toString('base64'),
+ resource: this._resource,
+ instrumentationScope: this._scope,
+ attributes,
+ droppedAttributesCount: 0,
+ },
+ ];
+
+ context.with(suppressTracing(context.active()), () => {
+ this._getExporter().export(logs, (result) => {
+ if (result.error !== undefined) {
+ diag.error('Error exporting profiling data', result.error);
+ }
+ });
+ });
+ })
+ .catch((err: unknown) => {
+ diag.error('Error encoding heap profile', err);
+ });
+ }
+
+ _getExporter(): OTLPLogExporter {
+ if (this._exporter !== undefined) {
+ return this._exporter;
+ }
+
+ const {
+ OTLPLogExporter,
+ } = require('@opentelemetry/exporter-logs-otlp-proto');
+
+ this._exporter = new OTLPLogExporter({
+ url: this._endpoint,
+ });
+
+ return this._exporter!;
+ }
+}
diff --git a/src/profiling/index.ts b/src/profiling/index.ts
index a54b56c4..42bb73bf 100644
--- a/src/profiling/index.ts
+++ b/src/profiling/index.ts
@@ -27,7 +27,7 @@ import {
recordHeapProfilerMetrics,
} from '../metrics/debug_metrics';
import { detect as detectResource } from '../resource';
-import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
+import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
import {
HeapProfile,
MemoryProfilingOptions,
@@ -38,7 +38,7 @@ import {
ProfilingStartOptions,
} from './types';
import { ProfilingContextManager } from './ProfilingContextManager';
-import { OTLPProfilingExporter } from './OTLPProfilingExporter';
+import { OtlpHttpProfilingExporter } from './OtlpHttpProfilingExporter';
import { isTracingContextManagerEnabled } from '../tracing';
export { StartProfilingOptions };
@@ -83,7 +83,7 @@ export function defaultExporterFactory(
options: ProfilingOptions
): ProfilingExporter[] {
const exporters: ProfilingExporter[] = [
- new OTLPProfilingExporter({
+ new OtlpHttpProfilingExporter({
endpoint: options.endpoint,
callstackInterval: options.callstackInterval,
resource: options.resource,
@@ -104,7 +104,7 @@ export function startProfiling(options: ProfilingOptions) {
if (extension === undefined) {
return {
- stop: () => {},
+ stop: async () => {},
};
}
@@ -169,7 +169,7 @@ export function startProfiling(options: ProfilingOptions) {
});
return {
- stop: () => {
+ stop: async () => {
if (options.memoryProfilingEnabled) {
clearInterval(memSamplesCollectInterval);
extStopMemoryProfiling(extension);
@@ -179,9 +179,17 @@ export function startProfiling(options: ProfilingOptions) {
const cpuProfile = extStopProfiling(extension);
if (cpuProfile) {
- for (const exporter of exporters) {
- exporter.send(cpuProfile);
- }
+ const sends = exporters.map((e) => e.send(cpuProfile));
+ await Promise.allSettled(sends).then((results) => {
+ for (const result of results) {
+ if (result.status === 'rejected') {
+ diag.error(
+ 'Failed sending CPU profile on shutdown',
+ result.reason
+ );
+ }
+ }
+ });
}
},
};
@@ -208,14 +216,14 @@ export function _setDefaultOptions(
options.endpoint ||
getNonEmptyEnvVar('SPLUNK_PROFILER_LOGS_ENDPOINT') ||
getNonEmptyEnvVar('OTEL_EXPORTER_OTLP_ENDPOINT') ||
- 'http://localhost:4317';
+ 'http://localhost:4318';
const combinedResource = detectResource();
const serviceName = String(
options.serviceName ||
getNonEmptyEnvVar('OTEL_SERVICE_NAME') ||
- combinedResource.attributes[SemanticResourceAttributes.SERVICE_NAME] ||
+ combinedResource.attributes[ATTR_SERVICE_NAME] ||
defaultServiceName()
);
@@ -226,7 +234,7 @@ export function _setDefaultOptions(
resource = resource.merge(
new Resource({
- [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
+ [ATTR_SERVICE_NAME]: serviceName,
})
);
diff --git a/src/profiling/types.ts b/src/profiling/types.ts
index 5f9fa099..5c3b86d1 100644
--- a/src/profiling/types.ts
+++ b/src/profiling/types.ts
@@ -105,8 +105,8 @@ export interface ProfilingOptions {
export type StartProfilingOptions = Partial;
export interface ProfilingExporter {
- send(profile: CpuProfile): void;
- sendHeapProfile(profile: HeapProfile): void;
+ send(profile: CpuProfile): Promise;
+ sendHeapProfile(profile: HeapProfile): Promise;
}
export const allowedProfilingOptions = [
diff --git a/src/profiling/utils.ts b/src/profiling/utils.ts
index 763a3a86..389a9703 100644
--- a/src/profiling/utils.ts
+++ b/src/profiling/utils.ts
@@ -13,12 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import * as fs from 'fs';
import { gzip } from 'zlib';
import { promisify } from 'util';
-import type * as GrpcModule from '@grpc/grpc-js';
-import { diag } from '@opentelemetry/api';
-import { getNonEmptyEnvVar } from '../utils';
import { perftools } from './proto/profile';
import type { CpuProfile, HeapProfile } from './types';
@@ -220,48 +216,3 @@ export const encode = async function encode(
const buffer = perftools.profiles.Profile.encode(profile).finish();
return gzipPromise(buffer);
};
-
-function readContentSync(location: string): Buffer | undefined {
- try {
- return fs.readFileSync(location);
- } catch (e) {
- diag.error(`Failed to read file at ${location}`, e);
- }
-
- return undefined;
-}
-
-function maybeReadPath(location: string | undefined): Buffer | undefined {
- if (location === undefined) {
- return undefined;
- }
-
- return readContentSync(location);
-}
-
-export function parseEndpoint(
- endpoint: string,
- grpc: typeof GrpcModule
-): {
- host: string;
- credentials: GrpcModule.ChannelCredentials;
-} {
- let host = endpoint;
- let credentials = grpc.ChannelCredentials.createInsecure();
-
- if (endpoint.startsWith('https://')) {
- host = endpoint.substr(8);
- credentials = grpc.credentials.createSsl(
- maybeReadPath(getNonEmptyEnvVar('OTEL_EXPORTER_OTLP_CERTIFICATE')),
- maybeReadPath(getNonEmptyEnvVar('OTEL_EXPORTER_OTLP_CLIENT_KEY')),
- maybeReadPath(getNonEmptyEnvVar('OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE'))
- );
- } else if (endpoint.startsWith('http://')) {
- host = endpoint.substr(7);
- }
-
- return {
- host,
- credentials,
- };
-}
diff --git a/src/start.ts b/src/start.ts
index feef7521..c8d9bf00 100644
--- a/src/start.ts
+++ b/src/start.ts
@@ -166,12 +166,7 @@ export const stop = async () => {
}
if (running.profiling) {
- promises.push(
- new Promise((resolve) => {
- running.profiling!.stop();
- resolve();
- })
- );
+ promises.push(promises.push(running.profiling!.stop()));
running.profiling = null;
}
diff --git a/src/tracing/options.ts b/src/tracing/options.ts
index ebdd9458..000ad42d 100644
--- a/src/tracing/options.ts
+++ b/src/tracing/options.ts
@@ -254,12 +254,7 @@ export function otlpSpanExporterFactory(options: Options): SpanExporter {
'OTEL_EXPORTER_OTLP_PROTOCOL',
]);
- let endpoint =
- options.endpoint ??
- getEnvValueByPrecedence([
- 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT',
- 'OTEL_EXPORTER_OTLP_ENDPOINT',
- ]);
+ let endpoint = options.endpoint;
const accessToken = options.accessToken;
@@ -270,7 +265,12 @@ export function otlpSpanExporterFactory(options: Options): SpanExporter {
);
}
- if (endpoint === undefined) {
+ const envEndpoint = getEnvValueByPrecedence([
+ 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT',
+ 'OTEL_EXPORTER_OTLP_ENDPOINT',
+ ]);
+
+ if (endpoint === undefined && envEndpoint === undefined) {
endpoint = `https://ingest.${options.realm}.signalfx.com/v2/trace/otlp`;
protocol = 'http/protobuf';
} else {
@@ -280,7 +280,7 @@ export function otlpSpanExporterFactory(options: Options): SpanExporter {
}
}
- protocol = protocol ?? 'grpc';
+ protocol = protocol ?? 'http/protobuf';
switch (protocol) {
case 'grpc': {
@@ -341,7 +341,7 @@ export function defaultSpanProcessorFactory(options: Options): SpanProcessor[] {
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
-export function defaultPropagatorFactory(options: Options): TextMapPropagator {
+export function defaultPropagatorFactory(_options: Options): TextMapPropagator {
const envPropagators = getEnvArray('OTEL_PROPAGATORS', [
'tracecontext',
'baggage',
diff --git a/test/examples/Dockerfile_app b/test/examples/Dockerfile_app
index 298fb374..9fa8c16e 100644
--- a/test/examples/Dockerfile_app
+++ b/test/examples/Dockerfile_app
@@ -1,5 +1,5 @@
# Set up the environment, install deps
-FROM node:18-alpine as base
+FROM node:20-alpine AS base
RUN apk add g++ make python3
USER node
@@ -21,7 +21,7 @@ COPY --chown=node:node ./ .
# Install deps for examples
-FROM base as published
+FROM base AS published
RUN ./scripts/examples-npm-install
@@ -31,7 +31,7 @@ CMD ["npm", "run", "start"]
# Compile the package and use it in examples
-FROM published as compiled
+FROM published AS compiled
# use a single prebuild for tests so we don't have to compile it each install
RUN npm run prebuild:current
diff --git a/test/examples/basic/app.env b/test/examples/basic/app.env
index 2eb7a682..7c5f5b0e 100644
--- a/test/examples/basic/app.env
+++ b/test/examples/basic/app.env
@@ -2,4 +2,4 @@ PORT=80
OTEL_SERVICE_NAME='basic-example'
OTEL_RESOURCE_ATTRIBUTES='deployment.environment=dev'
OTEL_LOG_LEVEL='DEBUG'
-OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317
+OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318
diff --git a/test/examples/basic/snapshot.js b/test/examples/basic/snapshot.js
index cc9459d7..7fadc910 100644
--- a/test/examples/basic/snapshot.js
+++ b/test/examples/basic/snapshot.js
@@ -1,50 +1,18 @@
// a console.log from a previous run
module.exports = [
{
- traceId: '/9GShGd4h/tJ1Yei1rzV8A==',
- id: '2PYWumUB8/Q=',
- startTime: '2022-10-27T15:28:23.685136896Z',
- name: 'GET /hello',
- kind: 'server',
- parentSpanId: undefined,
- parent: undefined,
- references: undefined,
- status: { code: undefined },
- attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-http',
- 'otel.library.version': '0.33.0',
- 'http.url': 'http://app/hello',
- 'http.host': 'app',
- 'net.host.name': 'app',
- 'http.method': 'GET',
- 'http.scheme': 'http',
- 'http.target': '/hello',
- 'http.user_agent': 'got (https://github.com/sindresorhus/got)',
- 'http.flavor': '1.1',
- 'net.transport': 'ip_tcp',
- 'net.host.ip': '::ffff:0.0.0.0',
- 'net.host.port': undefined,
- 'net.peer.ip': '::ffff:0.0.0.0',
- 'net.peer.port': undefined,
- 'http.status_code': undefined,
- 'http.status_text': 'CREATED',
- 'http.route': '/hello',
- 'span.kind': 'server'
- }
- },
- {
- traceId: '/9GShGd4h/tJ1Yei1rzV8A==',
- id: 'aBuv7mmBta4=',
- startTime: '2022-10-27T15:28:23.696763904Z',
+ traceId: 'LAWqC9bxJ/QJ4eXmjf6wpQ==',
+ id: '7D4S0IHq48A=',
+ startTime: '2024-10-23T11:49:39.286Z',
+ hrStartTime: 1729684179286000000n,
name: 'middleware - query',
kind: 'internal',
- parentSpanId: '2PYWumUB8/Q=',
- parent: { id: '2PYWumUB8/Q=', traceId: '/9GShGd4h/tJ1Yei1rzV8A==' },
- references: [],
+ parentSpanId: 'KUT43ADmiVo=',
+ parent: { id: 'KUT43ADmiVo=', traceId: 'LAWqC9bxJ/QJ4eXmjf6wpQ==' },
status: { code: undefined },
attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-express',
- 'otel.library.version': '0.31.2',
+ 'otel.scope.name': '@opentelemetry/instrumentation-express',
+ 'otel.scope.version': '0.42.0',
'http.route': '/',
'express.name': 'query',
'express.type': 'middleware',
@@ -52,18 +20,18 @@ module.exports = [
}
},
{
- traceId: '/9GShGd4h/tJ1Yei1rzV8A==',
- id: 'ijCrFyvrC5A=',
- startTime: '2022-10-27T15:28:23.699226624Z',
+ traceId: 'LAWqC9bxJ/QJ4eXmjf6wpQ==',
+ id: 'lcfZ8FvVJJ8=',
+ startTime: '2024-10-23T11:49:39.291Z',
+ hrStartTime: 1729684179291000000n,
name: 'middleware - expressInit',
kind: 'internal',
- parentSpanId: '2PYWumUB8/Q=',
- parent: { id: '2PYWumUB8/Q=', traceId: '/9GShGd4h/tJ1Yei1rzV8A==' },
- references: [],
+ parentSpanId: 'KUT43ADmiVo=',
+ parent: { id: 'KUT43ADmiVo=', traceId: 'LAWqC9bxJ/QJ4eXmjf6wpQ==' },
status: { code: undefined },
attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-express',
- 'otel.library.version': '0.31.2',
+ 'otel.scope.name': '@opentelemetry/instrumentation-express',
+ 'otel.scope.version': '0.42.0',
'http.route': '/',
'express.name': 'expressInit',
'express.type': 'middleware',
@@ -71,18 +39,18 @@ module.exports = [
}
},
{
- traceId: '/9GShGd4h/tJ1Yei1rzV8A==',
- id: 'nUmcea9N0DM=',
- startTime: '2022-10-27T15:28:23.700294656Z',
+ traceId: 'LAWqC9bxJ/QJ4eXmjf6wpQ==',
+ id: '6TdoTvXE+I4=',
+ startTime: '2024-10-23T11:49:39.293Z',
+ hrStartTime: 1729684179293000000n,
name: 'request handler - /hello',
kind: 'internal',
- parentSpanId: '2PYWumUB8/Q=',
- parent: { id: '2PYWumUB8/Q=', traceId: '/9GShGd4h/tJ1Yei1rzV8A==' },
- references: [],
+ parentSpanId: 'KUT43ADmiVo=',
+ parent: { id: 'KUT43ADmiVo=', traceId: 'LAWqC9bxJ/QJ4eXmjf6wpQ==' },
status: { code: undefined },
attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-express',
- 'otel.library.version': '0.31.2',
+ 'otel.scope.name': '@opentelemetry/instrumentation-express',
+ 'otel.scope.version': '0.42.0',
'http.route': '/hello',
'express.name': '/hello',
'express.type': 'request_handler',
@@ -90,18 +58,50 @@ module.exports = [
}
},
{
- traceId: '/9GShGd4h/tJ1Yei1rzV8A==',
- id: 'ugJHEI0w8TA=',
- startTime: '2022-10-27T15:28:23.700867328Z',
+ traceId: 'LAWqC9bxJ/QJ4eXmjf6wpQ==',
+ id: '1Al/kbAgRyM=',
+ startTime: '2024-10-23T11:49:39.294Z',
+ hrStartTime: 1729684179294000000n,
name: 'hello',
kind: 'internal',
- parentSpanId: '2PYWumUB8/Q=',
- parent: { id: '2PYWumUB8/Q=', traceId: '/9GShGd4h/tJ1Yei1rzV8A==' },
- references: [],
+ parentSpanId: 'KUT43ADmiVo=',
+ parent: { id: 'KUT43ADmiVo=', traceId: 'LAWqC9bxJ/QJ4eXmjf6wpQ==' },
status: { code: undefined },
attributes: {
- 'otel.library.name': 'splunk-otel-example-basic',
+ 'otel.scope.name': 'splunk-otel-example-basic',
'span.kind': 'internal'
}
+ },
+ {
+ traceId: 'LAWqC9bxJ/QJ4eXmjf6wpQ==',
+ id: 'KUT43ADmiVo=',
+ startTime: '2024-10-23T11:49:39.271Z',
+ hrStartTime: 1729684179271000000n,
+ name: 'GET /hello',
+ kind: 'server',
+ parentSpanId: undefined,
+ parent: undefined,
+ status: { code: undefined },
+ attributes: {
+ 'otel.scope.name': '@opentelemetry/instrumentation-http',
+ 'otel.scope.version': '0.53.0',
+ 'http.url': 'http://app/hello',
+ 'http.host': 'app',
+ 'net.host.name': 'app',
+ 'http.method': 'GET',
+ 'http.scheme': 'http',
+ 'http.target': '/hello',
+ 'http.user_agent': 'node',
+ 'http.flavor': '1.1',
+ 'net.transport': 'ip_tcp',
+ 'net.host.ip': '::ffff:172.18.0.3',
+ 'net.host.port': undefined,
+ 'net.peer.ip': '::ffff:172.18.0.4',
+ 'net.peer.port': undefined,
+ 'http.status_code': undefined,
+ 'http.status_text': 'CREATED',
+ 'http.route': '/hello',
+ 'span.kind': 'server'
+ }
}
];
diff --git a/test/examples/collector.config.yml b/test/examples/collector.config.yml
index 58951c57..f8608f9e 100644
--- a/test/examples/collector.config.yml
+++ b/test/examples/collector.config.yml
@@ -13,17 +13,17 @@ exporters:
logging:
httpsink:
endpoint: 0.0.0.0:8378
- logging/debug:
- loglevel: debug
+ debug:
+ verbosity: detailed
service:
pipelines:
traces:
receivers: [otlp]
- exporters: [httpsink, logging/debug]
+ exporters: [httpsink, debug]
metrics:
receivers: [otlp]
- exporters: [logging/debug]
+ exporters: [debug]
logs/profiling:
receivers: [otlp]
- exporters: [logging/debug]
+ exporters: [debug]
diff --git a/test/examples/e2e.docker-compose.yml b/test/examples/e2e.docker-compose.yml
index 0abfd784..f9f7f8da 100644
--- a/test/examples/e2e.docker-compose.yml
+++ b/test/examples/e2e.docker-compose.yml
@@ -1,7 +1,6 @@
-version: '3.4'
services:
collector:
- image: quay.io/signalfx/splunk-otel-collector:0.50.1
+ image: quay.io/signalfx/splunk-otel-collector:0.111.0
environment:
SPLUNK_CONFIG: /etc/otel/config.yml
volumes:
@@ -21,7 +20,7 @@ services:
command: node ./basic
environment:
REQ_URL: http://app/hello
- COLLECTOR_URL: http://collector:8378
+ COLLECTOR_URL: http://collector:8378/spans
depends_on:
- app
- collector
diff --git a/test/examples/express.override.yml b/test/examples/express.override.yml
index 972b311a..b24d520a 100644
--- a/test/examples/express.override.yml
+++ b/test/examples/express.override.yml
@@ -8,7 +8,7 @@ services:
command: node ./express
environment:
REQ_URL: http://app/animal
- COLLECTOR_URL: http://collector:8378
+ COLLECTOR_URL: http://collector:8378/spans
depends_on:
- app
- collector
diff --git a/test/examples/express/app.env b/test/examples/express/app.env
index 8a46777c..897622e3 100644
--- a/test/examples/express/app.env
+++ b/test/examples/express/app.env
@@ -2,4 +2,4 @@ PORT=80
OTEL_SERVICE_NAME='express-example'
OTEL_RESOURCE_ATTRIBUTES='deployment.environment=dev'
OTEL_LOG_LEVEL='DEBUG'
-OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317
+OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318
diff --git a/test/examples/express/snapshot.js b/test/examples/express/snapshot.js
index a20966cc..707add8a 100644
--- a/test/examples/express/snapshot.js
+++ b/test/examples/express/snapshot.js
@@ -1,247 +1,230 @@
module.exports = [
- {
- traceId: 'OsUGTyjZAT95YozWxOQrKg==',
- id: 'GexzSLvMxM0=',
- startTime: '2023-07-25T14:50:08.443000064Z',
- hrStartTime: 1690296608443000064n,
- name: 'middleware - query',
- kind: 'internal',
- parentSpanId: 'kOYrlY2RC3c=',
- parent: { id: 'kOYrlY2RC3c=', traceId: 'OsUGTyjZAT95YozWxOQrKg==' },
- status: { code: undefined },
- attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-express',
- 'otel.library.version': '0.33.0',
- 'http.route': '/',
- 'express.name': 'query',
- 'express.type': 'middleware',
- 'span.kind': 'internal'
- }
- },
- {
- traceId: 'OsUGTyjZAT95YozWxOQrKg==',
- id: '/S0ovsDo2Qw=',
- startTime: '2023-07-25T14:50:08.444999936Z',
- hrStartTime: 1690296608444999936n,
- name: 'middleware - expressInit',
- kind: 'internal',
- parentSpanId: 'kOYrlY2RC3c=',
- parent: { id: 'kOYrlY2RC3c=', traceId: 'OsUGTyjZAT95YozWxOQrKg==' },
- status: { code: undefined },
- attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-express',
- 'otel.library.version': '0.33.0',
- 'http.route': '/',
- 'express.name': 'expressInit',
- 'express.type': 'middleware',
- 'span.kind': 'internal'
- }
- },
- {
- traceId: 'OsUGTyjZAT95YozWxOQrKg==',
- id: 'HxX0RVOv3Rg=',
- startTime: '2023-07-25T14:50:08.446000128Z',
- hrStartTime: 1690296608446000128n,
- name: 'request handler - /animal',
- kind: 'internal',
- parentSpanId: 'kOYrlY2RC3c=',
- parent: { id: 'kOYrlY2RC3c=', traceId: 'OsUGTyjZAT95YozWxOQrKg==' },
- status: { code: undefined },
- attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-express',
- 'otel.library.version': '0.33.0',
- 'http.route': '/animal',
- 'express.name': '/animal',
- 'express.type': 'request_handler',
- 'span.kind': 'internal'
- }
- },
- {
- traceId: 'OsUGTyjZAT95YozWxOQrKg==',
- id: '0KVEUJRmGY8=',
- startTime: '2023-07-25T14:50:08.473999872Z',
- hrStartTime: 1690296608473999872n,
- name: 'middleware - query',
- kind: 'internal',
- parentSpanId: 'e5HVooMVkp4=',
- parent: { id: 'e5HVooMVkp4=', traceId: 'OsUGTyjZAT95YozWxOQrKg==' },
- status: { code: undefined },
- attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-express',
- 'otel.library.version': '0.33.0',
- 'http.route': '/',
- 'express.name': 'query',
- 'express.type': 'middleware',
- 'span.kind': 'internal'
- }
- },
- {
- traceId: 'OsUGTyjZAT95YozWxOQrKg==',
- id: 'qWoD2x6i4Ec=',
- startTime: '2023-07-25T14:50:08.473999872Z',
- hrStartTime: 1690296608473999872n,
- name: 'middleware - expressInit',
- kind: 'internal',
- parentSpanId: 'e5HVooMVkp4=',
- parent: { id: 'e5HVooMVkp4=', traceId: 'OsUGTyjZAT95YozWxOQrKg==' },
- status: { code: undefined },
- attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-express',
- 'otel.library.version': '0.33.0',
- 'http.route': '/',
- 'express.name': 'expressInit',
- 'express.type': 'middleware',
- 'span.kind': 'internal'
- }
- },
- {
- traceId: 'OsUGTyjZAT95YozWxOQrKg==',
- id: 'DMajdvSLIc0=',
- startTime: '2023-07-25T14:50:08.475000064Z',
- hrStartTime: 1690296608475000064n,
- name: 'request handler - /name',
- kind: 'internal',
- parentSpanId: 'e5HVooMVkp4=',
- parent: { id: 'e5HVooMVkp4=', traceId: 'OsUGTyjZAT95YozWxOQrKg==' },
- status: { code: undefined },
- attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-express',
- 'otel.library.version': '0.33.0',
- 'http.route': '/name',
- 'express.name': '/name',
- 'express.type': 'request_handler',
- 'span.kind': 'internal'
- }
- },
- {
- traceId: 'OsUGTyjZAT95YozWxOQrKg==',
- id: 'HTx7BLfkGIQ=',
- startTime: '2023-07-25T14:50:08.465999872Z',
- hrStartTime: 1690296608465999872n,
- name: 'dns.lookup',
- kind: 'client',
- parentSpanId: 'zOH1AFRxX5Y=',
- parent: { id: 'zOH1AFRxX5Y=', traceId: 'OsUGTyjZAT95YozWxOQrKg==' },
- status: { code: undefined },
- attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-dns',
- 'otel.library.version': '0.32.0',
- 'peer.ipv4': '127.0.0.1',
- 'span.kind': 'client'
- }
- },
- {
- traceId: 'OsUGTyjZAT95YozWxOQrKg==',
- id: 'd+593ui8uZY=',
- startTime: '2023-07-25T14:50:08.464999936Z',
- hrStartTime: 1690296608464999936n,
- name: 'tcp.connect',
- kind: 'internal',
- parentSpanId: 'zOH1AFRxX5Y=',
- parent: { id: 'zOH1AFRxX5Y=', traceId: 'OsUGTyjZAT95YozWxOQrKg==' },
- status: { code: undefined },
- attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-net',
- 'otel.library.version': '0.32.0',
- 'net.transport': 'ip_tcp',
- 'net.peer.name': 'localhost',
- 'net.peer.port': '80',
- 'net.peer.ip': '127.0.0.1',
- 'net.host.ip': '127.0.0.1',
- 'net.host.port': undefined,
- 'span.kind': 'internal'
- }
- },
- {
- traceId: 'OsUGTyjZAT95YozWxOQrKg==',
- id: 'e5HVooMVkp4=',
- startTime: '2023-07-25T14:50:08.473999872Z',
- hrStartTime: 1690296608473999872n,
- name: 'GET /name',
- kind: 'server',
- parentSpanId: 'zOH1AFRxX5Y=',
- parent: { id: 'zOH1AFRxX5Y=', traceId: 'OsUGTyjZAT95YozWxOQrKg==' },
- status: { code: undefined },
- attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-http',
- 'otel.library.version': '0.41.1',
- 'http.url': 'http://localhost/name',
- 'http.host': 'localhost',
- 'net.host.name': 'localhost',
- 'http.method': 'GET',
- 'http.scheme': 'http',
- 'http.target': '/name',
- 'http.user_agent': 'axios/0.21.4',
- 'http.flavor': '1.1',
- 'net.transport': 'ip_tcp',
- 'net.host.ip': '::ffff:127.0.0.1',
- 'net.host.port': undefined,
- 'net.peer.ip': '::ffff:127.0.0.1',
- 'net.peer.port': undefined,
- 'http.status_code': undefined,
- 'http.status_text': 'OK',
- 'http.route': '/name',
- 'span.kind': 'server'
- }
- },
- {
- traceId: 'OsUGTyjZAT95YozWxOQrKg==',
- id: 'zOH1AFRxX5Y=',
- startTime: '2023-07-25T14:50:08.463000064Z',
- hrStartTime: 1690296608463000064n,
- name: 'GET',
- kind: 'client',
- parentSpanId: 'kOYrlY2RC3c=',
- parent: { id: 'kOYrlY2RC3c=', traceId: 'OsUGTyjZAT95YozWxOQrKg==' },
- status: { code: undefined },
- attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-http',
- 'otel.library.version': '0.41.1',
- 'http.url': 'http://localhost/name',
- 'http.method': 'GET',
- 'http.target': '/name',
- 'net.peer.name': 'localhost',
- 'http.host': 'localhost:80',
- 'net.peer.ip': '127.0.0.1',
- 'net.peer.port': undefined,
- 'http.response_content_length_uncompressed': undefined,
- 'http.status_code': undefined,
- 'http.status_text': 'OK',
- 'http.flavor': '1.1',
- 'net.transport': 'ip_tcp',
- 'span.kind': 'client'
- }
- },
- {
- traceId: 'OsUGTyjZAT95YozWxOQrKg==',
- id: 'kOYrlY2RC3c=',
- startTime: '2023-07-25T14:50:08.433999872Z',
- hrStartTime: 1690296608433999872n,
- name: 'GET /animal',
- kind: 'server',
- parentSpanId: undefined,
- parent: undefined,
- status: { code: undefined },
- attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-http',
- 'otel.library.version': '0.41.1',
- 'http.url': 'http://app/animal',
- 'http.host': 'app',
- 'net.host.name': 'app',
- 'http.method': 'GET',
- 'http.scheme': 'http',
- 'http.target': '/animal',
- 'http.user_agent': 'undici',
- 'http.flavor': '1.1',
- 'net.transport': 'ip_tcp',
- 'net.host.ip': '::ffff:172.31.0.3',
- 'net.host.port': undefined,
- 'net.peer.ip': '::ffff:172.31.0.4',
- 'net.peer.port': undefined,
- 'http.status_code': undefined,
- 'http.status_text': 'OK',
- 'http.route': '/animal',
- 'span.kind': 'server'
- }
- }
+ {
+ traceId: 'c5zIzB9SgNYhBPCbTjwg4A==',
+ id: 'u2UfqEE6o2g=',
+ startTime: '2024-10-23T12:08:56.957Z',
+ hrStartTime: 1729685336957000000n,
+ name: 'middleware - query',
+ kind: 'internal',
+ parentSpanId: 'EjUwbQetNus=',
+ parent: { id: 'EjUwbQetNus=', traceId: 'c5zIzB9SgNYhBPCbTjwg4A==' },
+ status: { code: undefined },
+ attributes: {
+ 'otel.scope.name': '@opentelemetry/instrumentation-express',
+ 'otel.scope.version': '0.42.0',
+ 'http.route': '/',
+ 'express.name': 'query',
+ 'express.type': 'middleware',
+ 'span.kind': 'internal'
+ }
+ },
+ {
+ traceId: 'c5zIzB9SgNYhBPCbTjwg4A==',
+ id: 'th00mL0dypQ=',
+ startTime: '2024-10-23T12:08:56.960Z',
+ hrStartTime: 1729685336960000000n,
+ name: 'middleware - expressInit',
+ kind: 'internal',
+ parentSpanId: 'EjUwbQetNus=',
+ parent: { id: 'EjUwbQetNus=', traceId: 'c5zIzB9SgNYhBPCbTjwg4A==' },
+ status: { code: undefined },
+ attributes: {
+ 'otel.scope.name': '@opentelemetry/instrumentation-express',
+ 'otel.scope.version': '0.42.0',
+ 'http.route': '/',
+ 'express.name': 'expressInit',
+ 'express.type': 'middleware',
+ 'span.kind': 'internal'
+ }
+ },
+ {
+ traceId: 'c5zIzB9SgNYhBPCbTjwg4A==',
+ id: '1Er5vsUvUVg=',
+ startTime: '2024-10-23T12:08:56.961Z',
+ hrStartTime: 1729685336961000000n,
+ name: 'request handler - /animal',
+ kind: 'internal',
+ parentSpanId: 'EjUwbQetNus=',
+ parent: { id: 'EjUwbQetNus=', traceId: 'c5zIzB9SgNYhBPCbTjwg4A==' },
+ status: { code: undefined },
+ attributes: {
+ 'otel.scope.name': '@opentelemetry/instrumentation-express',
+ 'otel.scope.version': '0.42.0',
+ 'http.route': '/animal',
+ 'express.name': '/animal',
+ 'express.type': 'request_handler',
+ 'span.kind': 'internal'
+ }
+ },
+ {
+ traceId: 'c5zIzB9SgNYhBPCbTjwg4A==',
+ id: 'n6/1kjZEBD4=',
+ startTime: '2024-10-23T12:08:56.980Z',
+ hrStartTime: 1729685336980000000n,
+ name: 'middleware - query',
+ kind: 'internal',
+ parentSpanId: '4A4ribbJejI=',
+ parent: { id: '4A4ribbJejI=', traceId: 'c5zIzB9SgNYhBPCbTjwg4A==' },
+ status: { code: undefined },
+ attributes: {
+ 'otel.scope.name': '@opentelemetry/instrumentation-express',
+ 'otel.scope.version': '0.42.0',
+ 'http.route': '/',
+ 'express.name': 'query',
+ 'express.type': 'middleware',
+ 'span.kind': 'internal'
+ }
+ },
+ {
+ traceId: 'c5zIzB9SgNYhBPCbTjwg4A==',
+ id: '7Fogi1oddwA=',
+ startTime: '2024-10-23T12:08:56.981Z',
+ hrStartTime: 1729685336981000000n,
+ name: 'middleware - expressInit',
+ kind: 'internal',
+ parentSpanId: '4A4ribbJejI=',
+ parent: { id: '4A4ribbJejI=', traceId: 'c5zIzB9SgNYhBPCbTjwg4A==' },
+ status: { code: undefined },
+ attributes: {
+ 'otel.scope.name': '@opentelemetry/instrumentation-express',
+ 'otel.scope.version': '0.42.0',
+ 'http.route': '/',
+ 'express.name': 'expressInit',
+ 'express.type': 'middleware',
+ 'span.kind': 'internal'
+ }
+ },
+ {
+ traceId: 'c5zIzB9SgNYhBPCbTjwg4A==',
+ id: '+qi2mdPafOY=',
+ startTime: '2024-10-23T12:08:56.981Z',
+ hrStartTime: 1729685336981000000n,
+ name: 'request handler - /name',
+ kind: 'internal',
+ parentSpanId: '4A4ribbJejI=',
+ parent: { id: '4A4ribbJejI=', traceId: 'c5zIzB9SgNYhBPCbTjwg4A==' },
+ status: { code: undefined },
+ attributes: {
+ 'otel.scope.name': '@opentelemetry/instrumentation-express',
+ 'otel.scope.version': '0.42.0',
+ 'http.route': '/name',
+ 'express.name': '/name',
+ 'express.type': 'request_handler',
+ 'span.kind': 'internal'
+ }
+ },
+ {
+ traceId: 'c5zIzB9SgNYhBPCbTjwg4A==',
+ id: 'awOi2E+05aU=',
+ startTime: '2024-10-23T12:08:56.972Z',
+ hrStartTime: 1729685336972000000n,
+ name: 'tcp.connect',
+ kind: 'internal',
+ parentSpanId: '8ROHwPYvo4Q=',
+ parent: { id: '8ROHwPYvo4Q=', traceId: 'c5zIzB9SgNYhBPCbTjwg4A==' },
+ status: { code: undefined },
+ attributes: {
+ 'otel.scope.name': '@opentelemetry/instrumentation-net',
+ 'otel.scope.version': '0.39.0',
+ 'net.transport': 'ip_tcp',
+ 'net.peer.name': 'localhost',
+ 'net.peer.port': '80',
+ 'net.peer.ip': '::1',
+ 'net.host.ip': '::1',
+ 'net.host.port': undefined,
+ 'span.kind': 'internal'
+ }
+ },
+ {
+ traceId: 'c5zIzB9SgNYhBPCbTjwg4A==',
+ id: '4A4ribbJejI=',
+ startTime: '2024-10-23T12:08:56.980Z',
+ hrStartTime: 1729685336980000000n,
+ name: 'GET /name',
+ kind: 'server',
+ parentSpanId: '8ROHwPYvo4Q=',
+ parent: { id: '8ROHwPYvo4Q=', traceId: 'c5zIzB9SgNYhBPCbTjwg4A==' },
+ status: { code: undefined },
+ attributes: {
+ 'otel.scope.name': '@opentelemetry/instrumentation-http',
+ 'otel.scope.version': '0.53.0',
+ 'http.url': 'http://localhost/name',
+ 'http.host': 'localhost',
+ 'net.host.name': 'localhost',
+ 'http.method': 'GET',
+ 'http.scheme': 'http',
+ 'http.target': '/name',
+ 'http.user_agent': 'axios/0.28.1',
+ 'http.flavor': '1.1',
+ 'net.transport': 'ip_tcp',
+ 'net.host.ip': '::1',
+ 'net.host.port': undefined,
+ 'net.peer.ip': '::1',
+ 'net.peer.port': undefined,
+ 'http.status_code': undefined,
+ 'http.status_text': 'OK',
+ 'http.route': '/name',
+ 'span.kind': 'server'
+ }
+ },
+ {
+ traceId: 'c5zIzB9SgNYhBPCbTjwg4A==',
+ id: '8ROHwPYvo4Q=',
+ startTime: '2024-10-23T12:08:56.969Z',
+ hrStartTime: 1729685336969000000n,
+ name: 'GET',
+ kind: 'client',
+ parentSpanId: 'EjUwbQetNus=',
+ parent: { id: 'EjUwbQetNus=', traceId: 'c5zIzB9SgNYhBPCbTjwg4A==' },
+ status: { code: undefined },
+ attributes: {
+ 'otel.scope.name': '@opentelemetry/instrumentation-http',
+ 'otel.scope.version': '0.53.0',
+ 'http.url': 'http://localhost/name',
+ 'http.method': 'GET',
+ 'http.target': '/name',
+ 'net.peer.name': 'localhost',
+ 'http.host': 'localhost:80',
+ 'net.peer.ip': '::1',
+ 'net.peer.port': undefined,
+ 'http.response_content_length_uncompressed': undefined,
+ 'http.status_code': undefined,
+ 'http.status_text': 'OK',
+ 'http.flavor': '1.1',
+ 'net.transport': 'ip_tcp',
+ 'span.kind': 'client'
+ }
+ },
+ {
+ traceId: 'c5zIzB9SgNYhBPCbTjwg4A==',
+ id: 'EjUwbQetNus=',
+ startTime: '2024-10-23T12:08:56.944Z',
+ hrStartTime: 1729685336944000000n,
+ name: 'GET /animal',
+ kind: 'server',
+ parentSpanId: undefined,
+ parent: undefined,
+ status: { code: undefined },
+ attributes: {
+ 'otel.scope.name': '@opentelemetry/instrumentation-http',
+ 'otel.scope.version': '0.53.0',
+ 'http.url': 'http://app/animal',
+ 'http.host': 'app',
+ 'net.host.name': 'app',
+ 'http.method': 'GET',
+ 'http.scheme': 'http',
+ 'http.target': '/animal',
+ 'http.user_agent': 'node',
+ 'http.flavor': '1.1',
+ 'net.transport': 'ip_tcp',
+ 'net.host.ip': '::ffff:172.18.0.3',
+ 'net.host.port': undefined,
+ 'net.peer.ip': '::ffff:172.18.0.4',
+ 'net.peer.port': undefined,
+ 'http.status_code': undefined,
+ 'http.status_text': 'OK',
+ 'http.route': '/animal',
+ 'span.kind': 'server'
+ }
+ }
];
diff --git a/test/examples/log-injection.override.yml b/test/examples/log-injection.override.yml
index e0968e96..1dcc3c05 100644
--- a/test/examples/log-injection.override.yml
+++ b/test/examples/log-injection.override.yml
@@ -5,4 +5,4 @@ services:
test:
command: node ./log-injection
environment:
- COLLECTOR_URL: http://collector:8378
+ COLLECTOR_URL: http://collector:8378/spans
diff --git a/test/examples/log-injection/app.env b/test/examples/log-injection/app.env
index 0fedee11..bfb029b9 100644
--- a/test/examples/log-injection/app.env
+++ b/test/examples/log-injection/app.env
@@ -1,4 +1,4 @@
OTEL_SERVICE_NAME='log-injection-example'
OTEL_RESOURCE_ATTRIBUTES='deployment.environment=dev'
OTEL_LOG_LEVEL='DEBUG'
-OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317
+OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318
diff --git a/test/examples/log-injection/snapshot.js b/test/examples/log-injection/snapshot.js
index 26a67076..da266e44 100644
--- a/test/examples/log-injection/snapshot.js
+++ b/test/examples/log-injection/snapshot.js
@@ -1,17 +1,17 @@
// a console.log from a previous run
module.exports = [
{
- traceId: 'SugyaoARxWUXXGW7OE6nXg==',
- id: 'B4g4YngKBnM=',
- startTime: '2022-06-03T13:04:28.087011840Z',
+ traceId: 'zMEy3eC1iaInGGIWbtULUg==',
+ id: 'X0ohVf0SuXA=',
+ startTime: '2024-10-23T12:20:31.979Z',
+ hrStartTime: 1729686031979000000n,
name: 'main',
kind: 'internal',
parentSpanId: undefined,
parent: undefined,
- references: undefined,
status: { code: undefined },
attributes: {
- 'otel.library.name': 'splunk-otel-example-log-injection',
+ 'otel.scope.name': 'splunk-otel-example-log-injection',
'span.kind': 'internal'
}
}
diff --git a/test/examples/mixed.override.yml b/test/examples/mixed.override.yml
index a843b499..d48d67ad 100644
--- a/test/examples/mixed.override.yml
+++ b/test/examples/mixed.override.yml
@@ -6,4 +6,4 @@ services:
command: node ./mixed
environment:
REQ_URL: http://app/
- COLLECTOR_URL: http://collector:8378
+ COLLECTOR_URL: http://collector:8378/spans
diff --git a/test/examples/mixed/app.env b/test/examples/mixed/app.env
index 2f39b34a..a49262ee 100644
--- a/test/examples/mixed/app.env
+++ b/test/examples/mixed/app.env
@@ -2,4 +2,4 @@ PORT=80
OTEL_SERVICE_NAME='mixed-example'
OTEL_RESOURCE_ATTRIBUTES='deployment.environment=dev'
OTEL_LOG_LEVEL='DEBUG'
-OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317
+OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318
diff --git a/test/examples/mixed/snapshot.js b/test/examples/mixed/snapshot.js
index c6b3402f..ca0b9e56 100644
--- a/test/examples/mixed/snapshot.js
+++ b/test/examples/mixed/snapshot.js
@@ -1,24 +1,43 @@
// a console.log from a previous run
module.exports = [
{
- traceId: '0Iqbr5g8SjiaX3WlJBQyTA==',
- id: 'U9O4F1SzkzY=',
- startTime: '2022-06-03T13:06:01.752053248Z',
+ traceId: '/pCytNplYFQSLCxtMUCv8g==',
+ id: '7Moln4ajdLY=',
+ startTime: '2024-10-23T12:26:15.117Z',
+ hrStartTime: 1729686375117000000n,
+ name: 'work',
+ kind: 'internal',
+ parentSpanId: 'qhrhxw7WAiE=',
+ parent: { id: 'qhrhxw7WAiE=', traceId: '/pCytNplYFQSLCxtMUCv8g==' },
+ status: { code: undefined },
+ attributes: {
+ 'otel.scope.name': 'splunk-otel-example-mixed',
+ 'work.expected_duration': undefined,
+ 'work.my_parameter': undefined,
+ 'work.result': undefined,
+ 'span.kind': 'internal'
+ }
+ },
+ {
+ traceId: '/pCytNplYFQSLCxtMUCv8g==',
+ id: 'qhrhxw7WAiE=',
+ startTime: '2024-10-23T12:26:15.101Z',
+ hrStartTime: 1729686375101000000n,
name: 'GET',
kind: 'server',
parentSpanId: undefined,
parent: undefined,
- references: undefined,
status: { code: undefined },
attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-http',
- 'otel.library.version': '0.28.0',
+ 'otel.scope.name': '@opentelemetry/instrumentation-http',
+ 'otel.scope.version': '0.53.0',
'http.url': 'http://app/',
'http.host': 'app',
'net.host.name': 'app',
'http.method': 'GET',
+ 'http.scheme': 'http',
'http.target': '/',
- 'http.user_agent': 'got (https://github.com/sindresorhus/got)',
+ 'http.user_agent': 'node',
'http.flavor': '1.1',
'net.transport': 'ip_tcp',
'net.host.ip': '::ffff:172.18.0.3',
@@ -29,23 +48,5 @@ module.exports = [
'http.status_text': 'OK',
'span.kind': 'server'
}
- },
- {
- traceId: '0Iqbr5g8SjiaX3WlJBQyTA==',
- id: 'CnIjaAfhsFM=',
- startTime: '2022-06-03T13:06:01.755319040Z',
- name: 'work',
- kind: 'internal',
- parentSpanId: 'U9O4F1SzkzY=',
- parent: { id: 'U9O4F1SzkzY=', traceId: '0Iqbr5g8SjiaX3WlJBQyTA==' },
- references: [],
- status: { code: undefined },
- attributes: {
- 'otel.library.name': 'splunk-otel-example-mixed',
- 'work.expected_duration': undefined,
- 'work.my_parameter': undefined,
- 'work.result': undefined,
- 'span.kind': 'internal'
- }
}
];
diff --git a/test/examples/profiling.override.yml b/test/examples/profiling.override.yml
index b0136801..d793e6eb 100644
--- a/test/examples/profiling.override.yml
+++ b/test/examples/profiling.override.yml
@@ -5,4 +5,4 @@ services:
test:
command: node ./profiling
environment:
- COLLECTOR_URL: http://collector:8378
+ COLLECTOR_URL: http://collector:8378/spans
diff --git a/test/examples/profiling/app.env b/test/examples/profiling/app.env
index d62e6adf..dd645c71 100644
--- a/test/examples/profiling/app.env
+++ b/test/examples/profiling/app.env
@@ -1,5 +1,5 @@
OTEL_SERVICE_NAME='profiling-example'
OTEL_RESOURCE_ATTRIBUTES='deployment.environment=dev'
OTEL_LOG_LEVEL='DEBUG'
-OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317
-SPLUNK_PROFILER_LOGS_ENDPOINT=http://collector:4317
+OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318
+SPLUNK_PROFILER_LOGS_ENDPOINT=http://collector:4318
diff --git a/test/examples/profiling/index.js b/test/examples/profiling/index.js
index 05befd07..b15e587a 100644
--- a/test/examples/profiling/index.js
+++ b/test/examples/profiling/index.js
@@ -1,7 +1,6 @@
const {
assertSpans,
logSpanTable,
- request,
waitSpans,
} = require('../utils.js');
const snapshot = require('./snapshot.js');
diff --git a/test/examples/profiling/snapshot.js b/test/examples/profiling/snapshot.js
index a2ded860..2c454015 100644
--- a/test/examples/profiling/snapshot.js
+++ b/test/examples/profiling/snapshot.js
@@ -1,17 +1,17 @@
// a console.log from a previous run
module.exports = [
{
- traceId: 'SugyaoARxWUXXGW7OE6nXg==',
- id: 'B4g4YngKBnM=',
- startTime: '2022-06-03T13:04:28.087011840Z',
+ traceId: 'F/F3qoc4BVuoI+5xc2e+uA==',
+ id: '/7kIDz0ib94=',
+ startTime: '2024-10-23T15:34:21.116Z',
+ hrStartTime: 1729697661116000000n,
name: 'main',
kind: 'internal',
parentSpanId: undefined,
parent: undefined,
- references: undefined,
status: { code: undefined },
attributes: {
- 'otel.library.name': 'splunk-otel-example-profiling',
+ 'otel.scope.name': 'splunk-otel-example-profiling',
'span.kind': 'internal'
}
}
diff --git a/test/examples/typescript.override.yml b/test/examples/typescript.override.yml
index 80371de5..a4a16a4b 100644
--- a/test/examples/typescript.override.yml
+++ b/test/examples/typescript.override.yml
@@ -9,7 +9,7 @@ services:
command: node ./typescript
environment:
REQ_URL: http://app/
- COLLECTOR_URL: http://collector:8378
+ COLLECTOR_URL: http://collector:8378/spans
depends_on:
- app
- collector
diff --git a/test/examples/typescript/app.env b/test/examples/typescript/app.env
index bc6229a0..8a3df9be 100644
--- a/test/examples/typescript/app.env
+++ b/test/examples/typescript/app.env
@@ -1,4 +1,4 @@
PORT=80
OTEL_RESOURCE_ATTRIBUTES='deployment.environment=dev'
OTEL_LOG_LEVEL='DEBUG'
-OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317
+OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318
diff --git a/test/examples/typescript/snapshot.js b/test/examples/typescript/snapshot.js
index 7d86d6ff..0ffd96b7 100644
--- a/test/examples/typescript/snapshot.js
+++ b/test/examples/typescript/snapshot.js
@@ -1,17 +1,17 @@
module.exports = [
{
- traceId: 'neZpe/CP+vAd5/rhg0Tw3A==',
- id: 'fe+RxrZ76pE=',
- startTime: '2023-09-18T20:16:38.412999936Z',
- hrStartTime: 1695068198412999936n,
+ traceId: 'R+gxE9M1J6UTkIsOh7PMjg==',
+ id: 'V4DPhy8Psf4=',
+ startTime: '2024-10-23T13:06:59.060Z',
+ hrStartTime: 1729688819060000000n,
name: 'middleware - query',
kind: 'internal',
- parentSpanId: 'NVeO5hUT2bw=',
- parent: { id: 'NVeO5hUT2bw=', traceId: 'neZpe/CP+vAd5/rhg0Tw3A==' },
+ parentSpanId: 'iApIRUZb7+s=',
+ parent: { id: 'iApIRUZb7+s=', traceId: 'R+gxE9M1J6UTkIsOh7PMjg==' },
status: { code: undefined },
attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-express',
- 'otel.library.version': '0.33.0',
+ 'otel.scope.name': '@opentelemetry/instrumentation-express',
+ 'otel.scope.version': '0.42.0',
'http.route': '/',
'express.name': 'query',
'express.type': 'middleware',
@@ -19,18 +19,18 @@ module.exports = [
}
},
{
- traceId: 'neZpe/CP+vAd5/rhg0Tw3A==',
- id: 'CnuvgyiHryk=',
- startTime: '2023-09-18T20:16:38.416Z',
- hrStartTime: 1695068198416000000n,
+ traceId: 'R+gxE9M1J6UTkIsOh7PMjg==',
+ id: 'sDChkVN+hZg=',
+ startTime: '2024-10-23T13:06:59.063Z',
+ hrStartTime: 1729688819063000000n,
name: 'middleware - expressInit',
kind: 'internal',
- parentSpanId: 'NVeO5hUT2bw=',
- parent: { id: 'NVeO5hUT2bw=', traceId: 'neZpe/CP+vAd5/rhg0Tw3A==' },
+ parentSpanId: 'iApIRUZb7+s=',
+ parent: { id: 'iApIRUZb7+s=', traceId: 'R+gxE9M1J6UTkIsOh7PMjg==' },
status: { code: undefined },
attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-express',
- 'otel.library.version': '0.33.0',
+ 'otel.scope.name': '@opentelemetry/instrumentation-express',
+ 'otel.scope.version': '0.42.0',
'http.route': '/',
'express.name': 'expressInit',
'express.type': 'middleware',
@@ -38,18 +38,18 @@ module.exports = [
}
},
{
- traceId: 'neZpe/CP+vAd5/rhg0Tw3A==',
- id: 'ZXuWjxuKTqw=',
- startTime: '2023-09-18T20:16:38.416999936Z',
- hrStartTime: 1695068198416999936n,
+ traceId: 'R+gxE9M1J6UTkIsOh7PMjg==',
+ id: '1uGSa9Su+KI=',
+ startTime: '2024-10-23T13:06:59.064Z',
+ hrStartTime: 1729688819064000000n,
name: 'request handler - /',
kind: 'internal',
- parentSpanId: 'NVeO5hUT2bw=',
- parent: { id: 'NVeO5hUT2bw=', traceId: 'neZpe/CP+vAd5/rhg0Tw3A==' },
+ parentSpanId: 'iApIRUZb7+s=',
+ parent: { id: 'iApIRUZb7+s=', traceId: 'R+gxE9M1J6UTkIsOh7PMjg==' },
status: { code: undefined },
attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-express',
- 'otel.library.version': '0.33.0',
+ 'otel.scope.name': '@opentelemetry/instrumentation-express',
+ 'otel.scope.version': '0.42.0',
'http.route': '/',
'express.name': '/',
'express.type': 'request_handler',
@@ -57,47 +57,47 @@ module.exports = [
}
},
{
- traceId: 'neZpe/CP+vAd5/rhg0Tw3A==',
- id: '2rGvSI5L/p4=',
- startTime: '2023-09-18T20:16:38.417999872Z',
- hrStartTime: 1695068198417999872n,
+ traceId: 'R+gxE9M1J6UTkIsOh7PMjg==',
+ id: 'LJVoXT8xVY4=',
+ startTime: '2024-10-23T13:06:59.066Z',
+ hrStartTime: 1729688819066000000n,
name: 'calculate-random',
kind: 'internal',
- parentSpanId: 'NVeO5hUT2bw=',
- parent: { id: 'NVeO5hUT2bw=', traceId: 'neZpe/CP+vAd5/rhg0Tw3A==' },
+ parentSpanId: 'iApIRUZb7+s=',
+ parent: { id: 'iApIRUZb7+s=', traceId: 'R+gxE9M1J6UTkIsOh7PMjg==' },
status: { code: undefined },
attributes: {
- 'otel.library.name': 'rng-app',
+ 'otel.scope.name': 'rng-app',
'random-result': undefined,
'random-method': 'diceroll',
'span.kind': 'internal'
}
},
{
- traceId: 'neZpe/CP+vAd5/rhg0Tw3A==',
- id: 'NVeO5hUT2bw=',
- startTime: '2023-09-18T20:16:38.400999936Z',
- hrStartTime: 1695068198400999936n,
+ traceId: 'R+gxE9M1J6UTkIsOh7PMjg==',
+ id: 'iApIRUZb7+s=',
+ startTime: '2024-10-23T13:06:59.048Z',
+ hrStartTime: 1729688819048000000n,
name: 'GET /',
kind: 'server',
parentSpanId: undefined,
parent: undefined,
status: { code: undefined },
attributes: {
- 'otel.library.name': '@opentelemetry/instrumentation-http',
- 'otel.library.version': '0.41.2',
+ 'otel.scope.name': '@opentelemetry/instrumentation-http',
+ 'otel.scope.version': '0.53.0',
'http.url': 'http://app/',
'http.host': 'app',
'net.host.name': 'app',
'http.method': 'GET',
'http.scheme': 'http',
'http.target': '/',
- 'http.user_agent': 'undici',
+ 'http.user_agent': 'node',
'http.flavor': '1.1',
'net.transport': 'ip_tcp',
- 'net.host.ip': '::ffff:172.31.0.3',
+ 'net.host.ip': '::ffff:172.18.0.3',
'net.host.port': undefined,
- 'net.peer.ip': '::ffff:172.31.0.4',
+ 'net.peer.ip': '::ffff:172.18.0.4',
'net.peer.port': undefined,
'http.status_code': undefined,
'http.status_text': 'OK',
diff --git a/test/examples/utils.js b/test/examples/utils.js
index c90bebde..b497fbc7 100644
--- a/test/examples/utils.js
+++ b/test/examples/utils.js
@@ -111,14 +111,14 @@ function sortByName(spans) {
const waitSpans = (count, timeout = 60) => {
console.error(`Waiting for ${count} spans for ${timeout}s`);
console.time('waitSpans');
- const collectorUrl = new URL(process.env.COLLECTOR_URL ?? 'http://localhost:8378');
+ const collectorUrl = new URL(process.env.COLLECTOR_URL ?? 'http://localhost:8378/spans');
collectorUrl.searchParams.set('count', count);
collectorUrl.searchParams.set('timeout', timeout);
return fetch(collectorUrl)
.then((res) => res.text())
.then((content) => {
- if (content.match(/timed.*out.*waiting.*spans/)) {
+ if (content.match(/timed.*out.*while.*waiting.*for.*results/)) {
assert.fail(`Timed out waiting for ${count} spans for ${timeout}s.`);
}
diff --git a/test/metrics.options.test.ts b/test/metrics.options.test.ts
index 3e500d47..c094cbef 100644
--- a/test/metrics.options.test.ts
+++ b/test/metrics.options.test.ts
@@ -17,7 +17,7 @@
import * as api from '@opentelemetry/api';
import * as utils from './utils';
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
-import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';
+import { OTLPMetricExporter as OTLPGrpcMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';
import { OTLPMetricExporter as OTLPHttpProtoMetricExporter } from '@opentelemetry/exporter-metrics-otlp-proto';
import { _setDefaultOptions } from '../src/metrics';
import { ConsoleMetricExporter } from '../src/metrics/ConsoleMetricExporter';
@@ -53,7 +53,7 @@ describe('metrics options', () => {
assert.deepStrictEqual(readers.length, 2);
- assert(readers[0]['_exporter'] instanceof OTLPMetricExporter);
+ assert(readers[0]['_exporter'] instanceof OTLPHttpProtoMetricExporter);
assert(readers[1]['_exporter'] instanceof ConsoleMetricExporter);
});
@@ -85,27 +85,30 @@ describe('metrics options', () => {
});
it('is possible to use OTEL_EXPORTER_OTLP_PROTOCOL', () => {
- process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'http/protobuf';
+ process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'grpc';
const options = _setDefaultOptions();
const [reader] = options.metricReaderFactory(options);
- assert(reader['_exporter'] instanceof OTLPHttpProtoMetricExporter);
+ assert(reader['_exporter'] instanceof OTLPGrpcMetricExporter);
});
it('prefers OTEL_EXPORTER_OTLP_METRICS_PROTOCOL over OTEL_EXPORTER_OTLP_PROTOCOL', () => {
- process.env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL = 'http/protobuf';
- process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'grpc';
+ process.env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL = 'grpc';
+ process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'http/protobuf';
const options = _setDefaultOptions();
const [reader] = options.metricReaderFactory(options);
- assert(reader['_exporter'] instanceof OTLPHttpProtoMetricExporter);
+ assert(reader['_exporter'] instanceof OTLPGrpcMetricExporter);
});
it('is possible to use OTEL_EXPORTER_OTLP_ENDPOINT', () => {
- process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'foobar:4200';
+ process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foobar:4200';
const options = _setDefaultOptions();
const [reader] = options.metricReaderFactory(options);
const exporter = reader['_exporter'];
- assert(exporter instanceof OTLPMetricExporter);
- assert.deepStrictEqual(exporter['_otlpExporter'].url, 'foobar:4200');
+ assert(exporter instanceof OTLPHttpProtoMetricExporter);
+ assert.deepStrictEqual(
+ exporter['_otlpExporter'].url,
+ 'http://foobar:4200/v1/metrics'
+ );
});
});
@@ -164,7 +167,7 @@ describe('metrics options', () => {
it('warns when realm and endpoint are both set', () => {
process.env.SPLUNK_REALM = 'us0';
process.env.SPLUNK_ACCESS_TOKEN = 'abc';
- process.env.SPLUNK_METRICS_ENDPOINT = 'http://localhost:4317';
+ process.env.SPLUNK_METRICS_ENDPOINT = 'http://localhost:4320';
const options = _setDefaultOptions();
const [reader] = options.metricReaderFactory(options);
@@ -174,8 +177,11 @@ describe('metrics options', () => {
'OTLP metric exporter factory: Realm value ignored (full endpoint URL has been specified).';
assert.equal(logger.warn.mock.calls[0].arguments[0], msg);
- assert(exporter instanceof OTLPMetricExporter);
- assert.deepStrictEqual(exporter['_otlpExporter'].url, 'localhost:4317');
+ assert(exporter instanceof OTLPHttpProtoMetricExporter);
+ assert.deepStrictEqual(
+ exporter['_otlpExporter'].url,
+ 'http://localhost:4320'
+ );
});
});
});
diff --git a/test/metrics.test.ts b/test/metrics.test.ts
index 181a78c5..0b34c4c1 100644
--- a/test/metrics.test.ts
+++ b/test/metrics.test.ts
@@ -15,7 +15,7 @@
*/
import { metrics } from '@opentelemetry/api';
-import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';
+import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-proto';
import { Resource } from '@opentelemetry/resources';
import {
AggregationTemporality,
@@ -115,10 +115,11 @@ describe('metrics', () => {
);
assert.deepEqual(options.runtimeMetricsEnabled, true);
assert.deepEqual(options.runtimeMetricsCollectionIntervalMillis, 5000);
+
+ const readers = options.metricReaderFactory(options);
assert(
- options.metricReaderFactory(options)[0]['_exporter'] instanceof
- OTLPMetricExporter,
- 'Expected the default metric exporter to be OTLP gRPC'
+ readers[0]['_exporter'] instanceof OTLPMetricExporter,
+ 'Expected the default metric exporter to be OTLP over HTTP'
);
assert.deepEqual(options.debugMetricsEnabled, false);
});
diff --git a/test/options.test.ts b/test/options.test.ts
index 20f562d3..0356b715 100644
--- a/test/options.test.ts
+++ b/test/options.test.ts
@@ -16,8 +16,8 @@
import * as api from '@opentelemetry/api';
import { W3CBaggagePropagator } from '@opentelemetry/core';
-import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
-import { OTLPTraceExporter as OTLPHttpTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
+import { OTLPTraceExporter as OTLPGrpcTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
+import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import { InstrumentationBase } from '@opentelemetry/instrumentation';
import { Resource } from '@opentelemetry/resources';
import {
@@ -75,9 +75,6 @@ const assertContainerId = (containerIdAttr) => {
E.g. OTEL_RESOURCE_ATTRIBUTES="service.name="
*/
const MATCH_SERVICE_NAME_WARNING = /service\.name.*not.*set/i;
-// No instrumentations set to be loaded. Install an instrumentation package to enable auto-instrumentation.
-const MATCH_NO_INSTRUMENTATIONS_WARNING =
- /no.*instrumentation.*install.*package/i;
describe('options', () => {
let logger;
@@ -377,7 +374,7 @@ describe('options', () => {
assert.deepStrictEqual(exporters.length, 1);
const [exporter] = exporters;
- assert(exporter instanceof OTLPHttpTraceExporter);
+ assert(exporter instanceof OTLPTraceExporter);
assert.deepStrictEqual(
exporter.url,
`https://ingest.us0.signalfx.com/v2/trace/otlp`
@@ -405,7 +402,7 @@ describe('options', () => {
assert(Array.isArray(exporters));
const [exporter] = exporters;
- assert(exporter instanceof OTLPHttpTraceExporter);
+ assert(exporter instanceof OTLPTraceExporter);
assert.deepStrictEqual(
exporter.url,
'https://ingest.us0.signalfx.com/v2/trace/otlp'
@@ -421,7 +418,8 @@ describe('options', () => {
it('warns when realm and endpoint are both set', () => {
process.env.SPLUNK_REALM = 'us0';
process.env.SPLUNK_ACCESS_TOKEN = 'abc';
- process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://localhost:4317';
+ process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT =
+ 'http://myendpoint:4333/v1/my-traces';
const options = _setDefaultOptions();
const exporters = options.spanExporterFactory(options);
@@ -439,7 +437,10 @@ describe('options', () => {
exporter instanceof OTLPTraceExporter,
'Expected exporter to be instance of OTLPTraceExporter'
);
- assert.deepStrictEqual(exporter.url, 'localhost:4317');
+ assert.deepStrictEqual(
+ exporter.url,
+ 'http://myendpoint:4333/v1/my-traces'
+ );
});
});
@@ -455,22 +456,22 @@ describe('options', () => {
});
it('is possible to use OTEL_EXPORTER_OTLP_PROTOCOL', () => {
- process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'http/protobuf';
+ process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'grpc';
const options = _setDefaultOptions();
const exporters = options.spanExporterFactory(options);
assert(Array.isArray(exporters));
const [exporter] = exporters;
- assert(exporter instanceof OTLPHttpTraceExporter);
+ assert(exporter instanceof OTLPGrpcTraceExporter);
});
it('prefers OTEL_EXPORTER_OTLP_TRACES_PROTOCOL over OTEL_EXPORTER_OTLP_PROTOCOL', () => {
- process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = 'http/protobuf';
- process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'grpc';
+ process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = 'grpc';
+ process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'http/protobuf';
const options = _setDefaultOptions();
const exporters = options.spanExporterFactory(options);
assert(Array.isArray(exporters));
const [exporter] = exporters;
- assert(exporter instanceof OTLPHttpTraceExporter);
+ assert(exporter instanceof OTLPGrpcTraceExporter);
});
it('is possible to use OTEL_EXPORTER_OTLP_ENDPOINT', () => {
@@ -480,7 +481,7 @@ describe('options', () => {
assert(Array.isArray(exporters));
const [exporter] = exporters;
assert(exporter instanceof OTLPTraceExporter);
- assert.deepStrictEqual(exporter.url, 'foobar:4200');
+ assert.deepStrictEqual(exporter.url, 'foobar:4200/v1/traces');
});
it('prefers OTEL_EXPORTER_OTLP_TRACES_ENDPOINT over OTEL_EXPORTER_OTLP_ENDPOINT', () => {
diff --git a/test/profiling/exporter.test.ts b/test/profiling/exporter.test.ts
deleted file mode 100644
index 1e00a8fb..00000000
--- a/test/profiling/exporter.test.ts
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright Splunk Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import * as grpc from '@grpc/grpc-js';
-import { VERSION } from '@opentelemetry/core';
-import { Resource } from '@opentelemetry/resources';
-import { strict as assert } from 'assert';
-import { beforeEach, describe, it, mock } from 'node:test';
-import { OTLPProfilingExporter } from '../../src/profiling/OTLPProfilingExporter';
-import * as utils from '../utils';
-import { cpuProfile, heapProfile } from './profiles';
-
-describe('profiling OTLP exporter', () => {
- describe('configuration', () => {
- beforeEach(() => {
- utils.cleanEnvironment();
- });
-
- it('configures insecure gRPC credentials for endpoints without a scheme', () => {
- const exporter = new OTLPProfilingExporter({
- endpoint: 'foobar:8181',
- callstackInterval: 1000,
- resource: Resource.empty(),
- });
- assert.deepStrictEqual(
- exporter['_client'].getChannel()['internalChannel']['credentials'],
- grpc.ChannelCredentials.createInsecure()
- );
- });
-
- it('configures insecure gRPC credentials for http endpoints', () => {
- const exporter = new OTLPProfilingExporter({
- endpoint: 'http://foobar:8181',
- callstackInterval: 1000,
- resource: Resource.empty(),
- });
- assert.deepStrictEqual(
- exporter['_client'].getChannel()['internalChannel']['credentials'],
- grpc.ChannelCredentials.createInsecure()
- );
- });
-
- it('configures secure gRPC credentials for https endpoints', () => {
- const exporter = new OTLPProfilingExporter({
- endpoint: 'https://foobar:8181',
- callstackInterval: 1000,
- resource: Resource.empty(),
- });
- assert.deepStrictEqual(
- exporter['_client'].getChannel()['internalChannel']['credentials'],
- grpc.ChannelCredentials.createSsl()
- );
- });
- });
-
- describe('exporting', () => {
- it('attaches common attributes when exporting CPU profiles', () => {
- const exporter = new OTLPProfilingExporter({
- endpoint: 'http://foobar:8181',
- callstackInterval: 1000,
- resource: new Resource({ service: 'foo' }),
- });
-
- mock.method(exporter['_client'], 'export', (payload: unknown) => {
- const { resourceLogs } = payload as any;
- assert.deepStrictEqual(resourceLogs.length, 1);
- const { instrumentationLibraryLogs, resource } = resourceLogs[0];
- assert.deepStrictEqual(resource.attributes, [
- { key: 'telemetry.sdk.language', value: { stringValue: 'node' } },
- { key: 'telemetry.sdk.version', value: { stringValue: VERSION } },
- { key: 'service', value: { stringValue: 'foo' } },
- ]);
- assert.deepStrictEqual(instrumentationLibraryLogs.length, 1);
- const { logs } = instrumentationLibraryLogs[0];
- assert.deepStrictEqual(logs.length, 1);
- const log = logs[0];
-
- assert.deepStrictEqual(log.attributes, [
- {
- key: 'profiling.data.format',
- value: { stringValue: 'pprof-gzip-base64' },
- },
- { key: 'profiling.data.type', value: { stringValue: 'cpu' } },
- {
- key: 'com.splunk.sourcetype',
- value: { stringValue: 'otel.profiling' },
- },
- { key: 'profiling.data.total.frame.count', value: { intValue: 2 } },
- ]);
- });
-
- exporter.send(cpuProfile);
- });
-
- it('attaches common attributes when exporting heap profiles', () => {
- const exporter = new OTLPProfilingExporter({
- endpoint: 'http://foobar:8181',
- callstackInterval: 1000,
- resource: new Resource({ service: 'foo' }),
- });
-
- mock.method(exporter['_client'], 'export', (payload: unknown) => {
- const { resourceLogs } = payload as any;
- assert.deepStrictEqual(resourceLogs.length, 1);
- const { instrumentationLibraryLogs, resource } = resourceLogs[0];
- assert.deepStrictEqual(resource.attributes, [
- { key: 'telemetry.sdk.language', value: { stringValue: 'node' } },
- { key: 'telemetry.sdk.version', value: { stringValue: VERSION } },
- { key: 'service', value: { stringValue: 'foo' } },
- ]);
- assert.deepStrictEqual(instrumentationLibraryLogs.length, 1);
- const { logs } = instrumentationLibraryLogs[0];
- assert.deepStrictEqual(logs.length, 1);
- const log = logs[0];
-
- assert.deepStrictEqual(log.attributes, [
- {
- key: 'profiling.data.format',
- value: { stringValue: 'pprof-gzip-base64' },
- },
- { key: 'profiling.data.type', value: { stringValue: 'allocation' } },
- {
- key: 'com.splunk.sourcetype',
- value: { stringValue: 'otel.profiling' },
- },
- { key: 'profiling.data.total.frame.count', value: { intValue: 3 } },
- ]);
- });
-
- exporter.sendHeapProfile(heapProfile);
- });
- });
-});
diff --git a/test/profiling/http_exporter.test.ts b/test/profiling/http_exporter.test.ts
new file mode 100644
index 00000000..7301fdbe
--- /dev/null
+++ b/test/profiling/http_exporter.test.ts
@@ -0,0 +1,110 @@
+/*
+ * Copyright Splunk Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { VERSION } from '@opentelemetry/core';
+import { Resource } from '@opentelemetry/resources';
+import { strict as assert } from 'assert';
+import { describe, it, mock } from 'node:test';
+import { OtlpHttpProfilingExporter } from '../../src/profiling/OtlpHttpProfilingExporter';
+import { cpuProfile, heapProfile } from './profiles';
+import { InMemoryLogRecordExporter } from '@opentelemetry/sdk-logs';
+
+describe('profiling OTLP HTTP exporter', () => {
+ it('appends the logs path to the endpoint', () => {
+ const exporter = new OtlpHttpProfilingExporter({
+ endpoint: 'http://localhost:4318',
+ callstackInterval: 1000,
+ resource: new Resource({}),
+ });
+
+ assert.strictEqual(exporter._endpoint, 'http://localhost:4318/v1/logs');
+ });
+
+ it('does not append the logs path to the endpoint when one exists', () => {
+ const exporter = new OtlpHttpProfilingExporter({
+ endpoint: 'http://abc:4200/v1/logs',
+ callstackInterval: 1000,
+ resource: new Resource({}),
+ });
+
+ assert.strictEqual(exporter._endpoint, 'http://abc:4200/v1/logs');
+ });
+
+ it('attaches common attributes when exporting CPU profiles', async () => {
+ const exporter = new OtlpHttpProfilingExporter({
+ endpoint: 'http://foobar:8181',
+ callstackInterval: 1000,
+ resource: new Resource({ xyz: 'foo' }),
+ });
+
+ const logExporter = new InMemoryLogRecordExporter();
+ mock.method(exporter, '_getExporter', () => logExporter);
+
+ await exporter.send(cpuProfile);
+
+ const logs = logExporter.getFinishedLogRecords();
+
+ assert.strictEqual(logs.length, 1);
+
+ const [log] = logs;
+
+ assert.deepStrictEqual(log.resource.attributes, {
+ 'telemetry.sdk.language': 'node',
+ 'telemetry.sdk.version': VERSION,
+ xyz: 'foo',
+ });
+
+ assert.deepStrictEqual(log.attributes, {
+ 'profiling.data.format': 'pprof-gzip-base64',
+ 'profiling.data.type': 'cpu',
+ 'com.splunk.sourcetype': 'otel.profiling',
+ 'profiling.data.total.frame.count': 2,
+ });
+ });
+
+ it('attaches common attributes when exporting heap profiles', async () => {
+ const exporter = new OtlpHttpProfilingExporter({
+ endpoint: 'http://foobar:8181',
+ callstackInterval: 1000,
+ resource: new Resource({ xyz: 'foo' }),
+ });
+
+ const logExporter = new InMemoryLogRecordExporter();
+
+ mock.method(exporter, '_getExporter', () => logExporter);
+
+ await exporter.sendHeapProfile(heapProfile);
+
+ const logs = logExporter.getFinishedLogRecords();
+
+ assert.deepStrictEqual(logs.length, 1);
+
+ const [log] = logs;
+
+ assert.deepStrictEqual(log.resource.attributes, {
+ 'telemetry.sdk.language': 'node',
+ 'telemetry.sdk.version': VERSION,
+ xyz: 'foo',
+ });
+
+ assert.deepStrictEqual(log.attributes, {
+ 'profiling.data.format': 'pprof-gzip-base64',
+ 'profiling.data.type': 'allocation',
+ 'com.splunk.sourcetype': 'otel.profiling',
+ 'profiling.data.total.frame.count': 3,
+ });
+ });
+});
diff --git a/test/profiling/profiling.test.ts b/test/profiling/profiling.test.ts
index 50f49e20..713e8f95 100644
--- a/test/profiling/profiling.test.ts
+++ b/test/profiling/profiling.test.ts
@@ -61,7 +61,7 @@ describe('profiling', () => {
assert.deepStrictEqual(defaultOtherAttrs, {
serviceName: '@splunk/otel',
- endpoint: 'http://localhost:4317',
+ endpoint: 'http://localhost:4318',
callstackInterval: 1_000,
collectionDuration: 30_000,
exporterFactory: defaultExporterFactory,
@@ -107,12 +107,12 @@ describe('profiling', () => {
let sendCallCount = 0;
const stacktracesReceived: ProfilingStacktrace[] = [];
const exporter: ProfilingExporter = {
- send(cpuProfile: CpuProfile) {
+ async send(cpuProfile: CpuProfile) {
const { stacktraces } = cpuProfile;
sendCallCount += 1;
stacktracesReceived.push(...stacktraces);
},
- sendHeapProfile(_profile: HeapProfile) {},
+ async sendHeapProfile(_profile: HeapProfile) {},
};
// enabling tracing is required for span information to be caught
diff --git a/test/runner.js b/test/runner.js
index bf98a478..51e93baa 100644
--- a/test/runner.js
+++ b/test/runner.js
@@ -21,7 +21,22 @@ function findTestFiles(dir, fileList = []) {
}
// Find all test files in the ./test directory
-const testFiles = findTestFiles(__dirname);
+let testFiles = findTestFiles(__dirname);
+
+if (process.argv.length > 2) {
+ const patterns = process.argv.slice(2);
+
+ testFiles = testFiles.filter((path) => {
+ for (const pattern of patterns) {
+ if (path.includes(pattern)) {
+ return true;
+ }
+ }
+
+ return false;
+ });
+}
+
const args = [
'--require',
diff --git a/test/tracing/common.ts b/test/tracing/common.ts
index ab337ffc..39fbc2e9 100644
--- a/test/tracing/common.ts
+++ b/test/tracing/common.ts
@@ -18,7 +18,7 @@ import { strict as assert } from 'assert';
import { mock } from 'node:test';
import { trace } from '@opentelemetry/api';
-import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
+import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { ProxyTracerProvider } from '@opentelemetry/api';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
@@ -59,7 +59,9 @@ export function assertTracingPipeline(
if (accessToken) {
assert.equal(
- exporter['_transport']['_parameters']['metadata']().get('x-sf-token')[0],
+ exporter['_transport']['_transport']['_parameters']['headers'][
+ 'X-SF-TOKEN'
+ ],
accessToken
);
}
diff --git a/test/tracing/default_setup.test.ts b/test/tracing/default_setup.test.ts
index a2f81522..33bc6882 100644
--- a/test/tracing/default_setup.test.ts
+++ b/test/tracing/default_setup.test.ts
@@ -24,6 +24,10 @@ test('Tracing: set up with defaults', async () => {
const mocks = setupMocks();
const { tracingOptions } = parseOptionsAndConfigureInstrumentations();
startTracing(tracingOptions);
- assertTracingPipeline(mocks, 'localhost:4317', '@splunk/otel');
+ assertTracingPipeline(
+ mocks,
+ 'http://localhost:4318/v1/traces',
+ '@splunk/otel'
+ );
await stopTracing();
});
diff --git a/test/tracing/env_options.test.ts b/test/tracing/env_options.test.ts
index cef61555..c42cdfea 100644
--- a/test/tracing/env_options.test.ts
+++ b/test/tracing/env_options.test.ts
@@ -33,6 +33,6 @@ test('Tracing: set up with env options', async () => {
const { tracingOptions } = parseOptionsAndConfigureInstrumentations();
startTracing(tracingOptions);
- assertTracingPipeline(mocks, url, serviceName, accessToken);
+ assertTracingPipeline(mocks, `${url}/v1/traces`, serviceName, accessToken);
await stopTracing();
});
diff --git a/test/utils.ts b/test/utils.ts
index d8720dca..e4572432 100644
--- a/test/utils.ts
+++ b/test/utils.ts
@@ -122,7 +122,7 @@ export function calledWithExactly(mocked: any, expected: any) {
assert(match, `Expected call with: ${JSON.stringify(expected)} not found`);
}
-export function calledOnceWithMatch(mocked: any, match: Object) {
+export function calledOnceWithMatch(mocked: any, match: object) {
assert.strictEqual(
mocked.mock.calls.length,
1,