npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@prftesp/cle-logger

v2.3.1

Published

CLE Node Logging Library

Downloads

252

Readme

CLE Logger

A configurable javascript remote logging library, for the browser and Node.js, with built-in support for Twilio Flex UI.

Documentation

Target Environment

Any Node.js environment capable of running and/or transpiling code compatible with Node.js v8.10 or above.

ES5 Compatible Version

If you need an ES5 compatible version (for example you need IE11 support), use this package: https://www.npmjs.com/package/@prftesp/cle-logger-es5. This package is not regularly released with the main library, and should be used only when absolutely necessary. If you need to support IE11, don't forget to include the necessary polyfills, mainly for Promise support. To do this, you can include this script tag on the page, before you load this library <script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=es6"></script>, or visit https://polyfill.io for more options.

Please note that the ES5 version is generated, and is sharing the same code and documentation as the main library. This is why the rest of the documentation doesn't mention the ES5 version in text or examples. The only difference is how you reference it (@prftesp/cle-logger vs @prftesp/cle-logger-es5). To install it use npm install @prftesp/cle-logger-es5, and to import it use import { cleLogger } from "@prftesp/cle-logger-es5";.

Simple Example

import { cleLogger } from "@prftesp/cle-logger";

cleLogger.init({
	logSinks: [
		{
			name: "console sink",
			log: cleLogger.consoleLogger,
			piiSafe: true,
			logLevel: cleLogger.logLevels.VERBOSE,
		},
	],
});

// will log message to console
cleLogger.info("log message");

Installation

$ npm install @prftesp/cle-logger

Features

  • Runs in Node.js and the browser
  • Remote logging
  • Multiple log sinks
  • Support for tagging logs containing PII data to be delivered only to specified log sinks
  • Remote minimum log level overrides
  • Support for logging Twilio Flex Actions with debouncing for high volume
  • Optionally await logs to ensure requests complete in time before disposing resources (e.g. Twilio Functions)
  • Support for tagging logs with custom component names or correlation tokens
  • Send Twilio event hook data to a custom backend

Configuration

To configure the logger call the init function and pass in a configuration object. The library needs to be initialized and configured on page load, or in case of Node.js, in the main javascript file. Use in subsequent pages/components/files doesn't require configuration, the library behaves like a singleton.

Available options

import { cleLogger } from "@prftesp/cle-logger";

cleLogger.init({
	// Twilio account sid, required for use with CLE
	accountSid: "ACe3d7f8a771178fcerea4616445b0ed6l",

	// Will be associated with all logs,
	// if not provided, a unique uuid will be generated
	correlationToken: "b4b57b74-d3dc-4fd5-8e09-d4794c829f60",

	// An array of that will receive an array of log objects,
	// and can optionally return a promise. Please see the
	// "Log Sinks" section for more information.
	logSinks: [
		{
			// name of the log sink
			name: "exampleConsoleSink",
			// log handler function
			log: cleLogger.consoleLogger,
			// This flag defines if the log message is processed by this sink when the contains
			// PII parameter of the log statement is true. piiSafe of true indicates all log
			// messages are allowed (even when contains PII is true); piiSafe of false indicates
			// only log messages with contains PII set to false will be processed by this log sink.
			// Defaults to false
			piiSafe: true,
			// log level for the sink, defaults to INFO
			logLevel: cleLogger.logLevels.VERBOSE,
		},
	],

	// A way to display additional errors internal to the logger, useful for debugging, defaults to false
	logErrorsToConsole: false,

	// If logging Twilio Flex Actions, provide a list of actions
	// to be excluded from logs
	excludedFlexActionNames: ["SendTyping"],

	// A custom endpoint to fetch log level overrides
	// NOTE: the provided url should always end with 'accountSid=',
	// the library will append the accountSid
	minLogLevelOverrideUrl: "https://example.com/api/min-log-level?accountSid=",

	// An instance of ('@twilio/flex-ui').Manager.
	// If provided, it will be used to get the worker sid and call sid (only during a call), and
	// automatically include it in 'customProperties' log property and with every log
	twilioFlexManager: manager,

	// To send data from Twilio event hooks, to a custom backend,
	// configure one or more endpoints for each event type
	twilioEventHooks: {
		taskRouter: ["https://example.com/twilio-task-router-hook?key=123"],
		debugger: ["https://example.com/twilio-debugger-hook?key=123"],
		callStatus: ["https://example.com/twilio-call-status-hook?key=123"],
	},
});

API

The logger can be imported as an object in CommonJs or ES6 syntax:

import { cleLogger } from "@prftesp/cle-logger";
// or
const cleLogger = require("@prftesp/cle-logger");

Alternatively, all top level members of the cleLogger are available as named exports and can be imported separately:

import { info, init, consoleLogger, logLevels, componentNames } from "@prftesp/cle-logger";

init({
	logSinks: [{
		name: "exampleConsoleSink",
		log: consoleLogger,
		piiSafe: true,
		logLevel: logLevels.VERBOSE
	}],
});

info("log message", { data: 123 }, null, componentNames.DASHBOARD);

// vs

import { cleLogger } from "@prftesp/cle-logger";

init({
	cleLogger.logSinks: [{
		name: "exampleConsoleSink",
		log: cleLogger.consoleLogger,
		piiSafe: true,
		logLevel: cleLogger.logLevels.VERBOSE
	}],
});

cleLogger.info("log message", { data: 123 }, null, cleLogger.componentNames.DASHBOARD);

Log sinks

Log sinks are configurable log outputs, that enable you to send logs to multiple destinations in parallel. Log sinks can be provided via the logSinks config. The logSinks configuration defines an array of objects with each object defining the log sink activity. All provided log sinks will be executed in parallel. A log sink configuration must include the following properties:

  • name: this is an identifiable name for the logger and must be unique per log sink defined
  • log: this indicates the logic to process on each batch of logs processed by the sink. There are several built in processing functions that can be used or you can insert any code inline with this definition. The built in processing functions are consoleLogger which will send the log statements to the attached console or remoteLogger which will send the log statements to the specified url provided as a definition on the parameter (i.e. remoteLogger("https://mylogger.url"). For a custom log processing implementation, the logic must be async operations and must return a Promise object. The custom log method will receive an array of log objects for you to handle. You can find out more about the log object type in the Log Object section. Here is an example of a custom log function:
logs => {
	// log each received log to the console separately
	logs.forEach(log => console.log(log));
	return Promise.resolve();
};
  • logLevel: defines the minimum default log level that will be processed by this log sink. Log levels lower than the minimum level will not be processed by this log sink. The minimum default log level can be overridden at run time by the value returned from the overall minLogLevelOverrideUrl that is set up in the library init.
  • piiSafe: indicates if log messages with a containsPII parameter value of true should be processed by the log sink. If containsPII parameter value on the log message is true and piiSafe is false then the log message will not be processed by this log sink, if piiSafe is true then it will. If the containsPII parameter value is false on the log message than it is always processed by the log sink regardless of the piiSafe value.

Custom log sink configuration example. In this example, the custom code executed for each log statement is to append the log into a file. Note how a Promise is returned as required:

{
	// name of the log sink
	name: "exampleConsoleSink",
	// log handler function - this is where you put your custom handling code and
	// remember to always return a promise. If your operation is not asynchronous,
	// you can do this by returning Promise.resolve().
	log: logs => {
		fs.appendFile(
			"./log.txt",
			`${JSON.stringify(logs)}`,
			console.log
		);
		return Promise.resolve();
	},
	// should this log sink accept PII data, defaults to false
	piiSafe: true,
	// log level for the sink, defaults to INFO
	logLevel: cleLogger.logLevels.VERBOSE
}

Example log sink configuration that uses a custom coded sink and both standard console and remote logging sinks:

const fs = require("fs");
const cleLogger = require("@prftesp/cle-logger");

cleLogger.init({
	logSinks: [
		{
			name: "fileSink",
			log: logs => {
				fs.appendFile("./log.txt", `${JSON.stringify(logs)}`, console.log);
				return Promise.resolve();
			},
		},
		{
			name: "remoteSink",
			log: cleLogger.remoteLogger("https://my.log.url"),
			logLevel: cleLogger.logLevels.WARN,
			piiSafe: true,
		},
		{
			name: "consoleSink",
			log: cleLogger.consoleLogger,
			logLevel: cleLogger.logLevels.VERBOSE,
		},
	],
});

Logging statements

To create logs, you can use one of the logging function available. They all take the same arguments, described below, and log at a corresponding log level. For example, if you use the cleLogger.verbose logging function, and your log sink is configured with logLevel: cleLogger.logLevels.VERBOSE, that log sink will receive the log. If your log sink is configured with a higher log level, for example logLevel: cleLogger.logLevels.INFO, then it would not receive the verbose log.

Here are the available logging functions:

import { cleLogger } from "@prftesp/cle-logger";

cleLogger.verbose(...);
cleLogger.info(...);
cleLogger.warn(...);
cleLogger.error(...);
cleLogger.critical(...);

The functions are all async, return Promise<void>, and can be optionally awaited. The suggested approach is to await log functions in environments where there is low risk of resources being disposed before logging completes (e.g. browser, custom Node.js backends). It is suggested not to await logs in serverless environments (e.g. Twilio Functions, AWS Lambdas), that have limited execution time.

Logging parameters

All logging functions take the same parameters:

  • message: the only required property, no logs will be generated without it
    • type: string
    • required: yes
  • additionalData: any additional log data you would like to include with the log, can be any data type
    • type: any
    • required: no
    • default value: null
  • customProperties: a single level deep object of important properties you would like to distinguish from general log data, like various sids CLE uses it to index these properties in Application Insights. For CLE, try to use keys found in cleLogger.customPropertyKeys
    • type: object
    • required: no
    • default value: {}
  • componentName: another useful way to 'tag' your logs for easier searching. Can be any string, but for CLE, try to use available options in cleLogger.componentNames
    • type: string
    • required: no
    • default value: ""
  • logCode: log code, can be any number used to categorize logs. For defined ranges see the log codes section.
    • type: number
    • required: no
    • default value: 0
  • correlationToken: correlation token to be associated with this log only
    • type: string
    • required: no
    • default value: token provided in init, or a generated token if one wasn't provided
  • containsPII: does the log contain PII data, defaults to false. If set to true, the log will be passed in only to those log sinks that have piiSafe set to true. For more info see the handling PII data section.
    • type: boolean
    • required: no
    • default value: false

Alternative logging functions

If you would prefer to pass in an object to logging functions, instead of using a long list of parameters, you can use the new logging functions available under the cleLogger.v2 namespace. These functions are namespaced to keep backwards compatibility, but you should feel free to use them going forward. The behavior of these functions is exactly the same as with those listed in logging statements section.

Example verbose logging statement with both versions of the logging function:

import { cleLogger } from "@prftesp/cle-logger";

cleLogger.verbose(
	"Log message", // message
	{ data: "test" }, // additionalData
	{ [cleLogger.customPropertyKeys.CALL_SID]: "my-call-sid" }, // customProperties
	cleLogger.componentNames.SESSION, // componentName
	70123, // logCode
	"my-token", // correlationToken
	true, // containsPII
);

cleLogger.v2.verbose(
	"Log message",
	{
		additionalData: { data: "test" },
		customProperties: { [cleLogger.customPropertyKeys.CALL_SID]: "my-call-sid" },
		componentName: cleLogger.componentNames.SESSION,
		logCode: 70123,
		correlationToken: "my-token",
		containsPII: true,
	}
);

As you can see in the examples above, both functions take in the same values, but the v2 version makes it a bit easier to see which value corresponds to each key. It comes down to personal preference, use whichever you prefer.

Logging constants

Logging levels

Logging level constants should be used when configuring the log level of a log sink.

import { cleLogger } from "@prftesp/cle-logger";

cleLogger.logLevels.VERBOSE; // verbose
cleLogger.logLevels.INFO; // info
cleLogger.logLevels.WARN; // warn
cleLogger.logLevels.ERROR; // error
cleLogger.logLevels.CRITICAL; // critical

Component names

Defines a set of commonly used components that should be used for the componentName parameter value of a log statement if you are logging from one of these common components in a Twilio implementation.

import { cleLogger } from "@prftesp/cle-logger";

cleLogger.componentNames.SESSION;
cleLogger.componentNames.DIALER;
cleLogger.componentNames.DASHBOARD;
cleLogger.componentNames.AFTERCALL;
cleLogger.componentNames.SUPERVISOR;

Custom property keys

Defines a set of commonly used key that should be used when defining the custom properties object that is supplied in the customProperties parameter of any logging statement.

import { cleLogger } from "@prftesp/cle-logger";

cleLogger.customPropertyKeys.CHANNEL_SID;
cleLogger.customPropertyKeys.TASK_SID;
cleLogger.customPropertyKeys.CALL_SID;
cleLogger.customPropertyKeys.WORKFLOW_SID;
cleLogger.customPropertyKeys.WORKER_SID;

Log codes

It can be helpful when investigating issues to only view logs related to specific areas of a system. Use Log Codes to give a category definition for what area of the contact center the log activity occurred within. Use numbers within the following pre-defined log code ranges or define custom log codes by using your own numbers higher than 300,000.

  • 100 000 - 109 999 => CALL_STATUS
  • 110 000 - 119 999 => IVR
  • 120 000 - 129 999 => ROUTING
  • 130 000 - 139 999 => AGENT_ACTION
  • 140 000 - 149 999 => TRANSFER
  • 150 000 - 159 999 => RM_INTEGRATION
  • 160 000 - 169 999 => WFM_INTEGRATION
  • 170 000 - 179 999 => CUSTOM_INTEGRATION
  • 180 000 - 189 999 => SUPERVISOR_ACTIVITY

Registering Twilio Actions

It is important to log information from the Twilio Flex UI for all implementations even when there is little customization happening. Many developers find it useful to generate log activity when some, or any, of the Twilio Actions occur within the Twilio Flex UI. Twilio Actions are events that arise from the Twilio Flex UI base implementation and indicate when certain activity is occurring - such as an agent hanging up a call. The CLE Logger library can be setup to automatically register all, or selected, Twilio Actions such that right after any code tied to the Action event has been executed a log statement is written indicating the Action occurred. This log statement will also automatically include the action event payload. To enable this logging capability, use the following approach to register the Twilio Actions. This only needs to be performed once during the initialization of the Twilio Flex UI page on the client.

Example in a Twilio Flex UI plugin:

import { cleLogger } from "@prftesp/cle-logger";

/**
 * @param flex { typeof import('@twilio/flex-ui') }
 * @param manager { import('@twilio/flex-ui').Manager }
 */
init(flex, manager) {
	cleLogger.init({
		accountSid: "your-account-sid"
	});

	cleLogger.registerTwilioActions(flex);
}

Note: A Twilio account sid must be provided during init with the accountSid parameter, otherwise the actions won't be logged.

The logger will loop through all actions found under flex.Actions.actions, and attach after event handlers to log the action name and payload. Any private properties found in the payload (starting with '_') will be stripped out before logging. As these logs can be frequent, they will be sent in batches of 10 or every second, whichever comes first. Not all Action events need to be logged and by using the excludedFlexActionNames property in the logger configuration the Action events not desired can be ignored. Any actions names configured in excludedFlexActionNames will not be included in the logs.

Important Registering Twilio Actions must be done once per page load, otherwise duplicate actions will be registered. When using multiple Twilio Flex UI plugins, it's recommended to register Twilio Actions only in one of the plugins, or use a dedicated plugin for this purpose.

Twilio Actions log levels

Below is a list of associated log levels for known Twilio Actions, any unknown action will have a log level of INFO.

AcceptTask: INFO;
CancelTransfer: INFO;
CompleteTask: INFO;
HangupCall: INFO;
HideDirectory: VERBOSE;
HistoryGo: VERBOSE;
HistoryGoBack: VERBOSE;
HistoryGoForward: VERBOSE;
HistoryPush: VERBOSE;
HistoryReplace: VERBOSE;
HoldCall: INFO;
HoldParticipant: INFO;
KickParticipant: INFO;
Logout: INFO;
MonitorCall: INFO;
NavigateToView: INFO;
RejectTask: INFO;
SelectTask: INFO;
SelectTaskInSupervisor: INFO;
SelectWorkerInSupervisor: INFO;
SendMessage: INFO;
SendTyping: VERBOSE;
SetActivity: INFO;
SetInputText: VERBOSE;
ShowDirectory: VERBOSE;
StopMonitoringCall: INFO;
ToggleMute: INFO;
ToggleSidebar: VERBOSE;
TransferTask: INFO;
UnholdCall: INFO;
UnholdParticipant: INFO;
WrapupTask: INFO;

Twilio Event Hooks

Currently, the Twilio console only supports adding a single hook for events such as debugger and task router. To support proxying data to additional backends, you can configure custom hook urls with twilioEventHooks option, and use the following functions to send event data to a custom endpoint.

NOTE: this assumes you have a Node.js API to register as hooks with Twilio. You can then use this package in your API to proxy the event data to other endpoints. The content type of data sent by the logger is application/x-www-form-urlencoded to be consistent with the format Twilio is using. The data sent with the logger should be exactly what your api received from Twilio.

import { cleLogger } from "@prftesp/cle-logger";

cleLogger.init({
	// unrelated init properties omitted from this example.
	// include in the twilioEventHooks array an entry for only the event hooks
	// the executing code is going to relay. For example, if the code is only
	// handling task router web hook events then you would only need to define
	// the taskRouter relay url here.
	twilioEventHooks: {
		taskRouter: ["https://example.com/twilio-task-router-hook?key=123"],
		debugger: ["https://example.com/twilio-debugger-hook?key=123"],
		callStatus: ["https://example.com/twilio-call-status-hook?key=123"],
	},
});

cleLogger.sendTwilioDebuggerEvents(twilioDebuggerEventData);
cleLogger.sendTwilioTaskRouterEvent(twilioTaskRouterEventData);
cleLogger.sendTwilioCallStatusEvent(twilioCallStatusEventData);

Example Azure Function hook for debugger events:

const cleLogger = require("@prftesp/cle-logger");

module.exports = async function(context, req) {
	cleLogger.init({
		twilioEventHooks: {
			debugger: ["https://example.com/twilio-debugger-hook?key=123"],
		},
	});

	// log to console
	cleLogger.info("Received Twilio debugger event");

	// send event data to a configured url
	await cleLogger.sendTwilioDebuggerEvents(context.req.body);
};

NOTE WHEN USING THIS FUNCTIONALITY IN TWILIO FUNCTIONS: if using Twilio functions to setup the relay, an additional step is needed to ensure the correct format is sent. Right now, Twilio function will automatically convert the event data to json, and there doesn't seem to be a way to get the raw request body. To work around this, you need to manually convert the json event data back to x-www-form-urlencoded format.

Example Twilio function task router relay using the form-urlencoded npm package to convert the data to x-www-form-urlencoded format:

const cleLogger = require("@prftesp/cle-logger");
const formurlencoded = require("form-urlencoded").default;

exports.handler = async function(context, event, callback) {
	cleLogger.init({
		twilioEventHooks: {
			taskRouter: ["https://example.com/twilio-task-router-hook?key=123"],
		},
	});

	await cleLogger.sendTwilioTaskRouterEvent(formurlencoded(event));

	callback();
};

Version

Version will be automatically included in all logs.

import { cleLogger } from "@prftesp/cle-logger";

cleLogger.version; // 1.0.0

Error To Object

Utility function to convert an Error object to a plain JS object, with all properties preserved. When serialized, Error objects will omit custom properties from the output which makes debugging difficult. This utility will traverse all properties in the Error object, and output a plain JS object with all properties including the stack trace. See an example below.

import { cleLogger } from "@prftesp/cle-logger";

const err = new Error("error message");
console.log(err); // "Error: error message\n    at Object.<anonymous> …"

const errObject = cleLogger.errorToObject(err);
console.log(errObjct); // {name: 'Error', message: 'error message', stack: 'Error: error message\n    at Object.<anonymous> …'}

Example usage when logging errors:

import { cleLogger } from "@prftesp/cle-logger";

try {
	// some code that can throw an error
} catch (error) {
	cleLogger.error("My error message", cleLogger.errorToObject(error));
}

Log Object

The following is the type definition of the log object received by log sinks. It consists of properties provided in log messages, as well as some that are automatically inserted like the eventDate. You can use this information to customize your logs inside a custom log sink (e.g. filter out unwanted logs, modify some of the properties to include more data, or any kind of conditional logic based on the value of these properties). If using the built in remoteLogger log processor with your custom backend, you can expect an array of these objects to be sent to your log endpoint. For more info about implementing a custom logging endpoint see the remote logging section.

{
	// Account sid if provided during init
	accountSid: string;

	// Any additional log data to be included with the log
	additionalData: unknown;

	// Component name, if provided
	componentName: string;

	// Generated or configured token
	correlationToken: string;

	// Current UTC datetime in ISO 8601 format
	eventDate: string;

	// Log level
	level: string;

	// Log code, if provided
	logCode: number;

	// Log message
	message: string;

	// A single level deep object of important properties you would
	// like to distinguish from general log data, like various sids
	properties: object;

	// BrowserFunction if the environment is the browser
	// CloudFunction if the environment is Node.js
	source: string;

	// Indicates that the log contains PII data
	containsPII: boolean;

	// Logging library version
	loggerVersion: string;
}

Handling PII Data

The logger provides support for helping to protect log messages or data that need to include PII (Personally Identifiable Information). While the logger has several mechanisms that can be used to flag logs that contain PII and block PII from going to particular log sinks, it is still ultimately the developers responsibility to ensure PII is flagged or marked appropriately for the logger to know when it exists - the logger cannot automatically detect if PII is part of a log statement or data object. The general guideline is that developers should avoid including any PII data in log information whenever possible. In the instances where PII data must be included there are several mechanisms the logger supports to help indicate PII data and protect where it is sent.

A containsPII parameter exists on log statement methods. This flag should be set to true if there is PII data, or any potential chance of it, in the log message, additional data or custom properties data. When this flag is set to true then it will only allow log sinks that have the piiSafe configuration set to true to receive and process the log message. piiSafe indicates on a log sink whether that log sink receiver is able to internally store PII data OR has logic to strip PII data that is tagged in the message or from pre-configured additional data fields before the log is written to any storage or output device. When sending data to any remoteLogger endpoint the log sink can be marked piiSafe only as long as data is appropriately tagged in messages and/or the names of custom properties that might have PII values in additional data are pre-configured AND the endpoint implementer has verified and ensured their receiving code will remove marked PII data immediately before sending logs to any output or storage media.

To tag any part of the message parameter in a log statement as containing PII within the actual log message use the tagPII utility. The tagPII utility will indicate to a remote backend that the text between the tags should be stripped or masked before sending logs to any output or storage media.

Example tagged output:

import { tagPII } from "@prftesp/cle-logger";

const msg = `message sent to ${tagPII("[email protected]")}`; // message sent to [email protected]__PII_

Advanced Configuration

Remote logging

The library provides a built in way to transmit logs to a remote http endpoint using the remoteLogger logs processor. The remoteLogger can be directed at a known listener such as CLE or you can create your own custom log listener. In addition, the log level in effect can be controlled remotely setting the minLogLevelOverrideUrl to an http address that will return the current log level to use instead of any defined default logLevel on each logSink. The minLogLevelOverrideUrl can point to a known central API such as CLE or you can create your own endpoint.

The following sections outline how to create your own endpoints for either receiving log messages from the remoteLogger log sink or providing the current log level override to it.

Remote log endpoint

To implement your own remote logging endpoint, all you have to do is accept POST requests, with a JSON payload of an array of log objects, and return either { success: true } or { success: false }. The endpoint should always return a 200 OK status even if your server code fails so that the CLE logger does not cause failures in the business logic in which it is embedded. A good use-case would be leveraging a serverless api platform to output logs to a queue.

Example of an Azure Function that can receive requests from the remoteLogger log sink:

module.exports = async function(context, req) {
	context.log(req.body); // body will have the log array

	context.res = {
		status: 200,
		body: { success: true },
	};
};

Remote log level override

The minLogLevelOverrideUrl configuration property is used to provide an endpoint that accepts GET requests and a accountSid query string parameter. accountSid can be used to scope the log level override to a particular account. The return value of the request should be a valid log level or null. In cases when a valid log level is returned, it will override the minLogLevel configuration property. If null is returned, the minLogLevel value will be used. The call to this endpoint will be made during the initialization phase. The endpoint should always return a 200 OK status code and use the success property to indicate failure.

Example success response:

{
	"success": true,
	"minLogLevel": "warn"
}

Example error response:

{
	"success": false,
	"minLogLevel": null
}

Changelog

v2.3.0

New features

  • To address long-running log requests caused by occasional slow remote log responses, this version introduces default timeouts for log requests. Timeout for Twilio event hooks is 2000 ms and is not configurable. Timeout for the remoteLogger helper is 500 ms and can be adjusted with an optional second parameter: remoteLogger("https://mylogger.url", 1000);

v2.2.0

New features

  • Added alternative logging functions that have a much shorter parameter list, and allow you to specify only those logging properties that you want, without the need to pass in null for parameters you are not interested in. New functions are available under cleLogger.v2 for backward compatibility reasons.
import { cleLogger } from "@prftesp/cle-logger";

// if you want to log just the message and the token, 
// you need to default parameters to null until you get to token
cleLogger.verbose("Log message", null, null, null, null, "my-token");

// with the new functions, you just provide an object with the properties you want
cleLogger.v2.verbose("Log message", { correlationToken: "my-token" });

v2.1.0

New features

  • Added Error To Object method to assist users in converting error object to plain objects.

v2.0.7

New features

  • If an instance of the twilioFlexManager is provided during initialization, it will be used to get the call sid during a call, and automatically include it in customProperties log property for all logs that happen during that call (including Flex Action logs).

v2.0.5

New features

  • If an instance of the twilioFlexManager is provided during initialization, it will be used to get the worker sid and automatically include it in customProperties log property.

Other updates

  • Updated documentation based on user feedback.

v2.0.4

Bug fixes

  • Fixed issue with logging to console in Twilio Functions. The consoleLogger will now output the log object as serialized json.

v2.0.0 [2019-12-20]

New features

  • All logging output is now configured using the logSinks property. The library provides two commonly used loggers - consoleLogger and a remoteLogger that accepts the log url as a parameter. Configuration
  • Logging level is now configured per log sink. For example, you might want to have verbose console logging, but only send information logs to a remote log output. Log sinks
  • Log functions have a new optional containsPII parameter, that can be used to flag a log as PII. Logging parameters
  • A new helper function tagPII is available to help mark PII in log messages. This works for custom log objects as well. Handling PII Data
  • PII handling - log sinks can be configured as PII safe, meaning only PII safe log sinks will receive logs flagged as PII. Log sinks

Breaking changes

  • customLogSink configuration renamed to logSinks
  • Removed disableRemoteLogging configuration. Now that all log output is configured with log sinks, you can conditionally remove a log sink if needed.
  • Removed logToConsole configuration. This is now configured as a log sink with a consoleLogger helper function.
  • Removed logUrl configuration. This is now configured as a log sink with a remoteLogger helper function.
  • Removed minLogLevel configuration. This is now configured per log sink.

Migration guide

import cleLogger from "@prftesp/cle-logger";

// v1.0.0 and older config
cleLogger.init({
	disableRemoteLogSinks: true, // no direct replacement
	logToConsole: true, // replaced by the "console logger" sink
	logUrl: "http://log.output/api", // replaced by the "remote logger" sink
	minLogLevel: cleLogger.logLevels.INFO, // this is now configured per log sink
	customLogSinks: [
		{
			name: "custom sink",
			log: logs => {
				/* your custom logging */
			},
		},
	],
});

// v2.0.0 config
cleLogger.init({
	logSinks: [
		{
			name: "custom sink",
			log: logs => {
				/* your custom logging */
			},
			logLevel: cleLogger.logLevels.INFO,
			// set to true to get feature parity with older version,
			// please consider your use case before setting
			piiSafe: true,
		},
		{
			name: "console logger",
			log: consoleLogger,
			logLevel: cleLogger.logLevels.INFO,
			// set to true to get feature parity with older version,
			// please consider your use case before setting
			piiSafe: true,
		},
		{
			name: "remote logger",
			log: remoteLogger("http://log.output/api"),
			logLevel: cleLogger.logLevels.INFO,
			// set to true to get feature parity with older version,
			// please consider your use case before setting
			piiSafe: true,
		},
	],
});

v1.0.0 [2019-09-12]

  • Initial release