📓Log-Right is a light-weight (but expansive) javascript logging library with a focus on developer experience and simplifying the process of error handling, reporting, and troubleshooting.
Features
- Provides a logger utility to extend build-in logging functionality
- Includes a Result class that can be used to manage errors (or any other type of result) that are returned from any kind of function or process
- Simplifies global application logging by allowing users to specify how and when logs should be written/handled
- Provides various utility methods to handle Results return from functions/process and log information and performance metrics
- Allow user to specify custom event types which will then drive how event handler logic and logging is executed
- Supports formatting of log event messages using custom string templates provided by the user
Some Benefits of Using 📓Log-Right
- Simple: The APIs are extremely easy to use and include detailed documentation for all of the functionality
- Very Modular: Package modules are separated by functionality/utility. Works with webpack, Browserify, or Rollup and also supports tree-shaking.
- TypeScript Support: Log-Right was created using TypeScript, so all the types associated with the package are fully supported and up to date
- And many more
documentation for more info, guides, API and more!
Visit ourInstallation
Installing and using Log-Right is very simple. Start by installing the log-right
dependency:
$ npm i log-right --save
# or
$ yarn add log-right
Once it is installed, you can import and use the log-right
helper utilities and classes:
import { ConfigurationManager, validate, write, Result } from "log-right";
Configuration
Once the package has been installed, you can use the ConfigurationManager to specify how you want your application's logging to behave.
import { ConfigurationManager, LogEvent } from "log-right";
const writeLog = (logEvent: LogEvent) => {
console.log("Event Type: " + logEvent.eventType);
console.log("Event Message: " + logEvent.message);
};
ConfigurationManager.setConfig({
writeLogEvent: writeLog,
defaultEventSource: "User's Custom Source",
defaultResultName: "User's Result Name",
defaultErrorResultMessage:
"This is a custom default error message specified by the user",
});
The full list of configuration parameters can be found in our documentation.
📓 Logging 📓
Log-Right provides the user with "write" logging utility methods that will use the configuration parameters previously provided by the user to write logs.
import {
writeDebug,
writeInfo,
writeWarning,
writeError,
write,
} from "log-right";
writeDebug("This is an debug message.");
writeInfo("This is an info message.");
writeWarning("This is an warn message.");
writeError("This is an error message.");
// The below function call specifies a user-defined event type
write("This is a custom event message.", "CUSTOM_EVENT_TYPE");
This event logged in the write method above will use custom event handler and logging logic specified by the user for that specific event type. Prior to the code snippet above, it is assumed the user registered the "CUSTOM_EVENT_TYPE" event type in the ConfigurationManager.
NOTE: All five of the "write" methods above will call the writeLogEvent functions defined in the Configuration that were passed to the ConfigurationManager
More information on the "write" logging utility methods shown above can be found in our documentation.
Error (and Any Other Type of Result) Handling
The Result class provided by Log-Right can be used in any function or process to indicate success, failure, or something in between.
For quick usage, the Result class includes some static methods that can be used to generate a new Result object with the specified validationType
.
import { Result, validate, write } from "log-right";
const someSuccessfulFunction = () => {
const returnValues = {
value1: "foo",
value2: "bar",
};
return Result.success(returnValues);
import { Result, validate, write } from "log-right";
const someSuccessfulFunction = () => {
const returnValues = {
value1: "foo",
value2: "bar",
};
return Result.success(returnValues);
};
const someFailureFunction = () => {
return Result.error({ message: "The reason for the failure" });
};
const successResult: Result = someSuccessfulFunction();
if (successResult.isFailure) {
// This code will not be hit
}
// The validate helper function uses the same underlying logic as the Result.isFailure property accessor
if (!validate(successResult)) {
// This code will not be hit
}
// The values property will contain the values passed into Result.success function
console.log(success.values); -> { value1: "foo", value2: "bar" }
const failure = someFailureFunction();
if (failure.isFailure) {
// This code will be hit
}
// The "write" helper functions mentioned in the previous section can also
// accept a Result object as an input parameter to log
write(failure);
NOTE: In Log-Right, event types and validation types are NOT the same. Event types are free-format strings that can be used to look up details on how the log event object should be handled/logged. There are a variable amount of possible event types, as the user is able to register as many or as few as they like. Validation types are defined through code (as a result, they have a fixed number of types) and are used to determine which path in code should be taken when an event occurs. The user-defined event types added in the eventTypeRegistry will have a validation type associated with them. While there could be some overlap in the event and validation type values, they are not directly related to each other.
Custom User Defined Events
Log-Right allows users to specify custom event types, handlers, and logging.
When providing a configuration object to the ConfigurationManager, user's can specify the eventTypeRegistry parameter. This parameter allows users to register custom event types with Log-Right that can be handled at a later time.
import {
ConfigurationManager,
LogEvent,
ResultValidationTypes,
} from "log-right";
const writeCustomEventLog = (logEvent: LogEvent) => {
console.log(logEvent.message);
};
ConfigurationManager.setConfig({
eventTypeRegistry: {
CUSTOM_EVENT_TYPE: {
// Will be called to log this custom event type
writeLogEvent: writeCustomEventLog,
// Tell the validate function how to handle this event
validationType: ResultValidationTypes.ERROR,
// The specified object will be thrown if this event occurs (if nothing is specified
// in the throwOnEvent field, nothing will be thrown)
throwOnEvent: {
message: "This object was thrown because we specified it",
},
// The template used to format this event type's logs
formatTemplate: "CUSTOM_EVENT_TYPE: <!--MESSAGE--!>",
},
},
});
After registering the custom event type with the ConfigurationManager, you can use it by returning Result objects with the type specified in the eventType
field.
import { Result, validate } from "log-right";
const someCustomEventFunction = () => {
return new Result({ eventType: "CUSTOM_EVENT_TYPE" });
};
const result = someCustomEventFunction();
if (!validate(result)) {
// This code will be hit if the validationType on the eventTypeRegistry is set to "ERROR"
}
Please see the Result section in our documentation for more details on this functionality.
Log Message Format / Formatting Templates
Log-Right allows users to define their own custom templates to be used in formatting the data associated with an event into something that is either more human-readable or can be processed by a service. These templates can be applied to all types of logs on a global-level, or specific to a certain event type that is registered with the ConfigurationManager.
The format templates are made up of template fields that are passed into the formatTemplateToken function to generate template field tokens. Creating the template field tokens in the formatTemplateToken function is a very straight forward process - essentially just pre-pending the templateTokenStart and appending the templateTokenStop strings from the Configuration data around the field name. The below list of fields are available to include in a formatting template:
Field Name | Template Field |
---|---|
Event Type | EVENT_TYPE |
Validation Type | VALIDATION_TYPE |
Event ID | ID |
Event Name | NAME |
Event Source | SOURCE |
Context | CONTEXT |
Event Message | MESSAGE |
Event Message Details | DETAILS |
Stack Trace | STACK |
User ID | USER_ID |
Timestamp (formatted) | TIME_STAMP |
import { formatTemplateToken } from "log-right";
const templateToken = formatTemplateToken("EVENT_TYPE", "<-", "->");
console.log(templateToken); -> "<-EVENT_TYPE->"
After the formatTemplateToken is used to create the template tokens, a template string can be generated and saved to the ConfigurationManager.
import { formatTemplateToken, ConfigurationManager, formatLogMessage } from "log-right";
const sourceTemplateToken = "<-SOURCE->";
const userIdTemplateToken = "<-USER_ID->";
const messageTemplateToken = "<-MESSAGE->";
const detailsTemplateToken = "<-DETAILS->";
const timestampTemplateToken = "<-TIME_STAMP->";
const result = ConfigurationManager.setConfigItem("defaultFormatTemplate", `*** Sample Log Template Header ***
Event Source: ${defaultFormatTemplate}
User ID: ${userIdTemplateToken}
Timestamp (Est): ${timestampTemplateToken}
${messageTemplateToken}
------------------------
${detailsTemplateToken}
** A custom event log footer **
`);
if (result.isSuccessful) {
// Template was successfully saved to configuration
}
.
.
.
const result = formatLogMessage(logEventObj);
if (result.isSuccessful) {
console.log(result.values); -> `*** Sample Log Template Header ***
Event Source: TRADE_INPUT_SYSTEM
User ID: JohnsonR (Richard Johnson)
Timestamp (Est): 12/15/2022 11:23:57 AM
An error occurred while processing a transaction
------------------------
An unexpected value was provided for the transaction date and amount values. This transaction will require multiple levels of approval.
** A custom event log footer **
`
}
More details on creating templates and formatting logs can be found in our documentation.