Logging service
Service
The logging service provides a common logging mechanism for all packages and services.
It listens for messages from the message broker of type EventMessage.log_logged
and transmits these to the IBM Cloud LogDNA instance.
The logging service is the ingestion point for all important output generated by other services. This includes all relevant FFDC (First Failure Data Capture) information.
The purpose of FFDC is to collect enough information during the first occurrence of an issue to provide a fix without needing to reproduce the failure and perform additional debug of the problem.
Package APIs
The logging package is responsible for facilitating data transfer between services and the logging-service
.
In Standard run mode, it broadcasts messages to the messaging service.
In Dev mode, logs are written to stdout or stderr, depending on the log type.
Logging.isRemoteLoggingAllowed: boolean
Sets the global setting for whether or not remote logging is allowed to be enabled. This supersedes all environment-based switches and instance-based overrides. This is only really useful for testing purpose and for the logging service itself, which uses Logger objects, but does not bother writing them to the messaging infrastructure.
new Logging(config: LoggingConfig)
Instantiates a Logging
object with a given service and component name. All log messages given to this logging instance will automatically include the component and optionally specified LoggingOptions in the appropriate part of the resulting log entry.
Component strings can be anything that uniquely identifies an area of code, such as a class name, file name, etc.
Example
const logging = new Logging({ component: 'RequestCache' })
NOTE: By default, the service name in the resulting logs will come from the CARBON_SERVICE_NAME
environment variable. This can be overridden by specifying a service
in the LoggingConfig
object.
For all methods below, a “Loggable” object is defined as anything you’d typically expect to be able to provide to console.log
.
Logging#debug(message: Loggable): Promise<void>
Logs a debugging message. This includes things like important function entry/exit, the size of a list obtained from a remote source, the results after filtering an input set, etc.
NOTE: Debug messaging is enabled in the Dev run mode and disabled in the Standard run mode. It is safe and acceptable to leave debug statements in code, where appropriate, unlike
console.log
statements, which would typically be removed from production code.
NOTE: Debug logging can be turned on for a service running in Standard mode if
CARBON_DEBUG=true
is exported as an environment variables. This isn’t typically needed, but can be useful for advanced debugging of production-running applications.
Examples
logging.debug(`Pre-filter list size: ${orig.length}, Post-filter list size: ${filtered.length}`)
function someImportantOperation(inputValue: string): boolean {
logging.debug(`-> someImportantOperation args: ${inputValue}`)
// ...
logging.debug(`<- someImportantOperation returns: ${result}`)
return result
}
Logging#info(message: Loggable): Promise<void>
Logs an informational message. This is useful for point-in-time events, such as a service becoming ready, a user account being created, a configuration setting being updated, a new data ingestion endpoint becoming available, etc.
Examples
logging.info(`Web server now listening on port ${port}`)
Logging#warn(message: string | Error): Promise<void>
Logs a warning message. Warnings are typically unexpected situations, but do not represent a breakdown of the core application logic. Examples include a user account becoming locked due to failed login attempts, encountering an expected file that cannot be found or is blank, usages of deprecated APIs, an operation taking longer than expected, etc.
Examples
logging.warn(`Database collection ${collection.name} was empty. Recreating`)
Logging#error(message: string | Error): Promise<void>
Logs an error message. Errors are unexpected situations and often represent a breakdown in core logic. This often means entering the catch
block of a try/catch
statement. It can also mean encountering undefined
or null
where values are expected to be present.
Examples
try {
const dbConnection = db.connect()
dbConnection.query('stuff')
} catch (err) {
logging.error('Could not connect to database')
logging.error(err)
}
error(`processImage encountered a checksum mismatch. Expected: ${expected}, Was: ${actual}`)
Decorators and helpers
@Trace()
A decorator that automatically [debug] logs method entry and exit, along with the arguments and return value of the method.
withTrace()
A higher-order decoration function similar to @Trace()
, but for use outside of classes and/or in JS instead of TS.
safeStringify
A utility function to safely convert any object to a string representation, covering all edge cases of JS to prevent exceptions from being thrown in the process.
Note: This utility function is only useful to core logging infrastructure which needs to accept and log any arbitrary input from other code. It should not be used for any other type of logging and is not required in order to log data via the
Logging
class.
requestLogMiddleware
An ExpressJS middleware which can be use
d to provide logging for all requests coming through an express server.