or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdplatform.mdsamplers.mdspan-exporters.mdspan-processors.mdtracer-provider.md

samplers.mddocs/

0

# Samplers

1

2

Samplers control which traces are collected and recorded by making sampling decisions for each span. OpenTelemetry SDK Trace Base provides several built-in sampling strategies including always-on, always-off, ratio-based, and parent-aware samplers.

3

4

## Capabilities

5

6

### Core Sampler Interface

7

8

All samplers implement the base Sampler interface for consistent sampling decisions.

9

10

```typescript { .api }

11

/**

12

* Interface representing a sampler for controlling trace collection

13

*/

14

interface Sampler {

15

/**

16

* Checks whether span needs to be created and tracked

17

* @param context - Parent Context which may contain a span

18

* @param traceId - Trace ID of the span to be created

19

* @param spanName - Name of the span to be created

20

* @param spanKind - Kind of the span to be created

21

* @param attributes - Initial set of attributes for the span

22

* @param links - Collection of links associated with the span

23

* @returns SamplingResult with decision and optional attributes

24

*/

25

shouldSample(

26

context: Context,

27

traceId: string,

28

spanName: string,

29

spanKind: SpanKind,

30

attributes: Attributes,

31

links: Link[]

32

): SamplingResult;

33

34

/**

35

* Returns the sampler name or short description with configuration

36

*/

37

toString(): string;

38

}

39

40

/**

41

* Sampling result containing decision and additional attributes

42

*/

43

interface SamplingResult {

44

/** Sampling decision determining how the span will be handled */

45

decision: SamplingDecision;

46

/** Immutable list of attributes to add to the span */

47

attributes?: Readonly<Attributes>;

48

/** TraceState to associate with the span through SpanContext */

49

traceState?: TraceState;

50

}

51

52

/**

53

* Sampling decision that determines how a span will be recorded and collected

54

*/

55

enum SamplingDecision {

56

/** Span.isRecording() === false, span will not be recorded */

57

NOT_RECORD,

58

/** Span.isRecording() === true, but Sampled flag not set */

59

RECORD,

60

/** Span.isRecording() === true AND Sampled flag set */

61

RECORD_AND_SAMPLED

62

}

63

```

64

65

### AlwaysOnSampler

66

67

Sampler that always samples all traces, useful for development and debugging.

68

69

```typescript { .api }

70

/**

71

* Sampler that samples all traces

72

*/

73

class AlwaysOnSampler implements Sampler {

74

/**

75

* Always returns RECORD_AND_SAMPLED decision

76

*/

77

shouldSample(

78

context: Context,

79

traceId: string,

80

spanName: string,

81

spanKind: SpanKind,

82

attributes: Attributes,

83

links: Link[]

84

): SamplingResult;

85

86

/**

87

* Returns "AlwaysOnSampler"

88

*/

89

toString(): string;

90

}

91

```

92

93

**Usage Examples:**

94

95

```typescript

96

import { BasicTracerProvider, AlwaysOnSampler } from '@opentelemetry/sdk-trace-base';

97

98

// Enable sampling for all traces

99

const provider = new BasicTracerProvider({

100

sampler: new AlwaysOnSampler()

101

});

102

103

// Useful for development environments

104

const devProvider = new BasicTracerProvider({

105

sampler: new AlwaysOnSampler(),

106

resource: new Resource({

107

'service.name': 'dev-service',

108

'deployment.environment': 'development'

109

})

110

});

111

```

112

113

### AlwaysOffSampler

114

115

Sampler that never samples traces, useful for disabling tracing or testing scenarios.

116

117

```typescript { .api }

118

/**

119

* Sampler that samples no traces

120

*/

121

class AlwaysOffSampler implements Sampler {

122

/**

123

* Always returns NOT_RECORD decision

124

*/

125

shouldSample(

126

context: Context,

127

traceId: string,

128

spanName: string,

129

spanKind: SpanKind,

130

attributes: Attributes,

131

links: Link[]

132

): SamplingResult;

133

134

/**

135

* Returns "AlwaysOffSampler"

136

*/

137

toString(): string;

138

}

139

```

140

141

**Usage Examples:**

142

143

```typescript

144

import { BasicTracerProvider, AlwaysOffSampler } from '@opentelemetry/sdk-trace-base';

145

146

// Disable all tracing

147

const provider = new BasicTracerProvider({

148

sampler: new AlwaysOffSampler()

149

});

150

151

// Conditional sampling based on environment

152

const sampler = process.env.NODE_ENV === 'test'

153

? new AlwaysOffSampler()

154

: new AlwaysOnSampler();

155

156

const provider = new BasicTracerProvider({ sampler });

157

```

158

159

### TraceIdRatioBasedSampler

160

161

Sampler that samples a deterministic fraction of traces based on trace ID, ensuring consistent sampling decisions across services.

162

163

```typescript { .api }

164

/**

165

* Sampler that samples a deterministic fraction of traces based on trace ID

166

*/

167

class TraceIdRatioBasedSampler implements Sampler {

168

/**

169

* @param ratio - Sampling ratio between 0.0 and 1.0 (default: 0)

170

*/

171

constructor(ratio?: number);

172

173

/**

174

* Makes sampling decision based on trace ID hash

175

* Same trace ID always produces the same decision

176

*/

177

shouldSample(

178

context: Context,

179

traceId: string,

180

spanName: string,

181

spanKind: SpanKind,

182

attributes: Attributes,

183

links: Link[]

184

): SamplingResult;

185

186

/**

187

* Returns "TraceIdRatioBased{ratio}"

188

*/

189

toString(): string;

190

}

191

```

192

193

**Behavior Details:**

194

- Ratio is normalized to be between 0.0 and 1.0

195

- Uses deterministic hash of trace ID for consistent decisions

196

- Same trace ID will always produce the same sampling decision across all services

197

- Ratio of 0.0 = never sample, 1.0 = always sample

198

199

**Usage Examples:**

200

201

```typescript

202

import { BasicTracerProvider, TraceIdRatioBasedSampler } from '@opentelemetry/sdk-trace-base';

203

204

// Sample 10% of traces

205

const provider = new BasicTracerProvider({

206

sampler: new TraceIdRatioBasedSampler(0.1)

207

});

208

209

// Sample 50% of traces

210

const provider = new BasicTracerProvider({

211

sampler: new TraceIdRatioBasedSampler(0.5)

212

});

213

214

// Environment-based sampling rate

215

const samplingRate = parseFloat(process.env.TRACE_SAMPLING_RATE || '0.1');

216

const provider = new BasicTracerProvider({

217

sampler: new TraceIdRatioBasedSampler(samplingRate)

218

});

219

220

// No sampling (equivalent to AlwaysOffSampler)

221

const noSampleProvider = new BasicTracerProvider({

222

sampler: new TraceIdRatioBasedSampler(0.0)

223

});

224

```

225

226

### ParentBasedSampler

227

228

Composite sampler that respects parent span's sampling decision when available, otherwise delegates to a root sampler. This ensures sampling consistency across distributed traces.

229

230

```typescript { .api }

231

/**

232

* Sampler that respects parent span sampling decisions with fallback samplers

233

*/

234

class ParentBasedSampler implements Sampler {

235

constructor(config: ParentBasedSamplerConfig);

236

237

/**

238

* Makes sampling decision based on parent context or delegates to appropriate sampler

239

*/

240

shouldSample(

241

context: Context,

242

traceId: string,

243

spanName: string,

244

spanKind: SpanKind,

245

attributes: Attributes,

246

links: Link[]

247

): SamplingResult;

248

249

/**

250

* Returns string representation with root sampler info

251

*/

252

toString(): string;

253

}

254

255

/**

256

* Configuration for ParentBasedSampler with different samplers for different scenarios

257

*/

258

interface ParentBasedSamplerConfig {

259

/** Required: Sampler to use when there is no parent span */

260

root: Sampler;

261

262

/** Sampler for remote parent that was sampled (default: AlwaysOnSampler) */

263

remoteParentSampled?: Sampler;

264

265

/** Sampler for remote parent that was not sampled (default: AlwaysOffSampler) */

266

remoteParentNotSampled?: Sampler;

267

268

/** Sampler for local parent that was sampled (default: AlwaysOnSampler) */

269

localParentSampled?: Sampler;

270

271

/** Sampler for local parent that was not sampled (default: AlwaysOffSampler) */

272

localParentNotSampled?: Sampler;

273

}

274

```

275

276

**Sampling Logic:**

277

1. If parent span exists and was sampled → delegate to appropriate sampled sampler

278

2. If parent span exists and was not sampled → delegate to appropriate not-sampled sampler

279

3. If no parent span exists → delegate to root sampler

280

4. Local vs remote parent determined by trace flags

281

282

**Usage Examples:**

283

284

```typescript

285

import {

286

BasicTracerProvider,

287

ParentBasedSampler,

288

TraceIdRatioBasedSampler,

289

AlwaysOnSampler,

290

AlwaysOffSampler

291

} from '@opentelemetry/sdk-trace-base';

292

293

// Basic parent-based sampling with ratio-based root

294

const provider = new BasicTracerProvider({

295

sampler: new ParentBasedSampler({

296

root: new TraceIdRatioBasedSampler(0.1) // 10% of new traces

297

})

298

});

299

300

// Advanced parent-based configuration

301

const provider = new BasicTracerProvider({

302

sampler: new ParentBasedSampler({

303

root: new TraceIdRatioBasedSampler(0.05), // 5% of new traces

304

remoteParentSampled: new AlwaysOnSampler(), // Always continue sampled remote traces

305

remoteParentNotSampled: new AlwaysOffSampler(), // Never sample unsampled remote traces

306

localParentSampled: new AlwaysOnSampler(), // Always continue sampled local traces

307

localParentNotSampled: new TraceIdRatioBasedSampler(0.01) // 1% chance to sample unsampled local

308

})

309

});

310

311

// Production-ready configuration

312

const provider = new BasicTracerProvider({

313

sampler: new ParentBasedSampler({

314

root: new TraceIdRatioBasedSampler(0.1), // Sample 10% of root traces

315

// Use defaults for parent-based decisions (respects parent sampling)

316

})

317

});

318

```

319

320

### Environment Configuration

321

322

Samplers can be configured through environment variables for runtime control.

323

324

**Environment Variables:**

325

- `OTEL_TRACES_SAMPLER` - Sampler type

326

- `OTEL_TRACES_SAMPLER_ARG` - Sampler argument (ratio for ratio-based samplers)

327

328

**Supported Sampler Values:**

329

- `always_off``AlwaysOffSampler`

330

- `always_on``AlwaysOnSampler`

331

- `traceidratio``TraceIdRatioBasedSampler` (requires `OTEL_TRACES_SAMPLER_ARG`)

332

- `parentbased_always_off``ParentBasedSampler` with `AlwaysOffSampler` root

333

- `parentbased_always_on``ParentBasedSampler` with `AlwaysOnSampler` root

334

- `parentbased_traceidratio``ParentBasedSampler` with `TraceIdRatioBasedSampler` root

335

336

**Usage Examples:**

337

338

```bash

339

# Set environment variables

340

export OTEL_TRACES_SAMPLER=traceidratio

341

export OTEL_TRACES_SAMPLER_ARG=0.1

342

343

# Or parent-based with ratio

344

export OTEL_TRACES_SAMPLER=parentbased_traceidratio

345

export OTEL_TRACES_SAMPLER_ARG=0.05

346

```

347

348

```typescript

349

// Configuration will be loaded from environment variables

350

const provider = new BasicTracerProvider({

351

// Sampler will be built from OTEL_TRACES_SAMPLER env var

352

// Other configuration can override env vars

353

resource: new Resource({

354

'service.name': 'my-service'

355

})

356

});

357

```

358

359

### Custom Sampler Implementation

360

361

You can implement custom samplers by implementing the Sampler interface.

362

363

**Usage Examples:**

364

365

```typescript

366

import { Sampler, SamplingResult, SamplingDecision } from '@opentelemetry/sdk-trace-base';

367

368

// Custom sampler that samples based on operation name

369

class OperationBasedSampler implements Sampler {

370

constructor(private sampledOperations: Set<string>) {}

371

372

shouldSample(

373

context: Context,

374

traceId: string,

375

spanName: string,

376

spanKind: SpanKind,

377

attributes: Attributes,

378

links: Link[]

379

): SamplingResult {

380

const decision = this.sampledOperations.has(spanName)

381

? SamplingDecision.RECORD_AND_SAMPLED

382

: SamplingDecision.NOT_RECORD;

383

384

return { decision };

385

}

386

387

toString(): string {

388

return `OperationBasedSampler{${Array.from(this.sampledOperations).join(',')}}`;

389

}

390

}

391

392

// Use custom sampler

393

const provider = new BasicTracerProvider({

394

sampler: new OperationBasedSampler(new Set([

395

'user-login',

396

'payment-process',

397

'critical-operation'

398

]))

399

});

400

```