@lexamica-modules/logger
Version:
The various loggers and transports used for API logging in the Lexamica Eco-system
344 lines (326 loc) • 9.9 kB
text/typescript
import { format } from 'logform';
import { isDevelopment, isProduction, isStaging } from './environment';
import winston from 'winston';
import { getFormat } from './formatting';
import SlackTransport from 'winston-slack-webhook-transport';
import DataDogTransport from '@shelf/winston-datadog-logs-transport';
export interface ICreateLoggerEnvironmentOptions {
development?: {
slack_webhook?: string;
};
staging?: {
slack_webhook?: string;
};
}
interface ICreateLoggerOptions {
route?: ICreateLoggerEnvironmentOptions;
task?: ICreateLoggerEnvironmentOptions;
user?: ICreateLoggerEnvironmentOptions;
integration?: ICreateLoggerEnvironmentOptions;
auth?: ICreateLoggerEnvironmentOptions;
}
/**
*
* @param dataDogApiKey {string}
* @param service {string}
* @param defaultLevel { "silly" |'debug" |"verbose" | "info" | "warning" | "error" | }
* @param environment { string }
* @param formatType {"color" | "json" }
* @param consoleParams { winston.ConsoleTransportOptions }
* @param loggerParams { winston.LoggerOptions }
* @return {winston.Logger}
*/
function createLogger({
dataDogApiKey,
service,
defaultLevel = 'info',
environment,
formatType = 'json',
requireConsoleTransport = false,
requireDataDogTransport = false,
consoleParams,
loggerParams,
metadata = {},
slackWebhook,
slackLogLevel,
options,
}: {
dataDogApiKey: string;
service: string;
defaultLevel?: 'verbose' | 'info' | 'warn' | 'error';
environment: string;
formatType?: 'color' | 'json';
requireConsoleTransport?: boolean;
requireDataDogTransport?: boolean;
consoleParams: Record<string, unknown>;
loggerParams: Record<string, unknown>;
metadata?: Record<string, string>;
slackWebhook?: string;
slackLogLevel?: 'verbose' | 'info' | 'warn' | 'error';
options?: ICreateLoggerEnvironmentOptions;
}): winston.Logger {
if (
!dataDogApiKey &&
(!isDevelopment(environment) || requireDataDogTransport)
) {
throw new Error(
`Must provide a dataDogApiKey for logger in staging, demo, and production environments`
);
}
const transports = [];
if (isDevelopment(environment) || requireConsoleTransport) {
transports.push(
new winston.transports.Console({
...consoleParams,
handleExceptions: true,
})
);
}
if (isProduction(environment) && !!slackWebhook) {
const transport = new SlackTransport({
webhookUrl: slackWebhook,
level: slackLogLevel ?? 'info',
});
transports.push(transport);
}
if (isDevelopment(environment) && !!options?.development?.slack_webhook) {
const transport = new SlackTransport({
webhookUrl: options.development.slack_webhook,
level: slackLogLevel ?? 'info',
});
transports.push(transport);
}
if (isStaging(environment) && !!options?.staging?.slack_webhook) {
const transport = new SlackTransport({
webhookUrl: options.staging.slack_webhook,
level: slackLogLevel ?? 'info',
});
transports.push(transport);
}
if (!isDevelopment(environment) || requireDataDogTransport) {
transports.push(
new DataDogTransport({
apiKey: dataDogApiKey,
metadata: {
...metadata,
service,
ddsource: `node:${process.version ?? '0.0.0'}`,
host: `${service}:${environment}`,
environment,
},
})
);
}
return winston.createLogger({
format: getFormat(formatType),
level: defaultLevel || 'info',
exitOnError: false,
...loggerParams,
transports,
});
}
/**
* Logger initialization function
* @param datadog_key the API key to connect to datadog via transporter
* @param service a service string. Typically an API name or some other id
* @param environment the usage environment. Use the NODE_ENV env var
* @param slack_webhook give the webook url to transport these logs to a slack channel
* @returns {winston.Logger}
*/
export const authLogger = (
datadog_key: string,
service: string,
environment: string,
slack_webhook: string,
defaultLevel: 'verbose' | 'info' | 'warn' | 'error',
options?: ICreateLoggerEnvironmentOptions
) =>
createLogger({
service: `${service}/auth`,
dataDogApiKey: datadog_key,
defaultLevel,
environment: environment,
consoleParams: isDevelopment(environment)
? {
format: format.printf(({ message }) => message),
}
: {},
loggerParams: {},
slackWebhook: slack_webhook,
options,
});
/**
* Logger initialization function
* @param datadog_key the API key to connect to datadog via transporter
* @param service a service string. Typically an API name or some other id
* @param environment the usage environment. Use the NODE_ENV env var
* @param slack_webhook give the webook url to transport these logs to a slack channel
* @returns {winston.Logger}
*/
export const taskLogger = (
datadog_key: string,
service: string,
environment: string,
slack_webhook: string,
defaultLevel: 'verbose' | 'info' | 'warn' | 'error',
options?: ICreateLoggerEnvironmentOptions
) =>
createLogger({
service: `${service}/tasks`,
dataDogApiKey: datadog_key,
defaultLevel,
environment: environment,
consoleParams: isDevelopment(environment)
? {
format: format.printf(({ message }) => message),
}
: {},
loggerParams: {},
slackWebhook: slack_webhook,
options,
});
/**
* Logger initialization function
* @param datadog_key the API key to connect to datadog via transporter
* @param service a service string. Typically an API name or some other id
* @param environment the usage environment. Use the NODE_ENV env var
* @param slack_webhook give the webook url to transport these logs to a slack channel
* @returns {winston.Logger}
*/
export const userLogger = (
datadog_key: string,
service: string,
environment: string,
slack_webhook: string,
defaultLevel: 'verbose' | 'info' | 'warn' | 'error',
options?: ICreateLoggerEnvironmentOptions
) =>
createLogger({
service: `${service}/users`,
dataDogApiKey: datadog_key,
defaultLevel,
environment: environment,
consoleParams: isDevelopment(environment)
? {
format: format.printf(({ message }) => message),
}
: {},
loggerParams: {},
slackWebhook: slack_webhook,
options,
});
/**
* Logger initialization function
* @param datadog_key the API key to connect to datadog via transporter
* @param service a service string. Typically an API name or some other id
* @param environment the usage environment. Use the NODE_ENV env var
* @param slack_webhook give the webook url to transport these logs to a slack channel
* @returns {winston.Logger}
*/
export const integrationLogger = (
datadog_key: string,
service: string,
environment: string,
slack_webhook: string,
defaultLevel: 'verbose' | 'info' | 'warn' | 'error',
options?: ICreateLoggerEnvironmentOptions
) =>
createLogger({
service: `${service}/integrations`,
dataDogApiKey: datadog_key,
defaultLevel,
environment: environment,
consoleParams: isDevelopment(environment)
? {
format: format.printf(({ message }) => message),
}
: {},
loggerParams: {},
slackWebhook: slack_webhook,
options,
});
/**
* Logger initialization function
* @param datadog_key the API key to connect to datadog via transporter
* @param service a service string. Typically an API name or some other id
* @param environment the usage environment. Use the NODE_ENV env var
* @returns {winston.Logger}
*/
export const routeLogger = (
datadog_key: string,
service: string,
environment: string,
defaultLevel: 'verbose' | 'info' | 'warn' | 'error',
options?: ICreateLoggerEnvironmentOptions
) =>
createLogger({
service: `${service}/routes`,
dataDogApiKey: datadog_key,
defaultLevel,
environment: environment,
consoleParams: isDevelopment(environment)
? {
format: format.printf(({ message }) => message),
}
: {},
loggerParams: {},
options,
});
export class Loggers {
RouteLogger: winston.Logger;
TaskLogger: winston.Logger;
UserLogger: winston.Logger;
IntegrationLogger: winston.Logger;
AuthLogger: winston.Logger;
constructor(
datadog_api_key: string,
service: string,
environment: 'development' | 'staging' | 'demo' | 'production',
slack_user_logs_webhook: string,
slack_task_logs_webhook: string,
slack_auth_logs_webhook: string,
slack_integration_logs_webhook: string,
defaultLevel: 'verbose' | 'info' | 'warn' | 'error' = 'info',
options: ICreateLoggerOptions = {}
) {
this.RouteLogger = routeLogger(
datadog_api_key,
service,
environment,
defaultLevel,
options.route
);
this.TaskLogger = taskLogger(
datadog_api_key,
service,
environment,
slack_task_logs_webhook,
defaultLevel,
options.task
);
this.UserLogger = userLogger(
datadog_api_key,
service,
environment,
slack_user_logs_webhook,
defaultLevel,
options.user
);
this.IntegrationLogger = integrationLogger(
datadog_api_key,
service,
environment,
slack_integration_logs_webhook,
defaultLevel,
options.integration
);
this.AuthLogger = authLogger(
datadog_api_key,
service,
environment,
slack_auth_logs_webhook,
defaultLevel,
options.auth
);
}
}