Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to properly filter span by sampling #5302

Open
blephy opened this issue Jan 6, 2025 · 0 comments
Open

How to properly filter span by sampling #5302

blephy opened this issue Jan 6, 2025 · 0 comments

Comments

@blephy
Copy link

blephy commented Jan 6, 2025

I have an API that has 3 endpoints on which I would not like to send any span to my collector.

I have designed a custom SpanSampler to filter them, but this is not working as expected.

Could you please help me to review my implementation ?

// conventions/conventions.ts
const HTTP_METHOD_BLACKLIST = ['HEAD', 'OPTIONS', 'TRACE', 'CONNECT'];
const HTTP_ROUTE_BLACKLIST = ['/liveness', '/readyness', '/metrics'];

export { HTTP_METHOD_BLACKLIST, HTTP_ROUTE_BLACKLIST };
import { SamplingDecision, TraceIdRatioBasedSampler } from '@opentelemetry/sdk-trace-node';
import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';

import { HTTP_METHOD_BLACKLIST, HTTP_ROUTE_BLACKLIST } from '../conventions/conventions.js';

import type { Attributes, AttributeValue, Context, Link, SpanKind } from '@opentelemetry/api';
import type { Sampler, SamplingResult } from '@opentelemetry/sdk-trace-node';

class CustomSampler extends TraceIdRatioBasedSampler implements Sampler {
  public readonly excludeHttpMethods = HTTP_METHOD_BLACKLIST;

  public readonly excludeHttpRoutes = HTTP_ROUTE_BLACKLIST;

  // @ts-expect-error -- this is obvious with TS ! We can do it for sure
  // eslint-disable-next-line max-params
  public override shouldSample(
    context: Context,
    traceId: string,
    _spanName: string,
    _spanKind: SpanKind,
    attributes: Attributes,
    _links: Array<Link>,
  ): SamplingResult {
    const radioSampleDecision: SamplingResult = super.shouldSample(context, traceId);

    if (radioSampleDecision.decision === SamplingDecision.NOT_RECORD) {
      return radioSampleDecision;
    }

    const maybeSpanHttpMethod: AttributeValue | undefined =
      attributes['http.method'] ?? attributes[ATTR_HTTP_REQUEST_METHOD];
    const maybeSpanHttpRoute: AttributeValue | undefined =
      attributes['http.route'] ?? attributes[ATTR_HTTP_ROUTE];

    const normalizedHttpMethod = maybeSpanHttpMethod?.toString().toUpperCase() ?? 'GET';
    const normalizedHttpRoute = maybeSpanHttpRoute?.toString().toLowerCase() ?? '/';

    if (this.excludeHttpMethods.includes(normalizedHttpMethod)) {
      return {
        ...radioSampleDecision,
        decision: SamplingDecision.NOT_RECORD,
      };
    }

    if (this.excludeHttpRoutes.includes(normalizedHttpRoute)) {
      return {
        ...radioSampleDecision,
        decision: SamplingDecision.NOT_RECORD,
      };
    }

    return radioSampleDecision;
  }
}

export { CustomSampler };

My sampler is triggered, and my decision are returned, but SamplingDecision.NOT_RECORD is not doing anything, span are still sent on my collector

Capture d’écran 2025-01-06 à 17 58 32 Capture d’écran 2025-01-06 à 17 58 37

What did i missed ?

@blephy blephy changed the title How to properly sample a span How to properly filter span by sampling Jan 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant