Skip to main content
Version: 0.7

Logging

A Credo agent logs nothing until you give it a logger. The agent and all its modules, including tenant agents, use that one logger.

Console logger​

Pass a logger as config.logger:

agent.ts
import { Agent, ConsoleLogger, LogLevel } from '@credo-ts/core'
import { agentDependencies } from '@credo-ts/node'

const agent = new Agent({
config: {
// Logs Info, Warn, Error and Fatal messages
logger: new ConsoleLogger(LogLevel.Info),
},
dependencies: agentDependencies,
modules: {
...storage, // Storage and key management, see Agent setup
},
})

ConsoleLogger prints each message with its level as a prefix, such as INFO: Creating agent with config, using the console method that matches the level. Data passed with a message is printed as JSON. Errors in the data keep their message and stack.

Log levels​

A logger prints messages at its own level and above:

LevelWhat Credo logs at this level
LogLevel.TestNothing. Set it to print every message.
LogLevel.TraceThe most detailed steps, such as key imports, and requests to ledgers and their results.
LogLevel.DebugProcessing steps of protocols, including the content of DIDComm messages the agent sends.
LogLevel.InfoLifecycle events, such as the agent's config when it's created, storage updates, received DIDComm messages and created tenants.
LogLevel.WarnProblems the agent recovers from, such as a credential that breaks a recommendation of its specification.
LogLevel.ErrorFailed operations, such as a DIDComm message that can't be delivered.
LogLevel.FatalA storage update that failed.
LogLevel.OffNothing. The default.

Use Info or higher in production. At Debug and Trace, logs can contain message contents, credential data and other personal data.

Your own logger​

To send logs to your own logging library, implement the Logger interface from @credo-ts/core: a logLevel property and the methods test, trace, debug, info, warn, error and fatal, each taking a message and optional data. Extending BaseLogger saves some work: it stores the level and has isEnabled(level). This logger writes one JSON object per line:

JsonLogger.ts
import { BaseLogger, LogLevel, replaceError } from '@credo-ts/core'

type LogData = Record<string, unknown>

export class JsonLogger extends BaseLogger {
private log(level: LogLevel, message: string, data?: LogData) {
if (!this.isEnabled(level)) return

// replaceError keeps the message and stack of errors, which JSON.stringify would drop
console.log(JSON.stringify({ level: LogLevel[level], time: new Date().toISOString(), message, data }, replaceError))
}

public test(message: string, data?: LogData) {
this.log(LogLevel.Test, message, data)
}

public trace(message: string, data?: LogData) {
this.log(LogLevel.Trace, message, data)
}

public debug(message: string, data?: LogData) {
this.log(LogLevel.Debug, message, data)
}

public info(message: string, data?: LogData) {
this.log(LogLevel.Info, message, data)
}

public warn(message: string, data?: LogData) {
this.log(LogLevel.Warn, message, data)
}

public error(message: string, data?: LogData) {
this.log(LogLevel.Error, message, data)
}

public fatal(message: string, data?: LogData) {
this.log(LogLevel.Fatal, message, data)
}
}

Pass it as config.logger, for example new JsonLogger(LogLevel.Info).