Skip to content
Merged
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
28 changes: 10 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
"@elastic/monaco-esql": "^3.1.5",
"@elastic/node-crypto": "^1.2.3",
"@elastic/numeral": "^2.5.1",
"@elastic/opentelemetry-node": "^1.1.1",
"@elastic/react-search-ui": "^1.24.0",
"@elastic/react-search-ui-views": "^1.24.0",
"@elastic/request-converter": "^9.1.0",
Expand All @@ -155,7 +156,7 @@
"@formatjs/intl-utils": "^3.8.4",
"@formatjs/ts-transformer": "^3.13.14",
"@google/generative-ai": "^0.21.0",
"@grpc/grpc-js": "^1.8.22",
"@grpc/grpc-js": "^1.13.4",
"@hapi/accept": "^6.0.3",
"@hapi/boom": "^10.0.1",
"@hapi/cookie": "^12.0.1",
Expand Down Expand Up @@ -1121,23 +1122,14 @@
"@openfeature/server-sdk": "^1.18.0",
"@openfeature/web-sdk": "^1.5.0",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/api-metrics": "^0.31.0",
"@opentelemetry/context-async-hooks": "^2.0.0",
"@opentelemetry/core": "^2.0.0",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These APIs are env-agnostic I think - in the sense that you should be able to use them in both the browser and node.js. How do we plan to handle this if we fully delegate to @elastic/opentelemetry-node which is only for node.js?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question.

AFAIK, we're focusing on the server for now.

I would expect that there will be an @elastic/opentelemetry-web/sdk or something like that.

If not, we can install the vanilla packages again.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect that there will be an @elastic/opentelemetry-web/sdk or something like that.

I'm not sure. In general I'm not sure if we should hide OpenTelemetry APIs behind an elastic distrib. @trentm what are the advantages here? It just feels off to use re-exported OpenTelemetry types where we also have less control about versioning.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What benefit do we get from maintaining 12 different packages (17 really, but I only managed to remove 12 because we needed the other 5)? Especially with the current state of maturity of OTel.

Our renovate PR didn't manage to identify that @opentelemetry/api-metrics (link), or @opentelemetry/sdk-metrics-base (link) were deprecated 3 years ago!

And don't get me started on potentially incompatibilities across versions. I'd rather push that burden to the owners of EDOT.

I can also see the benefit of "dog-fooding" our products to identify opportunities to improve them: this PR highlights the bad DX of having to move from direct imports of types to namespaced imports: import { MeterProvider } becomes import { metrics } + metrics.MeterProvider 😢

IMO, this is a bad DX, and it's good that we figured it out first.

But I'd love to hear @trentm's thoughts.

Copy link
Copy Markdown
Member

@trentm trentm Jul 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't currently have a "web SDK" (i.e. an OTel SDK targetting browsers).

The state of a Web SDK in vanilla OTel JS is also much less mature that the packages for Node.js. See https://opentelemetry.io/docs/languages/js/getting-started/browser/ for a start, but one needs to learn more about the details to use it effectively. @david-luna and I can try to help where needed.

These APIs are env-agnostic I think

Dario, I'm not sure if you were talking about all three of those deps:

-    "@opentelemetry/api-metrics": "^0.31.0",
-    "@opentelemetry/context-async-hooks": "^2.0.0",
-    "@opentelemetry/core": "^2.0.0",
  • api-metrics is gone now. It was merged into @opentelemetry/api. It being a dep in Kibana's package.json shows that this metrics usage was a quite old usage from before the Metrics parts of @opentelemetry/api were stabilized.
  • context-async-hooks is only relevant to Node.js, so you shouldn't need to this dep at all. @elastic/opentelemetry-node will setup the appropriate ContextManager for Node.js.
  • core: The only usage of that in kibana.git that I see is:
x-pack/platform/packages/shared/kbn-inference-tracing/src/create_inference_active_span.ts
8:import { isTracingSuppressed } from '@opentelemetry/core';

Is createActiveInferenceSpan() used in Kibana browser code? If so, having a separate dep on @opentelemetry/core will be necessary -- and fine to have alongside @elastic/opentelemetry-node.
If just in Node.js code, the core module is re-exported by @elastic/opentelemetry-node/sdk:

> var edot = require('@elastic/opentelemetry-node/sdk')
> edot.core.isTracingSuppressed
[Function: isTracingSuppressed]

Copy link
Copy Markdown
Member Author

@afharo afharo Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @trentm for such informative comments.

Is there a problem with this:

import {metrics} from '@elastic/opentelemetry-node';
// ...
const myReader = new metrics.MetricReader(...)
or this:

import {metrics} from '@elastic/opentelemetry-node';
const {MetricReader} = metrics;
// ...
const myReader = new MetricReader(...)
other than a single line import {MetricReader} from 'something' looks nicer?

That makes it nicer (I'll adapt the PR to minimize the number of lines changed). However, the DX is still suboptimal: typically your IDE helps with the imports. This package forces you to intentionally type it because the IDE is never going to find the MetricReader that you're after.

Also, I wonder if this affects performance as it may be worse on tree-shaking: I might be completely wrong here but AFAIK the import in the example below is a noop at runtime and the compiler removes it:

import { MetricReader } from '...';

function doSomething(reader: MetricReader) {}

However, I'm not that sure about importing a parent variable metrics (in both flavors that you shared above). I'll need to test to see if the generated compiled code removes it or not.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@trentm, actually, we need to differentiate between runtime code and types 😢:

import { tracing } from '@elastic/opentelemetry-node/sdk';

const { TraceIdRatioBasedSampler } = tracing;
type SpanProcessor = tracing.SpanProcessor;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What benefit do we get from maintaining 12 different packages (17 really, but I only managed to remove 12 because we needed the other 5)? Especially with the current state of maturity of OTel.

We don't, but i think we'll end up using some of the packages directly anyway. It just feels off to me, but not a blocker for me in any case.

Dario, I'm not sure if you were talking about all three of those deps:

I'm talking about @opentelemetry/api and @opentelemetry/core. E.g., I have helpers that create spans. I want to be able to use that code in the browser and in Node.js. How can I do that if we are expected to go through @elastic/opentelemetry-node and a hypothetical @elastic/opentelemetry-web lib? We would need @elastic/opentelemetry to be created I guess. And we'd have to do that for every instrumentation package we want to use.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dgieselaar, I agree with you that this makes it harder to make agnostic code.

TBH, after trying to "simulate" some of the changes in #224933 with this set of packages, I think that creating spans or metrics should be used via imports from @opentelemetry/api (which is a peer dependency of @elastic/opentelemetry-node/sdk, meaning that we'll have to install it separately anyway)

IMO, it's better to do import { metrics } from '@opentelemetry/api'; than import { api } from '@elastic/opentelemetry-node/sdk'; + use api.metrics.

On top of that, given that OTel has this weird requirement about every component in the code having to know the name of the meter/tracer, we'll likely end up with some sort of utils package that exposes the default meter/tracer (the output of metrics.getMeter('kibana')).

So I'd expect that the EDOT imports are reduced to the places where we're configuring the SDK (setting up the providers and exporters), but not the actual code instrumentation.

Does this make sense?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm talking about @opentelemetry/api and @opentelemetry/core. E.g., I have helpers that create spans. I want to be able to use that code in the browser and in Node.js. How can I do that if we are expected to go through @elastic/opentelemetry-node and a hypothetical @elastic/opentelemetry-web lib?

My understanding of OTel is that separately importing @opentelemetry/api and using it is intentional and a good thing.

That leaves @opentelemetry/core. I think it would be fine for Kibana to have both @elastic/opentelemetry-node and @opentelemetry/core as deps. However, yes it means that you likely want to watch that the version of both are compatible versions so that the expected functionality works. And possibly want to sure that the same exact version is installed to reduce bundle sizes (if that is a concern).

"@opentelemetry/exporter-metrics-otlp-grpc": "^0.34.0",
"@opentelemetry/exporter-prometheus": "^0.31.0",
"@opentelemetry/exporter-trace-otlp-grpc": "^0.200.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.200.0",
"@opentelemetry/exporter-trace-otlp-proto": "^0.200.0",
"@opentelemetry/instrumentation": "^0.200.0",
"@opentelemetry/instrumentation-http": "^0.200.0",
"@opentelemetry/instrumentation-undici": "^0.11.0",
"@opentelemetry/otlp-exporter-base": "^0.200.0",
"@opentelemetry/resources": "^2.0.0",
"@opentelemetry/sdk-metrics-base": "^0.31.0",
"@opentelemetry/sdk-node": "^0.200.0",
"@opentelemetry/sdk-trace-base": "^2.0.0",
"@opentelemetry/sdk-trace-node": "^2.0.0",
"@opentelemetry/context-async-hooks": "^2.0.1",
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.202.0",
"@opentelemetry/exporter-prometheus": "^0.202.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.202.0",
"@opentelemetry/exporter-trace-otlp-proto": "^0.202.0",
"@opentelemetry/instrumentation": "^0.202.0",
"@opentelemetry/instrumentation-undici": "^0.13.2",
"@opentelemetry/otlp-exporter-base": "^0.202.0",
"@opentelemetry/semantic-conventions": "^1.34.0",
"@paralleldrive/cuid2": "^2.2.2",
"@reduxjs/toolkit": "1.9.7",
Expand Down
33 changes: 15 additions & 18 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@
"@aws-crypto/sha256-js",
"@aws-crypto/util",
"@langtrase/trace-attributes",
"@opentelemetry/sdk-trace-base",
"@arizeai/openinference-semantic-conventions",
"@smithy/eventstream-serde-node",
"@smithy/node-http-handler",
"@smithy/types",
Expand Down Expand Up @@ -3370,7 +3370,7 @@
],
"minimumReleaseAge": "7 days",
"enabled": true
},
},
{
"groupName": "redux-actions",
"matchDepNames": [
Expand Down Expand Up @@ -4346,36 +4346,33 @@
"groupName": "OpenTelemetry modules",
"matchDepNames": [
"@grpc/grpc-js",
"@elastic/opentelemetry-node",
"@opentelemetry/api",
"@opentelemetry/api-metrics",
"@opentelemetry/core",
"@opentelemetry/context-async-hooks",
"@opentelemetry/exporter-metrics-otlp-grpc",
"@opentelemetry/exporter-prometheus",
"@opentelemetry/resources",
"@opentelemetry/sdk-metrics-base",
"@opentelemetry/semantic-conventions",
"@arizeai/openinference-semantic-conventions",
"@opentelemetry/context-async-hooks",
"@opentelemetry/exporter-trace-otlp-grpc",
"@opentelemetry/exporter-trace-otlp-http",
"@opentelemetry/exporter-trace-otlp-proto",
"@opentelemetry/otlp-exporter-base",
"@opentelemetry/sdk-node",
"@opentelemetry/sdk-trace-node",
"@opentelemetry/instrumentation",
"@opentelemetry/instrumentation-http",
"@opentelemetry/instrumentation-undici"
"@opentelemetry/instrumentation-undici",
"@opentelemetry/otlp-exporter-base",
"@opentelemetry/semantic-conventions"
],
"reviewers": [
"team:stack-monitoring",
"team:kibana-core"
"team:appex-ai-infra",
"team:kibana-core",
"team:kibana-security",
"team:stack-monitoring"
Comment on lines +4362 to +4365
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New owners... do you all agree?

I was tempted to split the list based on who uses it:

  • @opentelemetry/exporter-metrics-otlp-grpc and @opentelemetry/exporter-prometheus are only used by @elastic/stack-monitoring
  • @opentelemetry/instrumentation, @opentelemetry/instrumentation-undici, @opentelemetry/exporter-trace-otlp-*, and @opentelemetry/otlp-exporter-baseare only used in @elastic/appex-ai-infra's plugins.

But I thought that there might be potential issues with mismatching versions, so it might be best to upgrade them in the same PR together. WDYT?

cc @elastic/kibana-core @elastic/kibana-security @elastic/appex-ai-infra @elastic/stack-monitoring

],
"matchBaseBranches": [
"main"
],
"labels": [
"Team:AI Infra",
"Team:Monitoring",
"backport:all-open",
"Team:Core",
"Team:Security",
"backport:prev-minor",
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll have to manually switch to backport:skip until 9.2 is released. But I'd rather do this over setting this to backport:skip now and forgetting to update renovate later.

"release_note:skip"
],
"minimumReleaseAge": "7 days",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ export class ImportResolver {
return Path.resolve(REPO_ROOT, `node_modules/@modelcontextprotocol/sdk/dist/esm/${relPath}`);
}

// We need this "hack" because our current import-resolver doesn't support "exports" in package.json.
// We should be able to remove this once we support cjs/esm interop.
if (req.startsWith('@elastic/opentelemetry-node/sdk')) {
return Path.resolve(REPO_ROOT, `node_modules/@elastic/opentelemetry-node/lib/sdk.js`);
}
Comment on lines +152 to +154
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes the runtime imports (including ESLint).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can likely add a note here so we don't forget we can remove this once the cjs/esm interop is in

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we create an issue and reference it here? That way we can track the technical debt and possibly trigger someone to fix it.


// turn root-relative paths into relative paths
if (
req.startsWith('src/') ||
Expand Down
31 changes: 10 additions & 21 deletions src/platform/packages/shared/kbn-tracing/src/init_tracing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,14 @@
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { core, node, resources, tracing } from '@elastic/opentelemetry-node/sdk';
import { LangfuseSpanProcessor, PhoenixSpanProcessor } from '@kbn/inference-tracing';
import { fromExternalVariant } from '@kbn/std';
import { TracingConfig } from '@kbn/tracing-config';
import { context, propagation, trace } from '@opentelemetry/api';
import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks';
import {
CompositePropagator,
W3CBaggagePropagator,
W3CTraceContextPropagator,
} from '@opentelemetry/core';
import {
NodeTracerProvider,
ParentBasedSampler,
SpanProcessor,
TraceIdRatioBasedSampler,
} from '@opentelemetry/sdk-trace-node';
import type { AgentConfigOptions } from 'elastic-apm-node';
import { castArray, once } from 'lodash';
import { resourceFromAttributes } from '@opentelemetry/resources';
import { ATTR_SERVICE_INSTANCE_ID, ATTR_SERVICE_NAMESPACE } from '@kbn/opentelemetry-attributes';
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
import { LateBindingSpanProcessor } from '..';
Expand All @@ -40,7 +29,7 @@ export function initTracing({
context.setGlobalContextManager(contextManager);
contextManager.enable();

const resource = resourceFromAttributes({
const resource = resources.resourceFromAttributes({
[ATTR_SERVICE_NAME]: apmConfig?.serviceName,
[ATTR_SERVICE_INSTANCE_ID]: apmConfig?.serviceNodeName,
[ATTR_SERVICE_NAMESPACE]: apmConfig?.environment,
Expand All @@ -49,20 +38,20 @@ export function initTracing({
// this is used for late-binding of span processors
const lateBindingProcessor = LateBindingSpanProcessor.get();

const allSpanProcessors: SpanProcessor[] = [lateBindingProcessor];
const allSpanProcessors: tracing.SpanProcessor[] = [lateBindingProcessor];

propagation.setGlobalPropagator(
new CompositePropagator({
propagators: [new W3CTraceContextPropagator(), new W3CBaggagePropagator()],
new core.CompositePropagator({
propagators: [new core.W3CTraceContextPropagator(), new core.W3CBaggagePropagator()],
})
);

const traceIdSampler = new TraceIdRatioBasedSampler(tracingConfig?.sample_rate ?? 1);
const traceIdSampler = new tracing.TraceIdRatioBasedSampler(tracingConfig?.sample_rate ?? 1);

const nodeTracerProvider = new NodeTracerProvider({
const nodeTracerProvider = new node.NodeTracerProvider({
// by default, base sampling on parent context,
// or for root spans, based on the configured sample rate
sampler: new ParentBasedSampler({
sampler: new tracing.ParentBasedSampler({
root: traceIdSampler,
}),
spanProcessors: allSpanProcessors,
Expand All @@ -85,8 +74,8 @@ export function initTracing({
trace.setGlobalTracerProvider(nodeTracerProvider);

propagation.setGlobalPropagator(
new CompositePropagator({
propagators: [new W3CTraceContextPropagator(), new W3CBaggagePropagator()],
new core.CompositePropagator({
propagators: [new core.W3CTraceContextPropagator(), new core.W3CBaggagePropagator()],
})
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
*/

import { Context } from '@opentelemetry/api';
import { ReadableSpan, Span, SpanProcessor } from '@opentelemetry/sdk-trace-node';
import { pull } from 'lodash';
import { tracing } from '@elastic/opentelemetry-node/sdk';

const noop = async () => {};

Expand All @@ -18,18 +18,18 @@ const noop = async () => {};
* which is useful if processors should be conditionally applied based on config
* or runtime logic.
*/
export class LateBindingSpanProcessor implements SpanProcessor {
export class LateBindingSpanProcessor implements tracing.SpanProcessor {
static #instance?: LateBindingSpanProcessor;

#processors: SpanProcessor[] = [];
#processors: tracing.SpanProcessor[] = [];

private constructor() {}

onStart(span: Span, parentContext: Context): void {
onStart(span: tracing.Span, parentContext: Context): void {
this.#processors.forEach((processor) => processor.onStart(span, parentContext));
}

onEnd(span: ReadableSpan): void {
onEnd(span: tracing.ReadableSpan): void {
this.#processors.forEach((processor) => processor.onEnd(span));
}

Expand All @@ -40,7 +40,7 @@ export class LateBindingSpanProcessor implements SpanProcessor {
await Promise.all(this.#processors.map((processor) => processor.shutdown()));
}

register(processor: SpanProcessor) {
register(processor: tracing.SpanProcessor) {
this.#processors.push(processor);

return async () => {
Expand All @@ -49,7 +49,7 @@ export class LateBindingSpanProcessor implements SpanProcessor {
};
}

static register(processor: SpanProcessor): () => Promise<void> {
static register(processor: tracing.SpanProcessor): () => Promise<void> {
return this.#instance?.register(processor) ?? noop;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { Counter, Meter } from '@opentelemetry/api-metrics';
import { Counter, Meter } from '@opentelemetry/api';

export class Metrics {
requestCounter: Counter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import { CoreSetup, Plugin } from '@kbn/core/server';
import { metrics } from '@opentelemetry/api-metrics';
import { metrics } from '@opentelemetry/api';
import { generateOtelMetrics } from './routes';
import { Metrics } from './monitoring/metrics';

Expand Down
5 changes: 4 additions & 1 deletion tsconfig.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -2268,7 +2268,10 @@
"@kbn/zod-helpers/*": ["src/platform/packages/shared/kbn-zod-helpers/*"],
// END AUTOMATED PACKAGE LISTING
// Allows for importing from `kibana` package for the exported types.
"@emotion/core": ["typings/@emotion"]
"@emotion/core": ["typings/@emotion"],
// We need the custom typings "proxy" because our current import-resolver doesn't support "exports" in package.json.
// We should be able to remove this once we support cjs/esm interop.
"@elastic/opentelemetry-node/sdk": ["typings/@elastic/opentelemetry-node/sdk"],
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tell TS where to look for the types of this package.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can likely add a note here as well so we don't forget to remove this in the future

},
// Support .tsx files and transform JSX into calls to React.createElement
"jsx": "react",
Expand Down
12 changes: 12 additions & 0 deletions typings/@elastic/opentelemetry-node/sdk.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

declare module '@elastic/opentelemetry-node/sdk' {
export * from '@elastic/opentelemetry-node/types/sdk';
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,23 @@
* 2.0.
*/

import { Context } from '@opentelemetry/api';
import { api, tracing } from '@elastic/opentelemetry-node/sdk';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import {
ReadableSpan,
SpanProcessor,
Span,
BatchSpanProcessor,
} from '@opentelemetry/sdk-trace-node';
import { isInInferenceContext } from './is_in_inference_context';
import { IS_ROOT_INFERENCE_SPAN_ATTRIBUTE_NAME } from './root_inference_span';

export abstract class BaseInferenceSpanProcessor implements SpanProcessor {
private delegate: SpanProcessor;
export abstract class BaseInferenceSpanProcessor implements tracing.SpanProcessor {
private delegate: tracing.SpanProcessor;

constructor(exporter: OTLPTraceExporter, scheduledDelayMillis: number) {
this.delegate = new BatchSpanProcessor(exporter, {
this.delegate = new tracing.BatchSpanProcessor(exporter, {
scheduledDelayMillis,
});
}

abstract processInferenceSpan(span: ReadableSpan): ReadableSpan;
abstract processInferenceSpan(span: tracing.ReadableSpan): tracing.ReadableSpan;

onStart(span: Span, parentContext: Context): void {
onStart(span: tracing.Span, parentContext: api.Context): void {
const shouldTrack =
(isInInferenceContext(parentContext) || span.instrumentationScope.name === 'inference') &&
span.instrumentationScope.name !== '@elastic/transport';
Expand All @@ -38,7 +32,7 @@ export abstract class BaseInferenceSpanProcessor implements SpanProcessor {
}
}

onEnd(span: ReadableSpan): void {
onEnd(span: tracing.ReadableSpan): void {
if (span.attributes._should_track) {
delete span.attributes._should_track;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { isTracingSuppressed } from '@opentelemetry/core';
import { core } from '@elastic/opentelemetry-node/sdk';
import { Span, context, propagation, trace } from '@opentelemetry/api';
import { BAGGAGE_TRACKING_BEACON_KEY, BAGGAGE_TRACKING_BEACON_VALUE } from './baggage';
import { InferenceSpanAttributes } from './with_inference_span';
Expand Down Expand Up @@ -49,7 +49,7 @@ export function createActiveInferenceSpan<T>(

let parentContext = context.active();

if (isTracingSuppressed(parentContext)) {
if (core.isTracingSuppressed(parentContext)) {
return cb();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* 2.0.
*/

import { tracing } from '@elastic/opentelemetry-node/sdk';
import { InferenceTracingLangfuseExportConfig } from '@kbn/inference-tracing-config';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { ReadableSpan } from '@opentelemetry/sdk-trace-node';
import { memoize, omit, partition } from 'lodash';
import { diag } from '@opentelemetry/api';
import { BaseInferenceSpanProcessor } from '../base_inference_span_processor';
Expand Down Expand Up @@ -48,7 +48,7 @@ export class LangfuseSpanProcessor extends BaseInferenceSpanProcessor {
};
}

override processInferenceSpan(span: ReadableSpan): ReadableSpan {
override processInferenceSpan(span: tracing.ReadableSpan): tracing.ReadableSpan {
// Langfuse doesn't understand fully semconv-compliant span events
// yet, so we translate to a format it does understand. see
// https://github.com/langfuse/langfuse/blob/c1c22a9b9b684bd45ca9436556c2599d5a23271d/web/src/features/otel/server/index.ts#L476
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
PROMPT_TEMPLATE_TEMPLATE,
LLM_TOOLS,
} from '@arizeai/openinference-semantic-conventions';
import { ReadableSpan } from '@opentelemetry/sdk-trace-base';
import { tracing } from '@elastic/opentelemetry-node/sdk';
import { omit, partition } from 'lodash';
import { ToolDefinition } from '@kbn/inference-common';
import {
Expand All @@ -45,7 +45,7 @@ import {
import { flattenAttributes } from '../util/flatten_attributes';
import { unflattenAttributes } from '../util/unflatten_attributes';

export function getChatSpan(span: ReadableSpan) {
export function getChatSpan(span: tracing.ReadableSpan) {
const [inputEvents, outputEvents] = partition(
span.events.filter((event) => event.name !== 'exception'),
(event) => event.name !== GenAISemanticConventions.GenAIChoice
Expand Down
Loading