or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdconfiguration.mdcore-logging.mdcustom-loggers.mdindex.mdscoped-loggers.mdtimers.md

advanced-features.mddocs/

0

# Advanced Features

1

2

Interactive mode, secrets filtering, stream management, and state control for advanced logging scenarios. These features provide sophisticated capabilities for production applications and complex logging requirements.

3

4

## Capabilities

5

6

### State Control

7

8

Enable, disable, and check the logging state of Signale instances.

9

10

```javascript { .api }

11

/**

12

* Disable logging functionality for this instance

13

*/

14

function disable(): void;

15

16

/**

17

* Enable logging functionality for this instance

18

*/

19

function enable(): void;

20

21

/**

22

* Check if logging is currently enabled

23

* @returns true if logging is enabled, false if disabled

24

*/

25

function isEnabled(): boolean;

26

```

27

28

### Secrets Management

29

30

Add and remove sensitive information filtering from log output.

31

32

```javascript { .api }

33

/**

34

* Add secrets/sensitive information to be filtered from logs

35

* @param secrets - Array of strings or numbers to filter out

36

* @throws TypeError if secrets parameter is not an array

37

*/

38

function addSecrets(secrets: (string | number)[]): void;

39

40

/**

41

* Remove all secrets from the instance

42

*/

43

function clearSecrets(): void;

44

```

45

46

### Instance Properties

47

48

Access current instance state and metadata.

49

50

```javascript { .api }

51

/**

52

* Get current instance configuration and options

53

*/

54

readonly currentOptions: SignaleOptions;

55

56

/**

57

* Get current date string

58

*/

59

readonly date: string;

60

61

/**

62

* Get current timestamp string

63

*/

64

readonly timestamp: string;

65

66

/**

67

* Get the filename of the calling code

68

*/

69

readonly filename: string;

70

71

/**

72

* Get package.json configuration

73

*/

74

readonly packageConfiguration: object;

75

76

interface SignaleOptions {

77

config: ConfigOptions;

78

disabled: boolean;

79

types: Record<string, LoggerType>;

80

interactive: boolean;

81

timers: Map<string, number>;

82

stream: NodeJS.WritableStream | NodeJS.WritableStream[];

83

secrets: (string | number)[];

84

logLevel: LogLevel;

85

}

86

```

87

88

### State Control Usage

89

90

Control logging functionality dynamically.

91

92

**Usage Examples:**

93

94

```javascript

95

const signale = require('signale');

96

97

// Normal logging

98

signale.info('Logging is enabled');

99

// Output: ℹ info Logging is enabled

100

101

console.log(signale.isEnabled()); // true

102

103

// Disable logging

104

signale.disable();

105

console.log(signale.isEnabled()); // false

106

107

signale.success('This will not appear');

108

// No output

109

110

signale.error('This will not appear either');

111

// No output

112

113

// Re-enable logging

114

signale.enable();

115

console.log(signale.isEnabled()); // true

116

117

signale.success('Logging is back!');

118

// Output: ✔ success Logging is back!

119

```

120

121

### Secrets Filtering

122

123

Filter sensitive information from log messages and metadata.

124

125

**Usage Examples:**

126

127

```javascript

128

const { Signale } = require('signale');

129

130

// Initialize with secrets

131

const logger = new Signale({

132

secrets: ['password123', 'secret-api-key']

133

});

134

135

logger.info('User login with password123');

136

// Output: ℹ info User login with [secure]

137

138

logger.warn('API key secret-api-key is expiring');

139

// Output: ⚠ warning API key [secure] is expiring

140

141

// Add more secrets at runtime

142

logger.addSecrets(['session-token-abc', 12345]);

143

144

logger.error('Session session-token-abc invalid for user 12345');

145

// Output: ✖ error Session [secure] invalid for user [secure]

146

147

// Clear all secrets

148

logger.clearSecrets();

149

150

logger.info('Now showing password123 and secret-api-key');

151

// Output: ℹ info Now showing password123 and secret-api-key

152

153

// Secrets in scope names are also filtered

154

const secureLogger = new Signale({

155

secrets: ['production']

156

});

157

158

const scopedLogger = secureLogger.scope('production', 'database');

159

scopedLogger.success('Connected successfully');

160

// Output: [[secure]] [database] › ✔ success Connected successfully

161

```

162

163

### Interactive Mode

164

165

Enable interactive mode for overriding previous log messages.

166

167

**Usage Examples:**

168

169

```javascript

170

const { Signale } = require('signale');

171

172

const interactive = new Signale({

173

interactive: true,

174

scope: 'progress'

175

});

176

177

// Interactive loggers override previous interactive messages

178

interactive.await('Processing step 1/4');

179

// Output: [progress] › ⋯ awaiting Processing step 1/4

180

181

setTimeout(() => {

182

interactive.await('Processing step 2/4');

183

// Previous message is overwritten

184

// Output: [progress] › ⋯ awaiting Processing step 2/4

185

186

setTimeout(() => {

187

interactive.success('Processing step 3/4');

188

// Output: [progress] › ✔ success Processing step 3/4

189

190

setTimeout(() => {

191

interactive.complete('All steps completed!');

192

// Output: [progress] › ☑ complete All steps completed!

193

}, 1000);

194

}, 1000);

195

}, 1000);

196

197

// Regular (non-interactive) messages are not overridden

198

const regular = require('signale');

199

regular.info('This message stays visible');

200

interactive.pending('This overwrites previous interactive message');

201

regular.success('This message also stays visible');

202

```

203

204

### Stream Management

205

206

Configure multiple output streams for flexible logging.

207

208

**Usage Examples:**

209

210

```javascript

211

const { Signale } = require('signale');

212

const fs = require('fs');

213

214

// Create file streams

215

const errorLog = fs.createWriteStream('error.log');

216

const accessLog = fs.createWriteStream('access.log');

217

218

// Global stream configuration

219

const fileLogger = new Signale({

220

stream: [process.stdout, accessLog] // All logs go to console AND file

221

});

222

223

fileLogger.info('This appears in console and access.log');

224

fileLogger.success('This also appears in both places');

225

226

// Per-logger-type stream configuration

227

const mixedLogger = new Signale({

228

stream: process.stdout, // Default stream

229

types: {

230

error: {

231

stream: [process.stderr, errorLog] // Errors to stderr AND error.log

232

},

233

info: {

234

stream: accessLog // Info only to access.log

235

}

236

}

237

});

238

239

mixedLogger.success('To console only'); // Uses default stream

240

mixedLogger.info('To access.log only'); // Uses custom stream

241

mixedLogger.error('To stderr AND error.log'); // Uses custom streams

242

243

// Stream inheritance in scoped loggers

244

const parent = new Signale({

245

stream: fs.createWriteStream('parent.log')

246

});

247

248

const child = parent.scope('child');

249

child.info('This goes to parent.log'); // Inherits parent stream

250

```

251

252

### Instance Inspection

253

254

Access and inspect instance properties and configuration.

255

256

**Usage Examples:**

257

258

```javascript

259

const { Signale } = require('signale');

260

261

const logger = new Signale({

262

scope: 'api',

263

secrets: ['token123'],

264

logLevel: 'warn',

265

types: {

266

custom: { badge: '🔧', color: 'blue', label: 'custom' }

267

}

268

});

269

270

// Inspect current options

271

console.log(logger.currentOptions);

272

// {

273

// config: { displayScope: true, displayBadge: true, ... },

274

// disabled: false,

275

// types: { await: {...}, complete: {...}, custom: {...}, ... },

276

// interactive: false,

277

// timers: Map(0) {},

278

// stream: [object Object],

279

// secrets: ['token123'],

280

// logLevel: 'warn'

281

// }

282

283

// Access metadata properties

284

console.log(logger.date); // "12/7/2023"

285

console.log(logger.timestamp); // "2:30:25 PM"

286

console.log(logger.filename); // "advanced-demo.js"

287

console.log(logger.scopeName); // "api"

288

289

// Package configuration

290

console.log(logger.packageConfiguration);

291

// Configuration loaded from package.json signale section

292

```

293

294

### Error Handling

295

296

Proper error handling for advanced features.

297

298

**Usage Examples:**

299

300

```javascript

301

const { Signale } = require('signale');

302

303

// addSecrets error handling

304

const logger = new Signale();

305

306

try {

307

logger.addSecrets('not-an-array'); // TypeError

308

} catch (error) {

309

console.error(error.message); // "Argument must be an array."

310

}

311

312

// Valid secrets addition

313

logger.addSecrets(['valid', 'secrets']);

314

logger.info('These valid secrets are filtered');

315

316

// Stream error handling

317

const invalidStream = { write: 'not-a-function' };

318

319

try {

320

const badLogger = new Signale({ stream: invalidStream });

321

badLogger.info('This may cause issues');

322

} catch (error) {

323

console.error('Stream configuration error:', error.message);

324

}

325

326

// Filename access with anonymous execution

327

const anonymousLogger = new Signale();

328

console.log(anonymousLogger.filename); // "anonymous" if no file context

329

```

330

331

### Performance Considerations

332

333

Optimize logging performance for production use.

334

335

**Usage Examples:**

336

337

```javascript

338

const { Signale } = require('signale');

339

340

// Disable logging in production for performance

341

const logger = new Signale({

342

disabled: process.env.NODE_ENV === 'production'

343

});

344

345

// Or use log levels to filter

346

const prodLogger = new Signale({

347

logLevel: process.env.NODE_ENV === 'production' ? 'error' : 'info'

348

});

349

350

// Lazy evaluation with isEnabled check

351

if (logger.isEnabled()) {

352

const expensiveData = computeExpensiveLogData();

353

logger.debug('Expensive debug data: %j', expensiveData);

354

}

355

356

// Stream buffering for high-volume logging

357

const bufferedStream = new (require('stream').PassThrough)();

358

const highVolumeLogger = new Signale({

359

stream: bufferedStream

360

});

361

362

// Batch write to file periodically

363

setInterval(() => {

364

const fs = require('fs');

365

if (bufferedStream.readable) {

366

const data = bufferedStream.read();

367

if (data) {

368

fs.appendFileSync('high-volume.log', data);

369

}

370

}

371

}, 1000);

372

```

373

374

### Advanced Configuration Patterns

375

376

Combine multiple advanced features for sophisticated logging setups.

377

378

**Usage Examples:**

379

380

```javascript

381

const { Signale } = require('signale');

382

const fs = require('fs');

383

384

// Production-ready logger with all advanced features

385

class ProductionLogger {

386

constructor(options = {}) {

387

const {

388

environment = 'development',

389

logLevel = 'info',

390

secrets = [],

391

logFile = null

392

} = options;

393

394

const streams = [process.stdout];

395

if (logFile) {

396

streams.push(fs.createWriteStream(logFile, { flags: 'a' }));

397

}

398

399

this.logger = new Signale({

400

disabled: environment === 'test',

401

logLevel: environment === 'production' ? 'warn' : logLevel,

402

secrets: [...secrets, process.env.API_SECRET].filter(Boolean),

403

stream: streams,

404

config: {

405

displayTimestamp: true,

406

displayDate: environment === 'production',

407

displayFilename: environment === 'development'

408

}

409

});

410

411

// Add environment-specific secrets

412

if (environment === 'production') {

413

this.logger.addSecrets([

414

process.env.DATABASE_URL,

415

process.env.JWT_SECRET

416

].filter(Boolean));

417

}

418

}

419

420

// Expose logger methods

421

get info() { return this.logger.info.bind(this.logger); }

422

get warn() { return this.logger.warn.bind(this.logger); }

423

get error() { return this.logger.error.bind(this.logger); }

424

get success() { return this.logger.success.bind(this.logger); }

425

426

// Advanced methods

427

scope(...names) { return this.logger.scope(...names); }

428

time(label) { return this.logger.time(label); }

429

timeEnd(label) { return this.logger.timeEnd(label); }

430

}

431

432

// Usage

433

const prodLogger = new ProductionLogger({

434

environment: 'production',

435

logLevel: 'warn',

436

secrets: ['user-session-key'],

437

logFile: 'production.log'

438

});

439

440

prodLogger.warn('Production warning'); // Appears in console and file

441

prodLogger.info('Development info'); // Filtered out in production

442

```