or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

basic-logging.mdfluent-logging.mdindex.mdmarkers.mdmdc.mdservice-providers.md

markers.mddocs/

0

# Markers

1

2

Markers are named objects used to enrich log statements with categorical information. They enable logging frameworks to filter, route, or specially handle log messages based on marker content. Markers can contain references to other markers and are fully supported in both traditional and fluent logging APIs.

3

4

## Capabilities

5

6

### Marker Factory

7

8

Static factory for creating and retrieving Marker instances.

9

10

```java { .api }

11

/**

12

* MarkerFactory is a utility class producing Marker instances

13

*/

14

public class MarkerFactory {

15

/**

16

* Return a Marker instance as specified by the name parameter

17

* @param name The name of the Marker object to return

18

* @return marker instance

19

*/

20

public static Marker getMarker(String name);

21

22

/**

23

* Create a marker which is detached (even at birth) from the MarkerFactory

24

* @param name the name of the marker

25

* @return a dangling marker

26

*/

27

public static Marker getDetachedMarker(String name);

28

29

/**

30

* Return the IMarkerFactory instance in use

31

* @return the IMarkerFactory instance in use

32

*/

33

public static IMarkerFactory getIMarkerFactory();

34

}

35

```

36

37

### Marker Interface

38

39

Core marker interface for creating named categorical objects.

40

41

```java { .api }

42

/**

43

* Markers are named objects used to enrich log statements

44

*/

45

public interface Marker extends Serializable {

46

/**

47

* This constant represents any marker, including a null marker

48

*/

49

String ANY_MARKER = "*";

50

51

/**

52

* This constant represents any non-null marker

53

*/

54

String ANY_NON_NULL_MARKER = "+";

55

56

/**

57

* Get the name of this Marker

58

* @return name of marker

59

*/

60

String getName();

61

62

/**

63

* Add a reference to another Marker

64

* @param reference a reference to another marker

65

* @throws IllegalArgumentException if 'reference' is null

66

*/

67

void add(Marker reference);

68

69

/**

70

* Remove a marker reference

71

* @param reference the marker reference to remove

72

* @return true if reference could be found and removed, false otherwise

73

*/

74

boolean remove(Marker reference);

75

76

/**

77

* Does this marker have any references?

78

* @return true if this marker has one or more references, false otherwise

79

*/

80

boolean hasReferences();

81

82

/**

83

* Returns an Iterator which can be used to iterate over the references of this marker

84

* @return Iterator over the references of this marker

85

*/

86

Iterator<Marker> iterator();

87

88

/**

89

* Does this marker contain a reference to the 'other' marker?

90

* @param other The marker to test for inclusion

91

* @return Whether this marker contains the other marker

92

* @throws IllegalArgumentException if 'other' is null

93

*/

94

boolean contains(Marker other);

95

96

/**

97

* Does this marker contain the marker named 'name'?

98

* @param name The marker name to test for inclusion

99

* @return Whether this marker contains the other marker

100

*/

101

boolean contains(String name);

102

103

/**

104

* Markers are considered equal if they have the same name

105

* @param o object to compare

106

* @return true, if this.name equals o.name

107

*/

108

boolean equals(Object o);

109

110

/**

111

* Compute the hash code based on the name of this marker

112

* @return the computed hashCode

113

*/

114

int hashCode();

115

}

116

```

117

118

### Marker Factory Interface

119

120

Factory interface for creating and managing Marker instances.

121

122

```java { .api }

123

/**

124

* Factory interface for Marker instances

125

*/

126

public interface IMarkerFactory {

127

/**

128

* Manufacture a Marker instance by name. If the instance has been created earlier, return the previously created instance

129

* @param name the name of the marker to be created, null value is not allowed

130

* @return a Marker instance

131

*/

132

Marker getMarker(String name);

133

134

/**

135

* Checks if the marker with the name already exists

136

* @param name marker name

137

* @return true if the marker exists, false otherwise

138

*/

139

boolean exists(String name);

140

141

/**

142

* Detach an existing marker

143

* @param name The name of the marker to detach

144

* @return whether the marker could be detached or not

145

*/

146

boolean detachMarker(String name);

147

148

/**

149

* Create a marker which is detached from this IMarkerFactory

150

* @param name marker name

151

* @return a marker detached from this factory

152

*/

153

Marker getDetachedMarker(String name);

154

}

155

```

156

157

**Usage Examples:**

158

159

```java

160

import org.slf4j.Logger;

161

import org.slf4j.LoggerFactory;

162

import org.slf4j.Marker;

163

import org.slf4j.MarkerFactory;

164

165

public class MarkerExample {

166

private static final Logger logger = LoggerFactory.getLogger(MarkerExample.class);

167

168

// Create markers for different categories

169

private static final Marker SECURITY_MARKER = MarkerFactory.getMarker("SECURITY");

170

private static final Marker AUDIT_MARKER = MarkerFactory.getMarker("AUDIT");

171

private static final Marker PERFORMANCE_MARKER = MarkerFactory.getMarker("PERFORMANCE");

172

173

public void basicMarkerUsage() {

174

// Simple marker usage

175

logger.info(SECURITY_MARKER, "User authentication successful");

176

logger.warn(AUDIT_MARKER, "Configuration changed by admin user");

177

logger.debug(PERFORMANCE_MARKER, "Query execution time: {} ms", 150);

178

}

179

180

public void markerHierarchy() {

181

// Create nested markers

182

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

183

Marker authMarker = MarkerFactory.getMarker("AUTH");

184

Marker loginMarker = MarkerFactory.getMarker("LOGIN");

185

186

// Build marker hierarchy: SECURITY -> AUTH -> LOGIN

187

authMarker.add(securityMarker);

188

loginMarker.add(authMarker);

189

190

// This log statement will match filters for LOGIN, AUTH, or SECURITY

191

logger.info(loginMarker, "User login attempt from IP: {}", "192.168.1.100");

192

193

// Check marker relationships

194

if (loginMarker.contains(securityMarker)) {

195

logger.debug("Login marker contains security marker");

196

}

197

}

198

199

public void conditionalLogging() {

200

// Check if marker-specific logging is enabled

201

if (logger.isInfoEnabled(AUDIT_MARKER)) {

202

// Perform expensive audit data collection only if needed

203

String auditData = collectAuditInformation();

204

logger.info(AUDIT_MARKER, "Audit event: {}", auditData);

205

}

206

}

207

}

208

```

209

210

### Traditional API with Markers

211

212

All traditional logging methods have marker-aware equivalents:

213

214

```java { .api }

215

// Marker-aware logging methods for each level

216

public interface Logger {

217

// TRACE level with markers

218

boolean isTraceEnabled(Marker marker);

219

void trace(Marker marker, String msg);

220

void trace(Marker marker, String format, Object arg);

221

void trace(Marker marker, String format, Object arg1, Object arg2);

222

void trace(Marker marker, String format, Object... arguments);

223

void trace(Marker marker, String msg, Throwable t);

224

225

// DEBUG level with markers

226

boolean isDebugEnabled(Marker marker);

227

void debug(Marker marker, String msg);

228

void debug(Marker marker, String format, Object arg);

229

void debug(Marker marker, String format, Object arg1, Object arg2);

230

void debug(Marker marker, String format, Object... arguments);

231

void debug(Marker marker, String msg, Throwable t);

232

233

// INFO level with markers

234

boolean isInfoEnabled(Marker marker);

235

void info(Marker marker, String msg);

236

void info(Marker marker, String format, Object arg);

237

void info(Marker marker, String format, Object arg1, Object arg2);

238

void info(Marker marker, String format, Object... arguments);

239

void info(Marker marker, String msg, Throwable t);

240

241

// WARN level with markers

242

boolean isWarnEnabled(Marker marker);

243

void warn(Marker marker, String msg);

244

void warn(Marker marker, String format, Object arg);

245

void warn(Marker marker, String format, Object arg1, Object arg2);

246

void warn(Marker marker, String format, Object... arguments);

247

void warn(Marker marker, String msg, Throwable t);

248

249

// ERROR level with markers

250

boolean isErrorEnabled(Marker marker);

251

void error(Marker marker, String msg);

252

void error(Marker marker, String format, Object arg);

253

void error(Marker marker, String format, Object arg1, Object arg2);

254

void error(Marker marker, String format, Object... arguments);

255

void error(Marker marker, String msg, Throwable t);

256

}

257

```

258

259

### Fluent API with Markers

260

261

The fluent API supports multiple markers on a single log statement:

262

263

```java

264

// Multiple markers with fluent API

265

logger.atWarn()

266

.addMarker(SECURITY_MARKER)

267

.addMarker(AUDIT_MARKER)

268

.addKeyValue("userId", "user123")

269

.addKeyValue("action", "sensitive_operation")

270

.log("Security violation detected");

271

272

// Conditional marker addition

273

LoggingEventBuilder builder = logger.atInfo();

274

if (isSecurityEvent) {

275

builder.addMarker(SECURITY_MARKER);

276

}

277

if (isAuditRequired) {

278

builder.addMarker(AUDIT_MARKER);

279

}

280

builder.log("Event processed successfully");

281

```

282

283

## Common Marker Patterns

284

285

### Categorization Markers

286

287

```java

288

// Functional category markers

289

private static final Marker DATABASE = MarkerFactory.getMarker("DATABASE");

290

private static final Marker HTTP = MarkerFactory.getMarker("HTTP");

291

private static final Marker CACHE = MarkerFactory.getMarker("CACHE");

292

293

// Operational category markers

294

private static final Marker STARTUP = MarkerFactory.getMarker("STARTUP");

295

private static final Marker SHUTDOWN = MarkerFactory.getMarker("SHUTDOWN");

296

private static final Marker HEALTH_CHECK = MarkerFactory.getMarker("HEALTH_CHECK");

297

298

public void databaseOperation() {

299

logger.debug(DATABASE, "Executing query: {}", sql);

300

logger.info(DATABASE, "Query completed in {} ms", duration);

301

}

302

303

public void httpRequest() {

304

logger.info(HTTP, "Incoming request: {} {}", method, path);

305

logger.debug(HTTP, "Request headers: {}", headers);

306

}

307

```

308

309

### Hierarchical Markers

310

311

```java

312

// Create marker hierarchy for better filtering

313

Marker applicationMarker = MarkerFactory.getMarker("APP");

314

Marker businessMarker = MarkerFactory.getMarker("BUSINESS");

315

Marker orderMarker = MarkerFactory.getMarker("ORDER");

316

Marker paymentMarker = MarkerFactory.getMarker("PAYMENT");

317

318

// Build hierarchy: APP -> BUSINESS -> ORDER/PAYMENT

319

businessMarker.add(applicationMarker);

320

orderMarker.add(businessMarker);

321

paymentMarker.add(businessMarker);

322

323

// Usage allows filtering at any level

324

logger.info(orderMarker, "Order {} created", orderId);

325

logger.warn(paymentMarker, "Payment {} failed", paymentId, exception);

326

327

// Filters can match:

328

// - Specific: only ORDER events

329

// - Category: all BUSINESS events (includes ORDER and PAYMENT)

330

// - Application: all APP events (includes everything)

331

```

332

333

### Security and Audit Markers

334

335

```java

336

// Security-related markers

337

private static final Marker SECURITY = MarkerFactory.getMarker("SECURITY");

338

private static final Marker AUTHENTICATION = MarkerFactory.getMarker("AUTH");

339

private static final Marker AUTHORIZATION = MarkerFactory.getMarker("AUTHZ");

340

private static final Marker SENSITIVE_DATA = MarkerFactory.getMarker("SENSITIVE");

341

342

// Create relationships

343

AUTHENTICATION.add(SECURITY);

344

AUTHORIZATION.add(SECURITY);

345

346

public void authenticateUser(String username, String password) {

347

logger.info(AUTHENTICATION, "Authentication attempt for user: {}", username);

348

349

try {

350

User user = authService.authenticate(username, password);

351

logger.info(AUTHENTICATION, "Authentication successful for user: {}", username);

352

} catch (AuthenticationException e) {

353

logger.warn(AUTHENTICATION, "Authentication failed for user: {}", username, e);

354

}

355

}

356

357

public void accessSensitiveData(String userId, String resource) {

358

if (!authService.hasPermission(userId, resource)) {

359

logger.warn(AUTHORIZATION, "Access denied: user {} attempted to access {}", userId, resource);

360

return;

361

}

362

363

logger.info(SENSITIVE_DATA, "Sensitive data accessed: user={}, resource={}", userId, resource);

364

}

365

```

366

367

### Performance Monitoring Markers

368

369

```java

370

private static final Marker PERFORMANCE = MarkerFactory.getMarker("PERFORMANCE");

371

private static final Marker SLOW_QUERY = MarkerFactory.getMarker("SLOW_QUERY");

372

private static final Marker MEMORY_WARNING = MarkerFactory.getMarker("MEMORY_WARNING");

373

374

SLOW_QUERY.add(PERFORMANCE);

375

MEMORY_WARNING.add(PERFORMANCE);

376

377

public void monitorQueryPerformance(String query, long executionTime) {

378

if (executionTime > SLOW_QUERY_THRESHOLD) {

379

logger.warn(SLOW_QUERY, "Slow query detected: {} ms - {}", executionTime, query);

380

} else {

381

logger.debug(PERFORMANCE, "Query executed in {} ms", executionTime);

382

}

383

}

384

385

public void checkMemoryUsage() {

386

long freeMemory = Runtime.getRuntime().freeMemory();

387

long totalMemory = Runtime.getRuntime().totalMemory();

388

double usagePercent = (double) (totalMemory - freeMemory) / totalMemory * 100;

389

390

if (usagePercent > 90) {

391

logger.warn(MEMORY_WARNING, "High memory usage: {:.1f}%", usagePercent);

392

} else {

393

logger.debug(PERFORMANCE, "Memory usage: {:.1f}%", usagePercent);

394

}

395

}

396

```

397

398

## Marker Management

399

400

### Singleton Pattern

401

402

Markers are typically managed as singletons within the MarkerFactory:

403

404

```java

405

// Multiple calls return the same instance

406

Marker marker1 = MarkerFactory.getMarker("TEST");

407

Marker marker2 = MarkerFactory.getMarker("TEST");

408

assert marker1 == marker2; // Same instance

409

410

// Detached markers are independent

411

Marker detached1 = MarkerFactory.getDetachedMarker("TEST");

412

Marker detached2 = MarkerFactory.getDetachedMarker("TEST");

413

assert detached1 != detached2; // Different instances

414

```

415

416

### Best Practices

417

418

1. **Static Final Constants**: Define markers as static final constants for reuse

419

2. **Descriptive Names**: Use clear, descriptive names that indicate purpose

420

3. **Hierarchical Organization**: Build marker hierarchies for flexible filtering

421

4. **Documentation**: Document marker semantics and intended use

422

5. **Consistent Naming**: Use consistent naming conventions across the application

423

424

```java

425

public class ApplicationMarkers {

426

// Base application marker

427

public static final Marker APP = MarkerFactory.getMarker("APP");

428

429

// Functional area markers

430

public static final Marker SECURITY = MarkerFactory.getMarker("SECURITY");

431

public static final Marker BUSINESS = MarkerFactory.getMarker("BUSINESS");

432

public static final Marker INTEGRATION = MarkerFactory.getMarker("INTEGRATION");

433

434

// Specific operation markers

435

public static final Marker USER_MANAGEMENT = MarkerFactory.getMarker("USER_MGMT");

436

public static final Marker ORDER_PROCESSING = MarkerFactory.getMarker("ORDER_PROC");

437

public static final Marker EXTERNAL_API = MarkerFactory.getMarker("EXT_API");

438

439

static {

440

// Build hierarchy

441

SECURITY.add(APP);

442

BUSINESS.add(APP);

443

INTEGRATION.add(APP);

444

445

USER_MANAGEMENT.add(SECURITY);

446

ORDER_PROCESSING.add(BUSINESS);

447

EXTERNAL_API.add(INTEGRATION);

448

}

449

}

450

```