or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

device-management.mdframe-processing.mdindex.mdlogging.mdpipeline-configuration.mdregistration-geometry.md

logging.mddocs/

0

# Logging

1

2

Configurable logging system with multiple severity levels and custom logger support. This module enables debugging, monitoring, and troubleshooting of libfreenect2 operations.

3

4

## Capabilities

5

6

### Logger Base Class

7

8

Base logging interface that can be extended for custom logging implementations.

9

10

```java { .api }

11

/**

12

* Provide interfaces to receive log messages.

13

* You can inherit this class and implement your custom logger.

14

*/

15

abstract class Logger {

16

// Logging level constants

17

/** No logging output */

18

static final int None = 0;

19

/** Error messages only */

20

static final int Error = 1;

21

/** Error and warning messages */

22

static final int Warning = 2;

23

/** Error, warning, and info messages */

24

static final int Info = 3;

25

/** All messages including debug output */

26

static final int Debug = 4;

27

28

/**

29

* Default logging level (Info), or overridden by environment variable.

30

* LIBFREENECT2_LOGGER_LEVEL can contain a case-insensitive name of level.

31

*/

32

@Cast("libfreenect2::Logger::Level") static int getDefaultLevel();

33

34

/**

35

* Convert logging level to a human-readable name

36

*/

37

@StdString static BytePointer level2str(@Cast("libfreenect2::Logger::Level") int level);

38

39

/**

40

* Get the level of the logger; the level is immutable

41

*/

42

@Cast("libfreenect2::Logger::Level") abstract int level();

43

44

/**

45

* libfreenect2 calls this function to output all log messages

46

* @param level Message severity level

47

* @param message Log message content

48

*/

49

void log(@Cast("libfreenect2::Logger::Level") int level, @StdString BytePointer message);

50

void log(@Cast("libfreenect2::Logger::Level") int level, @StdString String message);

51

}

52

```

53

54

**Usage Examples:**

55

56

```java

57

// Check default logging level

58

int defaultLevel = Logger.getDefaultLevel();

59

System.out.println("Default log level: " + Logger.level2str(defaultLevel).getString());

60

61

// The library automatically creates a console logger, but you can customize it

62

```

63

64

### Custom Logger Implementation

65

66

Implement custom loggers for different output destinations and formats.

67

68

**Usage Examples:**

69

70

```java

71

// Custom file logger implementation

72

class FileLogger extends Logger {

73

private final int logLevel;

74

private final PrintWriter writer;

75

76

public FileLogger(int level, String filename) throws IOException {

77

this.logLevel = level;

78

this.writer = new PrintWriter(new FileWriter(filename, true));

79

}

80

81

@Override

82

public int level() {

83

return logLevel;

84

}

85

86

@Override

87

public void log(int level, String message) {

88

if (level <= this.logLevel) {

89

String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());

90

String levelName = Logger.level2str(level).getString();

91

writer.println("[" + timestamp + "] " + levelName + ": " + message);

92

writer.flush();

93

}

94

}

95

96

@Override

97

public void log(int level, BytePointer message) {

98

log(level, message.getString());

99

}

100

101

public void close() {

102

writer.close();

103

}

104

}

105

106

// Custom console logger with formatting

107

class FormattedConsoleLogger extends Logger {

108

private final int logLevel;

109

110

public FormattedConsoleLogger(int level) {

111

this.logLevel = level;

112

}

113

114

@Override

115

public int level() {

116

return logLevel;

117

}

118

119

@Override

120

public void log(int level, String message) {

121

if (level <= this.logLevel) {

122

String levelName = Logger.level2str(level).getString();

123

String prefix = "";

124

125

switch (level) {

126

case Logger.Error:

127

prefix = "ERROR ";

128

break;

129

case Logger.Warning:

130

prefix = "WARN ";

131

break;

132

case Logger.Info:

133

prefix = "INFO ";

134

break;

135

case Logger.Debug:

136

prefix = "DEBUG ";

137

break;

138

}

139

140

System.out.println("[libfreenect2] " + prefix + message);

141

}

142

}

143

144

@Override

145

public void log(int level, BytePointer message) {

146

log(level, message.getString());

147

}

148

}

149

```

150

151

### Logging Level Configuration

152

153

Configure logging levels through environment variables or programmatically.

154

155

**Usage Examples:**

156

157

```java

158

// Check environment variable configuration

159

// Set environment variable: LIBFREENECT2_LOGGER_LEVEL=debug

160

int envLevel = Logger.getDefaultLevel();

161

switch (envLevel) {

162

case Logger.None:

163

System.out.println("Logging disabled");

164

break;

165

case Logger.Error:

166

System.out.println("Error logging only");

167

break;

168

case Logger.Warning:

169

System.out.println("Warning and error logging");

170

break;

171

case Logger.Info:

172

System.out.println("Info, warning, and error logging");

173

break;

174

case Logger.Debug:

175

System.out.println("All logging enabled");

176

break;

177

}

178

179

// Create loggers with different levels

180

Logger errorLogger = new FormattedConsoleLogger(Logger.Error);

181

Logger debugLogger = new FormattedConsoleLogger(Logger.Debug);

182

183

// Level names for display

184

for (int level = Logger.None; level <= Logger.Debug; level++) {

185

System.out.println("Level " + level + ": " + Logger.level2str(level).getString());

186

}

187

```

188

189

### Multi-Output Logging

190

191

Implement loggers that output to multiple destinations simultaneously.

192

193

**Usage Examples:**

194

195

```java

196

// Multi-output logger that logs to both console and file

197

class MultiLogger extends Logger {

198

private final List<Logger> loggers;

199

private final int logLevel;

200

201

public MultiLogger(int level, Logger... loggers) {

202

this.logLevel = level;

203

this.loggers = Arrays.asList(loggers);

204

}

205

206

@Override

207

public int level() {

208

return logLevel;

209

}

210

211

@Override

212

public void log(int level, String message) {

213

if (level <= this.logLevel) {

214

for (Logger logger : loggers) {

215

if (level <= logger.level()) {

216

logger.log(level, message);

217

}

218

}

219

}

220

}

221

222

@Override

223

public void log(int level, BytePointer message) {

224

log(level, message.getString());

225

}

226

}

227

228

// Usage

229

try {

230

FileLogger fileLogger = new FileLogger(Logger.Debug, "libfreenect2.log");

231

FormattedConsoleLogger consoleLogger = new FormattedConsoleLogger(Logger.Info);

232

233

MultiLogger multiLogger = new MultiLogger(Logger.Debug, fileLogger, consoleLogger);

234

235

// This would be set as the global logger if the library supported it

236

// In practice, libfreenect2 manages its own logging internally

237

238

} catch (IOException e) {

239

System.err.println("Failed to create file logger: " + e.getMessage());

240

}

241

```

242

243

### Filtering and Conditional Logging

244

245

Implement advanced logging features like filtering and conditional output.

246

247

**Usage Examples:**

248

249

```java

250

// Filtered logger that only logs messages containing specific keywords

251

class FilteredLogger extends Logger {

252

private final Logger delegate;

253

private final Set<String> keywords;

254

private final boolean includeMode; // true = include, false = exclude

255

256

public FilteredLogger(Logger delegate, boolean includeMode, String... keywords) {

257

this.delegate = delegate;

258

this.includeMode = includeMode;

259

this.keywords = new HashSet<>(Arrays.asList(keywords));

260

}

261

262

@Override

263

public int level() {

264

return delegate.level();

265

}

266

267

@Override

268

public void log(int level, String message) {

269

boolean hasKeyword = keywords.stream().anyMatch(message::contains);

270

271

if ((includeMode && hasKeyword) || (!includeMode && !hasKeyword)) {

272

delegate.log(level, message);

273

}

274

}

275

276

@Override

277

public void log(int level, BytePointer message) {

278

log(level, message.getString());

279

}

280

}

281

282

// Rate-limited logger to prevent spam

283

class RateLimitedLogger extends Logger {

284

private final Logger delegate;

285

private final Map<String, Long> lastLogTime = new HashMap<>();

286

private final long minIntervalMs;

287

288

public RateLimitedLogger(Logger delegate, long minIntervalMs) {

289

this.delegate = delegate;

290

this.minIntervalMs = minIntervalMs;

291

}

292

293

@Override

294

public int level() {

295

return delegate.level();

296

}

297

298

@Override

299

public void log(int level, String message) {

300

long now = System.currentTimeMillis();

301

Long lastTime = lastLogTime.get(message);

302

303

if (lastTime == null || (now - lastTime) >= minIntervalMs) {

304

delegate.log(level, message);

305

lastLogTime.put(message, now);

306

}

307

}

308

309

@Override

310

public void log(int level, BytePointer message) {

311

log(level, message.getString());

312

}

313

}

314

315

// Usage examples

316

FormattedConsoleLogger baseLogger = new FormattedConsoleLogger(Logger.Debug);

317

318

// Only log messages containing "device" or "frame"

319

FilteredLogger deviceLogger = new FilteredLogger(baseLogger, true, "device", "frame");

320

321

// Prevent duplicate messages within 5 seconds

322

RateLimitedLogger rateLimitedLogger = new RateLimitedLogger(baseLogger, 5000);

323

```

324

325

## Global Logging Functions

326

327

The library provides global functions for logger management, though these are typically handled internally:

328

329

```java

330

// Note: These are conceptual - actual global logger management

331

// is handled internally by the native library

332

333

/**

334

* Allocate a Logger instance that outputs log to standard input/output

335

*/

336

// Logger createConsoleLogger(int level);

337

338

/**

339

* Create console logger with default level from environment

340

*/

341

// Logger createConsoleLoggerWithDefaultLevel();

342

343

/**

344

* Get the pointer to the current logger (informational only)

345

*/

346

// Logger getGlobalLogger();

347

348

/**

349

* Set the logger for all log output in this library

350

* @param logger Pointer to your logger, or null to disable logging

351

*/

352

// void setGlobalLogger(Logger logger);

353

```

354

355

## Best Practices

356

357

### Logging in Production Applications

358

359

```java

360

public class LibFreenect2Logger {

361

private static Logger applicationLogger;

362

363

public static void initializeLogging(String logFile, int level) {

364

try {

365

if (logFile != null) {

366

FileLogger fileLogger = new FileLogger(level, logFile);

367

FormattedConsoleLogger consoleLogger = new FormattedConsoleLogger(Logger.Warning);

368

applicationLogger = new MultiLogger(level, fileLogger, consoleLogger);

369

} else {

370

applicationLogger = new FormattedConsoleLogger(level);

371

}

372

373

System.out.println("Logging initialized at level: " +

374

Logger.level2str(level).getString());

375

376

} catch (IOException e) {

377

System.err.println("Failed to initialize file logging: " + e.getMessage());

378

applicationLogger = new FormattedConsoleLogger(level);

379

}

380

}

381

382

public static void logDeviceInfo(Freenect2Device device) {

383

if (applicationLogger != null && applicationLogger.level() >= Logger.Info) {

384

String info = "Device Info - Serial: " + device.getSerialNumber().getString() +

385

", Firmware: " + device.getFirmwareVersion().getString();

386

applicationLogger.log(Logger.Info, info);

387

}

388

}

389

390

public static void logError(String message, Exception e) {

391

if (applicationLogger != null) {

392

applicationLogger.log(Logger.Error, message + ": " + e.getMessage());

393

}

394

}

395

}