or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

capabilities-management.mdcommand-execution.mddistributed-tracing.mddriver-services.mdhttp-communication.mdindex.mdwebdriver-operations.md

distributed-tracing.mddocs/

0

# Distributed Tracing

1

2

OpenTelemetry-based distributed tracing support for observability in distributed testing environments. This system provides comprehensive instrumentation for WebDriver operations, enabling performance monitoring, debugging, and analysis of complex test execution flows across multiple services and infrastructure components.

3

4

## Capabilities

5

6

### Tracer Interface

7

8

Core tracing interface providing context management, span creation, and trace propagation.

9

10

```java { .api }

11

/**

12

* Main tracing interface for creating and managing distributed traces

13

*/

14

public interface Tracer {

15

16

/**

17

* Get the current trace context

18

* @return Current trace context

19

*/

20

TraceContext getCurrentContext();

21

22

/**

23

* Get the propagator for trace context propagation

24

* @return Trace context propagator

25

*/

26

Propagator getPropagator();

27

28

/**

29

* Create a new attribute map for span attributes

30

* @return New attribute map instance

31

*/

32

AttributeMap createAttributeMap();

33

}

34

```

35

36

**Usage Examples:**

37

38

```java

39

import org.openqa.selenium.remote.tracing.opentelemetry.OpenTelemetryTracer;

40

import org.openqa.selenium.remote.tracing.Tracer;

41

42

// Get tracer instance

43

Tracer tracer = OpenTelemetryTracer.getInstance();

44

45

// Get current context

46

TraceContext currentContext = tracer.getCurrentContext();

47

48

// Create child context for operation

49

TraceContext childContext = currentContext.createChild("webdriver-operation");

50

```

51

52

### Span Interface

53

54

Represents a single operation within a distributed trace, providing methods for adding metadata, events, and status information.

55

56

```java { .api }

57

/**

58

* Represents a trace span - a single operation within a distributed trace

59

*/

60

public interface Span extends Closeable {

61

62

/**

63

* Set the span name

64

* @param name Operation name

65

* @return This span for chaining

66

*/

67

Span setName(String name);

68

69

/**

70

* Add string tag to span

71

* @param key Tag key

72

* @param value Tag value

73

* @return This span for chaining

74

*/

75

Span addTag(String key, String value);

76

77

/**

78

* Add boolean tag to span

79

* @param key Tag key

80

* @param value Tag value

81

* @return This span for chaining

82

*/

83

Span addTag(String key, boolean value);

84

85

/**

86

* Add numeric tag to span

87

* @param key Tag key

88

* @param value Tag value

89

* @return This span for chaining

90

*/

91

Span addTag(String key, long value);

92

93

/**

94

* Add double tag to span

95

* @param key Tag key

96

* @param value Tag value

97

* @return This span for chaining

98

*/

99

Span addTag(String key, double value);

100

101

/**

102

* Add event to span

103

* @param name Event name

104

* @return This span for chaining

105

*/

106

Span addEvent(String name);

107

108

/**

109

* Add event with attributes to span

110

* @param name Event name

111

* @param attributeMap Event attributes

112

* @return This span for chaining

113

*/

114

Span addEvent(String name, AttributeMap attributeMap);

115

116

/**

117

* Set span status

118

* @param status Span status

119

* @return This span for chaining

120

*/

121

Span setStatus(Status status);

122

123

/**

124

* Close and finish the span

125

*/

126

void close();

127

}

128

```

129

130

**Usage Examples:**

131

132

```java

133

import org.openqa.selenium.remote.tracing.Span;

134

import org.openqa.selenium.remote.tracing.Status;

135

136

// Create and configure span

137

TraceContext context = tracer.getCurrentContext();

138

TraceContext childContext = context.createChild("find-element");

139

140

try (Span span = childContext.getActiveSpan()) {

141

span.setName("findElement")

142

.addTag("locator.type", "id")

143

.addTag("locator.value", "submit-button")

144

.addTag("timeout.ms", 10000);

145

146

// Perform operation

147

WebElement element = driver.findElement(By.id("submit-button"));

148

149

// Add success event

150

span.addEvent("element-found")

151

.addTag("element.tag", element.getTagName())

152

.setStatus(Status.OK);

153

154

} catch (NoSuchElementException e) {

155

// Handle error in span

156

span.addEvent("element-not-found")

157

.addTag("error", true)

158

.addTag("error.message", e.getMessage())

159

.setStatus(Status.NOT_FOUND);

160

throw e;

161

}

162

```

163

164

### TraceContext

165

166

Manages trace context and span hierarchy, providing methods for creating child contexts and accessing active spans.

167

168

```java { .api }

169

/**

170

* Manages trace context and span hierarchy

171

*/

172

public interface TraceContext {

173

174

/**

175

* Create child context for nested operation

176

* @param operationName Name of the child operation

177

* @return Child trace context

178

*/

179

TraceContext createChild(String operationName);

180

181

/**

182

* Get the currently active span

183

* @return Active span instance

184

*/

185

Span getActiveSpan();

186

}

187

```

188

189

**Usage Examples:**

190

191

```java

192

// Create nested trace contexts

193

TraceContext rootContext = tracer.getCurrentContext();

194

TraceContext pageContext = rootContext.createChild("page-operations");

195

TraceContext elementContext = pageContext.createChild("element-interaction");

196

197

// Work with active spans

198

Span pageSpan = pageContext.getActiveSpan();

199

pageSpan.setName("navigate-to-page")

200

.addTag("url", "https://example.com");

201

202

Span elementSpan = elementContext.getActiveSpan();

203

elementSpan.setName("click-button")

204

.addTag("element.id", "submit");

205

```

206

207

### AttributeMap

208

209

Type-safe attribute management for spans, supporting different value types with proper serialization.

210

211

```java { .api }

212

/**

213

* Type-safe attribute management for spans

214

*/

215

public interface AttributeMap {

216

217

/**

218

* Add boolean attribute

219

* @param key Attribute key

220

* @param value Boolean value

221

* @return This attribute map for chaining

222

*/

223

AttributeMap put(AttributeKey<Boolean> key, Boolean value);

224

225

/**

226

* Add long attribute

227

* @param key Attribute key

228

* @param value Long value

229

* @return This attribute map for chaining

230

*/

231

AttributeMap put(AttributeKey<Long> key, Long value);

232

233

/**

234

* Add string attribute

235

* @param key Attribute key

236

* @param value String value

237

* @return This attribute map for chaining

238

*/

239

AttributeMap put(AttributeKey<String> key, String value);

240

}

241

```

242

243

### AttributeKey

244

245

Typed keys for span attributes ensuring type safety and proper serialization.

246

247

```java { .api }

248

/**

249

* Typed keys for span attributes

250

*/

251

public class AttributeKey<T> {

252

253

/**

254

* Create boolean attribute key

255

* @param key Key name

256

* @return Boolean attribute key

257

*/

258

public static AttributeKey<Boolean> booleanKey(String key);

259

260

/**

261

* Create long attribute key

262

* @param key Key name

263

* @return Long attribute key

264

*/

265

public static AttributeKey<Long> longKey(String key);

266

267

/**

268

* Create string attribute key

269

* @param key Key name

270

* @return String attribute key

271

*/

272

public static AttributeKey<String> stringKey(String key);

273

}

274

```

275

276

**Usage Examples:**

277

278

```java

279

import org.openqa.selenium.remote.tracing.AttributeKey;

280

import org.openqa.selenium.remote.tracing.AttributeMap;

281

282

// Define typed attribute keys

283

AttributeKey<String> urlKey = AttributeKey.stringKey("http.url");

284

AttributeKey<Long> durationKey = AttributeKey.longKey("operation.duration");

285

AttributeKey<Boolean> successKey = AttributeKey.booleanKey("operation.success");

286

287

// Create attribute map

288

AttributeMap attributes = tracer.createAttributeMap()

289

.put(urlKey, "https://example.com")

290

.put(durationKey, 1500L)

291

.put(successKey, true);

292

293

// Use with span events

294

span.addEvent("http-request-completed", attributes);

295

```

296

297

### TracedCommandExecutor

298

299

Command executor wrapper that automatically traces all WebDriver command executions.

300

301

```java { .api }

302

/**

303

* Command executor that adds distributed tracing to all WebDriver commands

304

*/

305

public class TracedCommandExecutor implements CommandExecutor {

306

307

/**

308

* Create traced command executor

309

* @param executor Underlying command executor

310

* @param tracer Tracer instance for creating spans

311

*/

312

public TracedCommandExecutor(CommandExecutor executor, Tracer tracer);

313

314

/**

315

* Execute command with tracing

316

* @param command WebDriver command to execute

317

* @return Command response

318

*/

319

public Response execute(Command command);

320

}

321

```

322

323

**Usage Examples:**

324

325

```java

326

import org.openqa.selenium.remote.TracedCommandExecutor;

327

import org.openqa.selenium.remote.HttpCommandExecutor;

328

329

// Create traced WebDriver

330

URL gridUrl = new URL("http://selenium-grid:4444/wd/hub");

331

CommandExecutor baseExecutor = new HttpCommandExecutor(gridUrl);

332

Tracer tracer = OpenTelemetryTracer.getInstance();

333

CommandExecutor tracedExecutor = new TracedCommandExecutor(baseExecutor, tracer);

334

335

// Use with RemoteWebDriver - all commands will be traced

336

RemoteWebDriver driver = new RemoteWebDriver(tracedExecutor, capabilities);

337

338

// Every WebDriver operation will create trace spans

339

driver.get("https://example.com"); // Creates "get" span

340

driver.findElement(By.id("btn")); // Creates "findElement" span

341

driver.quit(); // Creates "quit" span

342

```

343

344

### OpenTelemetry Implementation

345

346

Production-ready OpenTelemetry-based implementation of the tracing interfaces.

347

348

```java { .api }

349

/**

350

* OpenTelemetry-based tracer implementation

351

*/

352

public class OpenTelemetryTracer implements Tracer {

353

354

/**

355

* Get singleton tracer instance

356

* @return OpenTelemetry tracer instance

357

*/

358

public static Tracer getInstance();

359

360

// Tracer interface implementation

361

public TraceContext getCurrentContext();

362

public Propagator getPropagator();

363

public AttributeMap createAttributeMap();

364

}

365

```

366

367

### Null Implementation

368

369

No-op implementations for production environments where tracing is disabled.

370

371

```java { .api }

372

/**

373

* No-op tracer implementation for environments without tracing

374

*/

375

public class NullTracer implements Tracer {

376

377

public TraceContext getCurrentContext();

378

public Propagator getPropagator();

379

public AttributeMap createAttributeMap();

380

}

381

382

/**

383

* No-op span implementation

384

*/

385

public class NullSpan implements Span {

386

387

public Span setName(String name);

388

public Span addTag(String key, String value);

389

public Span addTag(String key, boolean value);

390

public Span addTag(String key, long value);

391

public Span addTag(String key, double value);

392

public Span addEvent(String name);

393

public Span addEvent(String name, AttributeMap attributeMap);

394

public Span setStatus(Status status);

395

public void close();

396

}

397

```

398

399

## Advanced Tracing Patterns

400

401

### Custom Span Creation

402

403

```java

404

// Manual span creation for custom operations

405

TraceContext context = tracer.getCurrentContext();

406

TraceContext customContext = context.createChild("custom-test-setup");

407

408

try (Span span = customContext.getActiveSpan()) {

409

span.setName("test-data-preparation")

410

.addTag("test.name", "loginTest")

411

.addTag("test.suite", "authentication");

412

413

// Perform setup operations

414

setupTestData();

415

416

span.addEvent("test-data-ready")

417

.setStatus(Status.OK);

418

}

419

```

420

421

### Distributed Context Propagation

422

423

```java

424

// Extract trace context from HTTP headers

425

Map<String, String> headers = getIncomingHttpHeaders();

426

Propagator propagator = tracer.getPropagator();

427

TraceContext extractedContext = propagator.extract(headers);

428

429

// Inject trace context into outgoing HTTP requests

430

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

431

propagator.inject(tracer.getCurrentContext(), outgoingHeaders);

432

httpRequest.setHeaders(outgoingHeaders);

433

```

434

435

### Performance Monitoring

436

437

```java

438

// Monitor WebDriver operation performance

439

long startTime = System.currentTimeMillis();

440

441

try (Span span = context.createChild("page-load").getActiveSpan()) {

442

span.setName("navigate-and-wait")

443

.addTag("url", targetUrl)

444

.addTag("expected.title", expectedTitle);

445

446

driver.get(targetUrl);

447

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

448

wait.until(ExpectedConditions.titleContains(expectedTitle));

449

450

long duration = System.currentTimeMillis() - startTime;

451

span.addTag("duration.ms", duration)

452

.addTag("performance.slow", duration > 5000)

453

.setStatus(Status.OK);

454

455

if (duration > 5000) {

456

span.addEvent("slow-page-load-detected");

457

}

458

}

459

```

460

461

### Error Tracking and Debugging

462

463

```java

464

// Comprehensive error tracking in spans

465

try (Span span = context.createChild("element-interaction").getActiveSpan()) {

466

span.setName("click-element")

467

.addTag("element.locator", locator.toString())

468

.addTag("retry.attempt", retryCount);

469

470

try {

471

WebElement element = driver.findElement(locator);

472

element.click();

473

474

span.addTag("element.found", true)

475

.addTag("element.tag", element.getTagName())

476

.setStatus(Status.OK);

477

478

} catch (NoSuchElementException e) {

479

span.addTag("element.found", false)

480

.addTag("error.type", "NoSuchElementException")

481

.addTag("error.message", e.getMessage())

482

.addEvent("element-not-found")

483

.setStatus(Status.NOT_FOUND);

484

throw e;

485

486

} catch (ElementNotInteractableException e) {

487

span.addTag("element.found", true)

488

.addTag("element.interactable", false)

489

.addTag("error.type", "ElementNotInteractableException")

490

.addEvent("element-not-interactable")

491

.setStatus(Status.FAILED_PRECONDITION);

492

throw e;

493

}

494

}

495

```

496

497

### Integration with Test Frameworks

498

499

```java

500

// JUnit integration example

501

@BeforeEach

502

void setupTracing() {

503

TraceContext testContext = tracer.getCurrentContext()

504

.createChild(testInfo.getDisplayName());

505

506

Span testSpan = testContext.getActiveSpan();

507

testSpan.setName("test-execution")

508

.addTag("test.class", testInfo.getTestClass().get().getSimpleName())

509

.addTag("test.method", testInfo.getTestMethod().get().getName());

510

}

511

512

@AfterEach

513

void finishTracing(TestInfo testInfo) {

514

Span testSpan = tracer.getCurrentContext().getActiveSpan();

515

if (testExecutionResult.wasSuccessful()) {

516

testSpan.setStatus(Status.OK);

517

} else {

518

testSpan.addTag("test.failed", true)

519

.setStatus(Status.ABORTED);

520

}

521

testSpan.close();

522

}

523

```