|
| 1 | +import WorkInProgressNotice from '@site/src/components/WorkInProgressNotice'; |
| 2 | + |
| 3 | +# How to Configure Logging |
| 4 | + |
| 5 | +<WorkInProgressNotice /> |
| 6 | + |
| 7 | +**Control console output from the ATT&CK Data Model** |
| 8 | + |
| 9 | +The library emits log output during data source registration, bundle parsing, and refinement checks. This guide shows you how to silence that output, surface more diagnostic detail, or route messages to your own logger. |
| 10 | + |
| 11 | +## Problem |
| 12 | + |
| 13 | +Use this guide when you need to: |
| 14 | + |
| 15 | +- Silence library output entirely (e.g. when parsing many bundles in a loop and the noise becomes overwhelming) |
| 16 | +- See additional informational messages while debugging a data load |
| 17 | +- Forward log messages to a structured logger like `pino`, `winston`, or `bunyan` |
| 18 | +- Configure log behavior via an environment variable for different deployment environments |
| 19 | + |
| 20 | +## Default Behavior |
| 21 | + |
| 22 | +By default, the library logs at the `warn` level. This means: |
| 23 | + |
| 24 | +- `warn` and `error` messages are printed to the console |
| 25 | +- `info` messages (e.g. "Retrieved data", "Parsed data") are suppressed |
| 26 | +- `debug` messages are suppressed |
| 27 | + |
| 28 | +The default handler routes output to `console.log` (`debug`/`info`), `console.warn`, and `console.error`. |
| 29 | + |
| 30 | +## Log Levels |
| 31 | + |
| 32 | +| Level | Description | |
| 33 | +|----------|--------------------------------------------------------------------| |
| 34 | +| `debug` | Verbose diagnostic output. | |
| 35 | +| `info` | Informational status messages (data retrieval, parse counts, etc). | |
| 36 | +| `warn` | Validation issues in `relaxed` mode and deprecation warnings. | |
| 37 | +| `error` | Errors only. | |
| 38 | +| `silent` | Disables all output. | |
| 39 | + |
| 40 | +Levels are inclusive: setting the level to `info` enables `info`, `warn`, and `error` messages. |
| 41 | + |
| 42 | +## Solution 1: Silence All Output |
| 43 | + |
| 44 | +When parsing large bundles or iterating over relationships in a tight loop, the deprecation warnings and validation messages can dominate stdout. Silence them with `configureLogger`: |
| 45 | + |
| 46 | +```typescript |
| 47 | +import { configureLogger } from '@mitre-attack/attack-data-model'; |
| 48 | + |
| 49 | +configureLogger({ level: 'silent' }); |
| 50 | +``` |
| 51 | + |
| 52 | +## Solution 2: Surface Informational Output |
| 53 | + |
| 54 | +To see status messages emitted during data source registration: |
| 55 | + |
| 56 | +```typescript |
| 57 | +import { configureLogger } from '@mitre-attack/attack-data-model'; |
| 58 | + |
| 59 | +configureLogger({ level: 'info' }); |
| 60 | +``` |
| 61 | + |
| 62 | +## Solution 3: Configure via Environment Variable |
| 63 | + |
| 64 | +Set `ADM_LOG_LEVEL` to any valid level (`debug`, `info`, `warn`, `error`, `silent`): |
| 65 | + |
| 66 | +```bash |
| 67 | +ADM_LOG_LEVEL=silent node ./my-script.js |
| 68 | +``` |
| 69 | + |
| 70 | +This is useful when you want different log behavior in CI versus local development without changing code. An explicit `configureLogger({ level })` call always wins over the environment variable. |
| 71 | + |
| 72 | +## Solution 4: Provide a Custom Handler |
| 73 | + |
| 74 | +To integrate with a structured logger, supply a `LogHandler`: |
| 75 | + |
| 76 | +```typescript |
| 77 | +import { configureLogger } from '@mitre-attack/attack-data-model'; |
| 78 | +import type { LogHandler } from '@mitre-attack/attack-data-model'; |
| 79 | +import pino from 'pino'; |
| 80 | + |
| 81 | +const log = pino(); |
| 82 | + |
| 83 | +const handler: LogHandler = (level, message) => { |
| 84 | + log[level]({ source: 'attack-data-model' }, message); |
| 85 | +}; |
| 86 | + |
| 87 | +configureLogger({ level: 'info', handler }); |
| 88 | +``` |
| 89 | + |
| 90 | +The handler receives the level (`debug`, `info`, `warn`, or `error` — never `silent`) and the message string. Configure the level and handler independently, or together in a single call. |
| 91 | + |
| 92 | +## Solution 5: Reset to Defaults |
| 93 | + |
| 94 | +To restore the default level and handler — useful in test suites that mutate logger state: |
| 95 | + |
| 96 | +```typescript |
| 97 | +import { resetLogger } from '@mitre-attack/attack-data-model'; |
| 98 | + |
| 99 | +afterEach(() => { |
| 100 | + resetLogger(); |
| 101 | +}); |
| 102 | +``` |
| 103 | + |
| 104 | +## Reference |
| 105 | + |
| 106 | +```typescript |
| 107 | +import { |
| 108 | + configureLogger, |
| 109 | + resetLogger, |
| 110 | +} from '@mitre-attack/attack-data-model'; |
| 111 | +import type { |
| 112 | + LogLevel, |
| 113 | + LogHandler, |
| 114 | + LoggerConfig, |
| 115 | +} from '@mitre-attack/attack-data-model'; |
| 116 | +``` |
| 117 | + |
| 118 | +- `configureLogger(config: LoggerConfig)`: Apply the supplied `level` and/or `handler`. Either field is optional — provide only what you want to change. |
| 119 | +- `resetLogger()`: Clear any overrides; subsequent calls fall back to the `ADM_LOG_LEVEL` environment variable, or to `warn` if it is unset. |
| 120 | + |
| 121 | +--- |
0 commit comments