or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

domain-management.mdindex.mdjavascript-integration.mdlogging-operations.mdnetwork-operations.mdruntime-events.mdtarget-management.md

logging-operations.mddocs/

0

# Browser Logging

1

2

Browser console log collection, filtering, and event stream management with level conversion and timestamp handling through the v115Log class.

3

4

## Capabilities

5

6

### Log Domain

7

8

Comprehensive browser console log management with event streaming and level conversion.

9

10

```java { .api }

11

/**

12

* Browser log domain for console log collection and management

13

* Implements the idealized Log interface for version independence

14

*/

15

public class v115Log implements Log {

16

/**

17

* Enable log domain for console log collection

18

* @return Command to enable log domain

19

*/

20

public Command<Void> enable();

21

22

/**

23

* Clear all browser console logs

24

* @return Command to clear browser logs

25

*/

26

public Command<Void> clear();

27

28

/**

29

* Get log entry added event stream

30

* @return Event stream for new log entries

31

*/

32

public Event<LogEntry> entryAdded();

33

}

34

```

35

36

### Log Collection

37

38

Enable browser log collection and receive log entries as they are created.

39

40

**Usage Examples:**

41

42

```java

43

import org.openqa.selenium.devtools.v115.v115Log;

44

import org.openqa.selenium.devtools.idealized.log.model.LogEntry;

45

import java.util.logging.Level;

46

47

// Create log domain

48

v115Log log = new v115Log();

49

50

// Enable log collection

51

devTools.send(log.enable());

52

53

// Listen for log entries

54

devTools.addListener(log.entryAdded(), logEntry -> {

55

System.out.println("Browser Log Entry:");

56

System.out.println(" Kind: " + logEntry.getKind());

57

58

org.openqa.selenium.logging.LogEntry entry = logEntry.getEntry();

59

System.out.println(" Level: " + entry.getLevel());

60

System.out.println(" Timestamp: " + new Date(entry.getTimestamp()));

61

System.out.println(" Message: " + entry.getMessage());

62

System.out.println();

63

});

64

65

// Navigate and generate logs

66

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

67

68

// Generate console logs from browser

69

driver.executeScript("console.log('Information message');");

70

driver.executeScript("console.warn('Warning message');");

71

driver.executeScript("console.error('Error message');");

72

73

// JavaScript error

74

driver.executeScript("throw new Error('Test error');");

75

```

76

77

### Log Level Conversion

78

79

The v115Log class automatically converts CDP log levels to standard Java logging levels.

80

81

**Supported Level Mappings:**

82

83

```java { .api }

84

/**

85

* Convert CDP log level to Java logging level

86

* @param level CDP LogEntry.Level enum

87

* @return Java logging Level

88

*/

89

private Level fromCdpLevel(LogEntry.Level level);

90

```

91

92

**Level Conversion Table:**

93

94

| CDP Level | Java Level | Description |

95

|-----------|------------|-------------|

96

| `verbose` | `FINEST` | Detailed debug information |

97

| `info` | `INFO` | General information messages |

98

| `warning` | `WARNING` | Warning conditions |

99

| `error` | `SEVERE` | Error conditions |

100

| (default) | `INFO` | Fallback for unknown levels |

101

102

**Usage Examples:**

103

104

```java

105

// The level conversion happens automatically in log event processing

106

devTools.addListener(log.entryAdded(), logEntry -> {

107

org.openqa.selenium.logging.LogEntry entry = logEntry.getEntry();

108

Level javaLevel = entry.getLevel();

109

110

// Handle different log levels

111

switch (javaLevel.getName()) {

112

case "SEVERE" -> System.err.println("ERROR: " + entry.getMessage());

113

case "WARNING" -> System.out.println("WARN: " + entry.getMessage());

114

case "INFO" -> System.out.println("INFO: " + entry.getMessage());

115

case "FINEST" -> System.out.println("DEBUG: " + entry.getMessage());

116

default -> System.out.println("LOG: " + entry.getMessage());

117

}

118

});

119

```

120

121

### Log Management

122

123

Clear browser logs and manage log collection lifecycle.

124

125

**Usage Examples:**

126

127

```java

128

// Clear existing logs before starting test

129

devTools.send(log.clear());

130

131

// Run test operations

132

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

133

performTestOperations();

134

135

// Clear logs after test

136

devTools.send(log.clear());

137

138

// Disable log collection when done

139

// Note: Log domain doesn't have explicit disable - use DevTools session lifecycle

140

```

141

142

### Advanced Log Filtering

143

144

Filter and categorize log entries based on content and level.

145

146

**Usage Examples:**

147

148

```java

149

import java.util.concurrent.ConcurrentHashMap;

150

import java.util.concurrent.atomic.AtomicInteger;

151

152

// Set up log categorization

153

Map<String, AtomicInteger> logCounts = new ConcurrentHashMap<>();

154

List<String> errorMessages = Collections.synchronizedList(new ArrayList<>());

155

List<String> networkLogs = Collections.synchronizedList(new ArrayList<>());

156

157

devTools.addListener(log.entryAdded(), logEntry -> {

158

org.openqa.selenium.logging.LogEntry entry = logEntry.getEntry();

159

String message = entry.getMessage();

160

Level level = entry.getLevel();

161

162

// Count logs by level

163

String levelName = level.getName();

164

logCounts.computeIfAbsent(levelName, k -> new AtomicInteger(0)).incrementAndGet();

165

166

// Collect error messages

167

if (level == Level.SEVERE) {

168

errorMessages.add(message);

169

}

170

171

// Filter network-related logs

172

if (message.contains("Failed to load resource") ||

173

message.contains("XMLHttpRequest") ||

174

message.contains("fetch")) {

175

networkLogs.add(message);

176

}

177

178

// Filter security warnings

179

if (message.contains("Mixed Content") ||

180

message.contains("Insecure") ||

181

message.contains("HTTPS")) {

182

System.out.println("SECURITY WARNING: " + message);

183

}

184

});

185

186

// Generate logs and analyze

187

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

188

performComplexOperations();

189

190

// Print analysis

191

System.out.println("\nLog Analysis:");

192

logCounts.forEach((level, count) ->

193

System.out.println(level + ": " + count.get() + " entries"));

194

195

System.out.println("\nErrors found: " + errorMessages.size());

196

errorMessages.forEach(error -> System.out.println(" - " + error));

197

198

System.out.println("\nNetwork issues: " + networkLogs.size());

199

networkLogs.forEach(networkLog -> System.out.println(" - " + networkLog));

200

```

201

202

### Log Pattern Matching

203

204

Identify specific log patterns for automated testing and monitoring.

205

206

**Usage Examples:**

207

208

```java

209

import java.util.regex.Pattern;

210

import java.util.concurrent.CompletableFuture;

211

212

// Set up pattern-based log monitoring

213

Pattern errorPattern = Pattern.compile("Error:.*|Uncaught.*|TypeError:.*", Pattern.CASE_INSENSITIVE);

214

Pattern apiErrorPattern = Pattern.compile("HTTP.*[45]\\d\\d|API.*error|Request failed", Pattern.CASE_INSENSITIVE);

215

Pattern performancePattern = Pattern.compile("Performance.*|Slow.*|Timeout.*", Pattern.CASE_INSENSITIVE);

216

217

CompletableFuture<String> firstErrorFuture = new CompletableFuture<>();

218

List<String> apiErrors = Collections.synchronizedList(new ArrayList<>());

219

List<String> performanceIssues = Collections.synchronizedList(new ArrayList<>());

220

221

devTools.addListener(log.entryAdded(), logEntry -> {

222

String message = logEntry.getEntry().getMessage();

223

224

// Detect first JavaScript error

225

if (errorPattern.matcher(message).find() && !firstErrorFuture.isDone()) {

226

firstErrorFuture.complete(message);

227

}

228

229

// Collect API errors

230

if (apiErrorPattern.matcher(message).find()) {

231

apiErrors.add(message);

232

}

233

234

// Collect performance issues

235

if (performancePattern.matcher(message).find()) {

236

performanceIssues.add(message);

237

}

238

});

239

240

// Run operations and wait for specific conditions

241

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

242

243

try {

244

// Wait for first error (with timeout)

245

String firstError = firstErrorFuture.get(10, TimeUnit.SECONDS);

246

System.out.println("First error detected: " + firstError);

247

} catch (TimeoutException e) {

248

System.out.println("No errors detected within timeout");

249

} catch (Exception e) {

250

System.err.println("Error waiting for log: " + e.getMessage());

251

}

252

253

// Analyze collected issues

254

System.out.println("API errors detected: " + apiErrors.size());

255

System.out.println("Performance issues detected: " + performanceIssues.size());

256

```

257

258

### Integration with WebDriver Logs

259

260

Combine DevTools logs with WebDriver's built-in logging capabilities.

261

262

**Usage Examples:**

263

264

```java

265

import org.openqa.selenium.logging.LogType;

266

import org.openqa.selenium.logging.LoggingPreferences;

267

import org.openqa.selenium.chrome.ChromeOptions;

268

import org.openqa.selenium.logging.LogEntries;

269

270

// Set up WebDriver logging (complementary to DevTools logging)

271

ChromeOptions options = new ChromeOptions();

272

LoggingPreferences logPrefs = new LoggingPreferences();

273

logPrefs.enable(LogType.BROWSER, Level.ALL);

274

logPrefs.enable(LogType.PERFORMANCE, Level.INFO);

275

options.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);

276

277

ChromeDriver driver = new ChromeDriver(options);

278

DevTools devTools = driver.getDevTools();

279

devTools.createSession();

280

281

// Enable DevTools logging

282

v115Log devToolsLog = new v115Log();

283

devTools.send(devToolsLog.enable());

284

285

// Collect logs from both sources

286

List<String> devToolsLogs = Collections.synchronizedList(new ArrayList<>());

287

List<String> webDriverLogs = Collections.synchronizedList(new ArrayList<>());

288

289

// DevTools log collection

290

devTools.addListener(devToolsLog.entryAdded(), logEntry -> {

291

devToolsLogs.add("DevTools: " + logEntry.getEntry().getMessage());

292

});

293

294

// Perform operations

295

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

296

performTestOperations();

297

298

// Collect WebDriver logs

299

LogEntries browserLogs = driver.manage().logs().get(LogType.BROWSER);

300

browserLogs.forEach(entry -> {

301

webDriverLogs.add("WebDriver: " + entry.getMessage());

302

});

303

304

// Compare and analyze both log sources

305

System.out.println("DevTools logs: " + devToolsLogs.size());

306

System.out.println("WebDriver logs: " + webDriverLogs.size());

307

308

// Find overlapping entries

309

Set<String> uniqueMessages = new HashSet<>();

310

devToolsLogs.forEach(log -> uniqueMessages.add(log.substring(log.indexOf(":") + 2)));

311

webDriverLogs.forEach(log -> uniqueMessages.add(log.substring(log.indexOf(":") + 2)));

312

313

System.out.println("Unique log messages: " + uniqueMessages.size());

314

```

315

316

## Timestamp Handling

317

318

### CDP Timestamp Conversion

319

320

The v115Log class handles CDP timestamp conversion with error recovery.

321

322

```java { .api }

323

/**

324

* Convert CDP timestamp to milliseconds since epoch

325

* @param timestamp CDP Timestamp object

326

* @return Long timestamp in milliseconds, or current time if conversion fails

327

*/

328

private long fromCdpTimestamp(Timestamp timestamp);

329

```

330

331

**Usage Examples:**

332

333

```java

334

// Timestamp conversion happens automatically, but you can access it

335

devTools.addListener(log.entryAdded(), logEntry -> {

336

org.openqa.selenium.logging.LogEntry entry = logEntry.getEntry();

337

long timestamp = entry.getTimestamp();

338

339

// Convert to various time formats

340

Instant instant = Instant.ofEpochMilli(timestamp);

341

LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());

342

343

System.out.println("Log timestamp: " + dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

344

System.out.println("Relative time: " + Duration.between(Instant.now(), instant).toMillis() + "ms ago");

345

});

346

```

347

348

## Error Handling

349

350

### Malformed Timestamps

351

352

The system gracefully handles malformed CDP timestamps:

353

354

```java

355

// Automatic fallback to current system time for invalid timestamps

356

private long fromCdpTimestamp(Timestamp timestamp) {

357

try {

358

return Long.parseLong(timestamp.toString());

359

} catch (NumberFormatException e) {

360

// Return current time as fallback

361

return System.currentTimeMillis();

362

}

363

}

364

```

365

366

### Log Collection Failures

367

368

Handle cases where log collection fails or is interrupted:

369

370

```java

371

try {

372

devTools.send(log.enable());

373

System.out.println("Log collection enabled");

374

} catch (Exception e) {

375

System.err.println("Failed to enable log collection: " + e.getMessage());

376

// Continue without DevTools logging, rely on WebDriver logs

377

}

378

379

// Safe log clearing

380

try {

381

devTools.send(log.clear());

382

System.out.println("Browser logs cleared");

383

} catch (Exception e) {

384

System.err.println("Failed to clear logs: " + e.getMessage());

385

// Not critical - continue operation

386

}

387

```

388

389

### Memory Management

390

391

Prevent memory leaks when collecting large numbers of log entries:

392

393

```java

394

// Use bounded collections for log storage

395

private final Queue<String> recentLogs = new ArrayDeque<String>() {

396

@Override

397

public boolean add(String item) {

398

if (size() >= 1000) { // Keep only last 1000 logs

399

poll();

400

}

401

return super.add(item);

402

}

403

};

404

405

devTools.addListener(log.entryAdded(), logEntry -> {

406

String message = logEntry.getEntry().getMessage();

407

408

// Store with size limit

409

synchronized (recentLogs) {

410

recentLogs.add(message);

411

}

412

});

413

```