or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

fluent-logging.mdindex.mdmarker-logging.mdmarker-management.mdmdc-support.mdstandard-logging.md

fluent-logging.mddocs/

0

# Fluent Logging API

1

2

SLF4J 2.x fluent interface for building complex log events with structured data, lazy evaluation, and method chaining. This API enables modern logging patterns with key-value pairs, conditional logging, and deferred message construction.

3

4

## Capabilities

5

6

### Event Builder Creation

7

8

Create fluent logging event builders for each log level.

9

10

```java { .api }

11

/**

12

* Create a fluent logging event builder at TRACE level

13

* @return LoggingEventBuilder for TRACE level

14

*/

15

LoggingEventBuilder atTrace();

16

17

/**

18

* Create a fluent logging event builder at DEBUG level

19

* @return LoggingEventBuilder for DEBUG level

20

*/

21

LoggingEventBuilder atDebug();

22

23

/**

24

* Create a fluent logging event builder at INFO level

25

* @return LoggingEventBuilder for INFO level

26

*/

27

LoggingEventBuilder atInfo();

28

29

/**

30

* Create a fluent logging event builder at WARN level

31

* @return LoggingEventBuilder for WARN level

32

*/

33

LoggingEventBuilder atWarn();

34

35

/**

36

* Create a fluent logging event builder at ERROR level

37

* @return LoggingEventBuilder for ERROR level

38

*/

39

LoggingEventBuilder atError();

40

```

41

42

**Usage Examples:**

43

44

```java

45

// Create event builders

46

LoggingEventBuilder infoEvent = logger.atInfo();

47

LoggingEventBuilder errorEvent = logger.atError();

48

49

// Builders are only created if the level is enabled

50

if (logger.isDebugEnabled()) {

51

LoggingEventBuilder debugEvent = logger.atDebug();

52

}

53

```

54

55

### Basic Event Configuration

56

57

Configure basic properties of the log event.

58

59

```java { .api }

60

/**

61

* Set the exception cause for this log event

62

* @param cause The throwable cause

63

* @return This event builder for chaining

64

*/

65

LoggingEventBuilder setCause(Throwable cause);

66

67

/**

68

* Add a marker to this log event

69

* @param marker The marker to add

70

* @return This event builder for chaining

71

*/

72

LoggingEventBuilder addMarker(Marker marker);

73

74

/**

75

* Set the log message

76

* @param message The message string

77

* @return This event builder for chaining

78

*/

79

LoggingEventBuilder setMessage(String message);

80

81

/**

82

* Set the log message using a supplier (lazy evaluation)

83

* @param messageSupplier Supplier that provides the message

84

* @return This event builder for chaining

85

*/

86

LoggingEventBuilder setMessage(Supplier<String> messageSupplier);

87

```

88

89

**Usage Examples:**

90

91

```java

92

// Basic event configuration

93

logger.atInfo()

94

.setMessage("User login successful")

95

.log();

96

97

// With marker and exception

98

Marker securityMarker = MarkerFactory.getMarker("SECURITY");

99

logger.atError()

100

.addMarker(securityMarker)

101

.setCause(exception)

102

.setMessage("Authentication failed")

103

.log();

104

105

// Lazy message evaluation

106

logger.atDebug()

107

.setMessage(() -> "Expensive computation result: " + computeExpensiveValue())

108

.log();

109

```

110

111

### Parameterized Messages

112

113

Add arguments for parameterized messages with type safety.

114

115

```java { .api }

116

/**

117

* Add an argument for parameterized message

118

* @param p The argument object

119

* @return This event builder for chaining

120

*/

121

LoggingEventBuilder addArgument(Object p);

122

123

/**

124

* Add a lazy-evaluated argument using a supplier

125

* @param objectSupplier Supplier that provides the argument

126

* @return This event builder for chaining

127

*/

128

LoggingEventBuilder addArgument(Supplier<?> objectSupplier);

129

```

130

131

**Usage Examples:**

132

133

```java

134

// Parameterized message with arguments

135

logger.atInfo()

136

.setMessage("User {} logged in from {}")

137

.addArgument(username)

138

.addArgument(ipAddress)

139

.log();

140

141

// Lazy argument evaluation

142

logger.atDebug()

143

.setMessage("Processing item {} with result {}")

144

.addArgument(itemId)

145

.addArgument(() -> performExpensiveCalculation(itemId))

146

.log();

147

148

// Multiple arguments

149

logger.atInfo()

150

.setMessage("Transfer of ${} from {} to {} completed")

151

.addArgument(amount)

152

.addArgument(fromAccount)

153

.addArgument(toAccount)

154

.log();

155

```

156

157

### Structured Data (Key-Value Pairs)

158

159

Add structured data as key-value pairs for modern observability platforms.

160

161

```java { .api }

162

/**

163

* Add a key-value pair to the log event

164

* @param key The key name

165

* @param value The value object

166

* @return This event builder for chaining

167

*/

168

LoggingEventBuilder addKeyValue(String key, Object value);

169

170

/**

171

* Add a key-value pair with lazy-evaluated value

172

* @param key The key name

173

* @param valueSupplier Supplier that provides the value

174

* @return This event builder for chaining

175

*/

176

LoggingEventBuilder addKeyValue(String key, Supplier<Object> valueSupplier);

177

```

178

179

**Usage Examples:**

180

181

```java

182

// Structured logging with key-value pairs

183

logger.atInfo()

184

.setMessage("API request processed")

185

.addKeyValue("userId", userId)

186

.addKeyValue("endpoint", "/api/users")

187

.addKeyValue("method", "GET")

188

.addKeyValue("responseTime", responseTime)

189

.addKeyValue("statusCode", 200)

190

.log();

191

192

// Lazy key-value evaluation

193

logger.atDebug()

194

.setMessage("Cache operation completed")

195

.addKeyValue("operation", "get")

196

.addKeyValue("key", cacheKey)

197

.addKeyValue("hit", () -> cache.containsKey(cacheKey))

198

.addKeyValue("size", () -> cache.size())

199

.log();

200

201

// Complex structured data

202

logger.atWarn()

203

.setMessage("Rate limit exceeded")

204

.addKeyValue("clientId", clientId)

205

.addKeyValue("requestsPerMinute", requestCount)

206

.addKeyValue("limit", rateLimitThreshold)

207

.addKeyValue("windowStart", windowStart.toString())

208

.addKeyValue("action", "throttle")

209

.log();

210

```

211

212

### Event Execution

213

214

Execute the configured log event.

215

216

```java { .api }

217

/**

218

* Execute the log event with configured settings

219

*/

220

void log();

221

222

/**

223

* Set message and execute the log event

224

* @param message The log message

225

*/

226

void log(String message);

227

228

/**

229

* Set message with one argument and execute

230

* @param message The log message with placeholder

231

* @param arg The argument

232

*/

233

void log(String message, Object arg);

234

235

/**

236

* Set message with two arguments and execute

237

* @param message The log message with placeholders

238

* @param arg0 The first argument

239

* @param arg1 The second argument

240

*/

241

void log(String message, Object arg0, Object arg1);

242

243

/**

244

* Set message with multiple arguments and execute

245

* @param message The log message with placeholders

246

* @param args The arguments

247

*/

248

void log(String message, Object... args);

249

250

/**

251

* Set lazy message and execute

252

* @param messageSupplier Supplier that provides the message

253

*/

254

void log(Supplier<String> messageSupplier);

255

```

256

257

**Usage Examples:**

258

259

```java

260

// Build and execute separately

261

LoggingEventBuilder event = logger.atInfo()

262

.addKeyValue("operation", "user_creation")

263

.addKeyValue("userId", newUserId);

264

265

if (isSuccessful) {

266

event.setMessage("User created successfully").log();

267

} else {

268

event.setMessage("User creation failed").log();

269

}

270

271

// Set message and execute in one call

272

logger.atInfo()

273

.addKeyValue("requestId", requestId)

274

.addKeyValue("duration", duration)

275

.log("Request completed");

276

277

// Multiple arguments in log call

278

logger.atInfo()

279

.addKeyValue("operation", "data_sync")

280

.log("Synchronized {} records in {} ms", recordCount, duration);

281

```

282

283

## Advanced Fluent Logging Patterns

284

285

### Conditional Logging with Context

286

287

```java

288

// Only log if specific conditions are met

289

if (logger.isDebugEnabled()) {

290

logger.atDebug()

291

.addKeyValue("threadName", Thread.currentThread().getName())

292

.addKeyValue("memoryUsage", Runtime.getRuntime().totalMemory())

293

.addKeyValue("activeConnections", connectionPool.getActiveCount())

294

.setMessage("System state snapshot")

295

.log();

296

}

297

```

298

299

### Business Event Logging

300

301

```java

302

// Order processing event

303

logger.atInfo()

304

.addMarker(MarkerFactory.getMarker("BUSINESS_EVENT"))

305

.setMessage("Order processed")

306

.addKeyValue("orderId", order.getId())

307

.addKeyValue("customerId", order.getCustomerId())

308

.addKeyValue("amount", order.getTotalAmount())

309

.addKeyValue("currency", order.getCurrency())

310

.addKeyValue("items", order.getItems().size())

311

.addKeyValue("processingTime", processingTime)

312

.addKeyValue("paymentMethod", order.getPaymentMethod())

313

.log();

314

```

315

316

### Error Context Enrichment

317

318

```java

319

// Rich error context

320

logger.atError()

321

.addMarker(MarkerFactory.getMarker("PAYMENT_ERROR"))

322

.setCause(paymentException)

323

.setMessage("Payment processing failed")

324

.addKeyValue("transactionId", transactionId)

325

.addKeyValue("amount", paymentAmount)

326

.addKeyValue("currency", currency)

327

.addKeyValue("paymentProvider", provider)

328

.addKeyValue("customerId", customerId)

329

.addKeyValue("retryAttempt", retryCount)

330

.addKeyValue("errorCode", paymentException.getErrorCode())

331

.log();

332

```

333

334

### Performance Monitoring

335

336

```java

337

// Performance event with timing

338

long startTime = System.currentTimeMillis();

339

try {

340

// perform operation

341

performDatabaseOperation();

342

343

logger.atInfo()

344

.addMarker(MarkerFactory.getMarker("PERFORMANCE"))

345

.setMessage("Database operation completed")

346

.addKeyValue("operation", "select")

347

.addKeyValue("table", "users")

348

.addKeyValue("duration", System.currentTimeMillis() - startTime)

349

.addKeyValue("recordCount", resultCount)

350

.log();

351

} catch (Exception e) {

352

logger.atError()

353

.addMarker(MarkerFactory.getMarker("PERFORMANCE"))

354

.setCause(e)

355

.setMessage("Database operation failed")

356

.addKeyValue("operation", "select")

357

.addKeyValue("table", "users")

358

.addKeyValue("duration", System.currentTimeMillis() - startTime)

359

.log();

360

}

361

```

362

363

### Lazy Evaluation Benefits

364

365

```java

366

// Expensive operations only executed if logging level is enabled

367

logger.atDebug()

368

.setMessage(() -> "Complex state: " + generateComplexStateDescription())

369

.addKeyValue("timestamp", () -> Instant.now().toString())

370

.addKeyValue("threadDump", () -> generateThreadDump())

371

.addKeyValue("memoryStats", () -> getDetailedMemoryStats())

372

.log();

373

```

374

375

### Caller Boundary Control

376

377

For advanced framework integration, control the caller boundary for accurate location information.

378

379

```java { .api }

380

/**

381

* Set the caller boundary for accurate location information

382

* @param fqcn Fully qualified class name of the caller boundary

383

*/

384

void setCallerBoundary(String fqcn);

385

```

386

387

**Usage Example:**

388

389

```java

390

import org.slf4j.Logger;

391

import org.slf4j.spi.CallerBoundaryAware;

392

import org.slf4j.spi.LoggingEventBuilder;

393

import java.util.Map;

394

395

// Framework wrapper example

396

public class LoggingWrapper {

397

private static final String FQCN = LoggingWrapper.class.getName();

398

private final Logger logger;

399

400

public void logBusinessEvent(String event, Map<String, Object> context) {

401

LoggingEventBuilder builder = logger.atInfo();

402

403

if (builder instanceof CallerBoundaryAware) {

404

((CallerBoundaryAware) builder).setCallerBoundary(FQCN);

405

}

406

407

builder.setMessage(event);

408

context.forEach(builder::addKeyValue);

409

builder.log();

410

}

411

}

412

```

413

414

## Integration with Observability Platforms

415

416

The structured key-value pairs integrate seamlessly with modern observability platforms:

417

418

```java

419

// APM/Observability friendly logging

420

logger.atInfo()

421

.addKeyValue("trace.id", traceId)

422

.addKeyValue("span.id", spanId)

423

.addKeyValue("service.name", "user-service")

424

.addKeyValue("service.version", "1.2.3")

425

.addKeyValue("environment", "production")

426

.setMessage("Service operation completed")

427

.log();

428

```