or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

context-keys-scoping.mdcontext-propagation.mdcore-context.mdexecutor-integration.mdfunction-wrapping.mdimplicit-context-values.mdindex.mdstorage-customization.md

context-propagation.mddocs/

0

# Context Propagation

1

2

Context propagation enables transmission of contextual information across service boundaries using configurable text map propagators. This is essential for distributed tracing, baggage propagation, and other cross-cutting concerns in microservices architectures.

3

4

## Context Propagators

5

6

### Creating Context Propagators

7

8

Creates a ContextPropagators instance with a text map propagator.

9

10

```java { .api }

11

static ContextPropagators create(TextMapPropagator textPropagator);

12

```

13

14

**Parameters:**

15

- `textPropagator` - The text map propagator to use

16

17

**Returns:** A ContextPropagators instance

18

19

**Usage Example:**

20

```java

21

// Create with single propagator

22

TextMapPropagator traceContext = HttpTraceContext.getInstance();

23

ContextPropagators propagators = ContextPropagators.create(traceContext);

24

25

// Create with composite propagator

26

TextMapPropagator composite = TextMapPropagator.composite(

27

HttpTraceContext.getInstance(),

28

W3CBaggagePropagator.getInstance(),

29

new CustomPropagator()

30

);

31

ContextPropagators propagators = ContextPropagators.create(composite);

32

```

33

34

### No-op Context Propagators

35

36

Creates a no-op ContextPropagators that performs no injection or extraction.

37

38

```java { .api }

39

static ContextPropagators noop();

40

```

41

42

**Usage Example:**

43

```java

44

ContextPropagators noopPropagators = ContextPropagators.noop();

45

TextMapPropagator propagator = noopPropagators.getTextMapPropagator();

46

// propagator.fields() returns empty collection

47

// propagator.inject() does nothing

48

// propagator.extract() returns original context

49

```

50

51

### Get Text Map Propagator

52

53

Returns the composite text map propagator.

54

55

```java { .api }

56

TextMapPropagator getTextMapPropagator();

57

```

58

59

**Usage Example:**

60

```java

61

ContextPropagators propagators = ContextPropagators.create(somePropagator);

62

TextMapPropagator textMapPropagator = propagators.getTextMapPropagator();

63

64

// Use for injection/extraction

65

Map<String, String> headers = new HashMap<>();

66

textMapPropagator.inject(Context.current(), headers, Map::put);

67

```

68

69

## Text Map Propagation

70

71

### Composite Propagators

72

73

Creates a composite propagator that delegates to multiple propagators.

74

75

```java { .api }

76

static TextMapPropagator composite(TextMapPropagator... propagators);

77

static TextMapPropagator composite(Iterable<TextMapPropagator> propagators);

78

```

79

80

**Usage Example:**

81

```java

82

// Array version

83

TextMapPropagator composite = TextMapPropagator.composite(

84

HttpTraceContext.getInstance(),

85

W3CBaggagePropagator.getInstance(),

86

JaegerPropagator.getInstance()

87

);

88

89

// Iterable version

90

List<TextMapPropagator> propagatorList = Arrays.asList(

91

HttpTraceContext.getInstance(),

92

CustomPropagator.getInstance()

93

);

94

TextMapPropagator composite = TextMapPropagator.composite(propagatorList);

95

```

96

97

### No-op Text Map Propagator

98

99

Creates a no-op propagator that performs no operations.

100

101

```java { .api }

102

static TextMapPropagator noop();

103

```

104

105

### Get Propagation Fields

106

107

Returns the field names that will be used for propagation.

108

109

```java { .api }

110

Collection<String> fields();

111

```

112

113

**Usage Example:**

114

```java

115

TextMapPropagator propagator = TextMapPropagator.composite(

116

HttpTraceContext.getInstance(),

117

W3CBaggagePropagator.getInstance()

118

);

119

120

Collection<String> fields = propagator.fields();

121

// Might return: ["traceparent", "tracestate", "baggage"]

122

123

// Clear fields before injection if reusing carrier

124

for (String field : fields) {

125

headers.remove(field);

126

}

127

```

128

129

### Context Injection

130

131

Injects context data into a carrier for downstream consumption.

132

133

```java { .api }

134

<C> void inject(Context context, C carrier, TextMapSetter<C> setter);

135

```

136

137

**Parameters:**

138

- `context` - The context containing values to inject

139

- `carrier` - The carrier to inject into (e.g., HTTP headers)

140

- `setter` - Function to set values in the carrier

141

142

**Usage Example:**

143

```java

144

// HTTP client injection

145

HttpURLConnection connection = (HttpURLConnection) url.openConnection();

146

Map<String, String> headers = new HashMap<>();

147

148

// Inject current context

149

TextMapPropagator propagator = propagators.getTextMapPropagator();

150

propagator.inject(Context.current(), headers, (map, key, value) -> {

151

map.put(key, value);

152

connection.setRequestProperty(key, value);

153

});

154

155

// Alternative with lambda

156

propagator.inject(Context.current(), connection, HttpURLConnection::setRequestProperty);

157

```

158

159

### Context Extraction

160

161

Extracts context data from a carrier and merges with existing context.

162

163

```java { .api }

164

<C> Context extract(Context context, C carrier, TextMapGetter<C> getter);

165

```

166

167

**Parameters:**

168

- `context` - The base context to merge extracted data into

169

- `carrier` - The carrier containing propagated data

170

- `getter` - Function to retrieve values from the carrier

171

172

**Returns:** A new Context with extracted data merged in

173

174

**Usage Example:**

175

```java

176

// HTTP server extraction

177

HttpServletRequest request = getRequest();

178

179

TextMapPropagator propagator = propagators.getTextMapPropagator();

180

Context extractedContext = propagator.extract(

181

Context.current(),

182

request,

183

new TextMapGetter<HttpServletRequest>() {

184

@Override

185

public Iterable<String> keys(HttpServletRequest carrier) {

186

return Collections.list(carrier.getHeaderNames());

187

}

188

189

@Override

190

public String get(HttpServletRequest carrier, String key) {

191

return carrier.getHeader(key);

192

}

193

}

194

);

195

196

// Use extracted context

197

try (Scope scope = extractedContext.makeCurrent()) {

198

processRequest();

199

}

200

```

201

202

## Text Map Getters and Setters

203

204

### Text Map Getter

205

206

Interface for extracting values from carriers.

207

208

```java { .api }

209

interface TextMapGetter<C> {

210

Iterable<String> keys(C carrier);

211

String get(C carrier, String key);

212

default Iterator<String> getAll(C carrier, String key);

213

}

214

```

215

216

**Usage Example:**

217

```java

218

// HTTP headers getter

219

TextMapGetter<Map<String, String>> httpGetter = new TextMapGetter<Map<String, String>>() {

220

@Override

221

public Iterable<String> keys(Map<String, String> carrier) {

222

return carrier.keySet();

223

}

224

225

@Override

226

public String get(Map<String, String> carrier, String key) {

227

return carrier.get(key);

228

}

229

230

@Override

231

public Iterator<String> getAll(Map<String, String> carrier, String key) {

232

String value = carrier.get(key);

233

return value != null ? Collections.singleton(value).iterator()

234

: Collections.emptyIterator();

235

}

236

};

237

```

238

239

### Text Map Setter

240

241

Interface for setting values in carriers.

242

243

```java { .api }

244

interface TextMapSetter<C> {

245

void set(C carrier, String key, String value);

246

}

247

```

248

249

**Usage Example:**

250

```java

251

// HTTP headers setter

252

TextMapSetter<HttpURLConnection> httpSetter = (connection, key, value) -> {

253

connection.setRequestProperty(key, value);

254

};

255

256

// Map setter

257

TextMapSetter<Map<String, String>> mapSetter = Map::put;

258

```

259

260

## Complete Propagation Examples

261

262

### HTTP Client with Propagation

263

264

```java

265

public class HttpClientWithPropagation {

266

private final ContextPropagators propagators;

267

268

public HttpClientWithPropagation(ContextPropagators propagators) {

269

this.propagators = propagators;

270

}

271

272

public String makeRequest(String url) throws IOException {

273

HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();

274

275

// Inject current context into HTTP headers

276

TextMapPropagator propagator = propagators.getTextMapPropagator();

277

propagator.inject(Context.current(), connection, (conn, key, value) -> {

278

conn.setRequestProperty(key, value);

279

});

280

281

// Make request

282

try (InputStream is = connection.getInputStream()) {

283

return new String(is.readAllBytes(), StandardCharsets.UTF_8);

284

}

285

}

286

}

287

```

288

289

### HTTP Server with Propagation

290

291

```java

292

public class HttpServerWithPropagation {

293

private final ContextPropagators propagators;

294

295

public HttpServerWithPropagation(ContextPropagators propagators) {

296

this.propagators = propagators;

297

}

298

299

public void handleRequest(HttpServletRequest request, HttpServletResponse response) {

300

// Extract context from incoming request

301

TextMapPropagator propagator = propagators.getTextMapPropagator();

302

Context extractedContext = propagator.extract(

303

Context.current(),

304

request,

305

new HttpServletRequestGetter()

306

);

307

308

// Process request with extracted context

309

try (Scope scope = extractedContext.makeCurrent()) {

310

String result = processRequest(request);

311

response.getWriter().write(result);

312

} catch (IOException e) {

313

response.setStatus(500);

314

}

315

}

316

317

private static class HttpServletRequestGetter implements TextMapGetter<HttpServletRequest> {

318

@Override

319

public Iterable<String> keys(HttpServletRequest request) {

320

return Collections.list(request.getHeaderNames());

321

}

322

323

@Override

324

public String get(HttpServletRequest request, String key) {

325

return request.getHeader(key);

326

}

327

}

328

}

329

```

330

331

### Custom Propagator Implementation

332

333

```java

334

public class CustomBaggagePropagator implements TextMapPropagator {

335

private static final String BAGGAGE_HEADER = "custom-baggage";

336

private static final Collection<String> FIELDS = Collections.singleton(BAGGAGE_HEADER);

337

338

@Override

339

public Collection<String> fields() {

340

return FIELDS;

341

}

342

343

@Override

344

public <C> void inject(Context context, C carrier, TextMapSetter<C> setter) {

345

String baggage = context.get(CUSTOM_BAGGAGE_KEY);

346

if (baggage != null) {

347

setter.set(carrier, BAGGAGE_HEADER, baggage);

348

}

349

}

350

351

@Override

352

public <C> Context extract(Context context, C carrier, TextMapGetter<C> getter) {

353

String baggage = getter.get(carrier, BAGGAGE_HEADER);

354

if (baggage != null) {

355

return context.with(CUSTOM_BAGGAGE_KEY, baggage);

356

}

357

return context;

358

}

359

360

private static final ContextKey<String> CUSTOM_BAGGAGE_KEY =

361

ContextKey.named("custom-baggage");

362

}

363

```

364

365

## Integration Patterns

366

367

### Spring Boot Integration

368

369

```java

370

@Configuration

371

public class TracingConfiguration {

372

373

@Bean

374

public ContextPropagators contextPropagators() {

375

return ContextPropagators.create(

376

TextMapPropagator.composite(

377

HttpTraceContext.getInstance(),

378

W3CBaggagePropagator.getInstance()

379

)

380

);

381

}

382

383

@Bean

384

public RestTemplate restTemplate(ContextPropagators propagators) {

385

RestTemplate restTemplate = new RestTemplate();

386

restTemplate.getInterceptors().add(new TracingClientInterceptor(propagators));

387

return restTemplate;

388

}

389

}

390

```

391

392

### Asynchronous Propagation

393

394

```java

395

public class AsyncPropagationExample {

396

private final ContextPropagators propagators;

397

398

public CompletableFuture<String> processAsync(String data) {

399

// Capture current context for propagation

400

Context currentContext = Context.current();

401

402

return CompletableFuture.supplyAsync(() -> {

403

// Manually apply context in async operation

404

try (Scope scope = currentContext.makeCurrent()) {

405

return processWithContext(data);

406

}

407

});

408

}

409

410

public void sendMessage(String message) {

411

// Serialize context for message queue

412

Map<String, String> headers = new HashMap<>();

413

TextMapPropagator propagator = propagators.getTextMapPropagator();

414

propagator.inject(Context.current(), headers, Map::put);

415

416

// Send message with headers

417

messageQueue.send(message, headers);

418

}

419

420

public void receiveMessage(String message, Map<String, String> headers) {

421

// Deserialize context from message headers

422

TextMapPropagator propagator = propagators.getTextMapPropagator();

423

424

TextMapGetter<Map<String, String>> getter = new TextMapGetter<Map<String, String>>() {

425

@Override

426

public Iterable<String> keys(Map<String, String> carrier) {

427

return carrier.keySet();

428

}

429

430

@Override

431

public String get(Map<String, String> carrier, String key) {

432

return carrier.get(key);

433

}

434

};

435

436

Context extractedContext = propagator.extract(Context.current(), headers, getter);

437

438

try (Scope scope = extractedContext.makeCurrent()) {

439

processMessage(message);

440

}

441

}

442

}