Skip to content

MrHands/log-spark

Repository files navigation

log-spark adds abstract syntax tree (AST) transformer functions for logging to Typescript. These function calls are evaluated at compile-time and only included in the generated JavaScript when certain conditions are met.

log-spark uses ts-patch to add transformer plugins to Typescript compilation and ts-node to run the modified compiler.

Example

// Logging macros take a domain and a message string
$logTrace('Storage', 'Initializing...');

// Messages are string literals and can use variables
$logInfo('Game', `Ready player ${playerName}!`);

// The domain parameter can be an object on which `.toString()` is called
$logWarn(oven, `Set to ${oven.degrees} Celcius`);

// You can also use `this` as the domain
$logError(this, `${this._drinks} is too many drinks!`);

// Fatal log messages throw an error by default
$logFatal('Map', 'City not found');

// This macro will output only when compiling in a development configuration (default)
let environment = 'production';
$devOnly(() => {
	environment = 'development';
});

// And this macro works the other way around
let moneyOwed = 100000;
$prodOnly(() => {
	moneyOwed = 0;
});

When the above is compiled, the following JavaScript is produced:

console.log("[TRACE] (Storage) Initializing...");

console.log("(Game)", `Ready player ${playerName}!`);

console.warn("(" + oven.toString() + ")", `Set to ${oven.degrees} degrees Celcius`);

console.error("(" + this.toString() + ")", `${this._drinks} is too many drinks!`);

(() => {
	throw new Error("(Map) City not found");
})();

let environment = 'production';
(() => {
	environment = 'development';
})();

let moneyOwed = 100000;

Logging macros

Severity Config Value Macro Output Notes
Disabled -1 - - Used to disable options from the configuration settings
Trace 0 $logTrace() console.log() Output is prefixed with "[TRACE]" to differentiate it from Info messages
Info 1 $logInfo() console.log()
Warn 2 $logWarn() console.warn()
Error 3 $logError() console.error()
Fatal 4 $logFatal() throw new Error() (default) or console.error() Output is prefixed with "[FATAL]" to differentiate it from Error messages when not throwing an exception
Maximum 5 - - Used to disable options from the configuration settings

Building with Node.JS

Before you can use log-spark to transform your code, you must run npx ts-patch install, and modify your tsconfig.json:

{
	"$schema": "http://json.schemastore.org/tsconfig",
	"compilerOptions": {
		"plugins": [
			{
				"transform": "log-spark"
				// See additional settings in the table below
			}
		],
		"typeRoots": [
			// Required for adding the macros to the global namespace
			"./node_modules/log-spark/dist"
		],
		"include": [
			// Required for the compiler to recognize the macros as global functions
			"./node_modules/log-spark/dist"
		],
	},
	"ts-node": {
		// NOTE: You must run `npx ts-patch install` first!
		"compiler": "ts-patch/compiler"
	}
}

The object in the plugins array takes these additional properties:

Property Type Default Description
logSeverityMinimum number ELogSeverity.Trace Minimum log severity that will be translated to log statements.
logSeverityMaximum number ELogSeverity.Fatal Maximum log severity that will be translated to log statements. Setting this to ELogSeverity.Disabled will disable all logging macros.
throwExceptionMinimum number ELogSeverity.Fatal Minimum log severity that throws an exception.
throwExceptionMaximum number ELogSeverity.Fatal Maximum log severity that throws an exception. Setting this to ELogSeverity.Disabled will disable logging macros throwing exceptions.
isProduction boolean false Compiling for production (true) or development (false).

Building with Webpack

When using Webpack, you can read your tsconfig.json and modify the plugin settings before compiling your Typescript with ts-loader:

import { ELogSeverity } from 'log-spark/dist/log-severity';

import tsconfig from './tsconfig.json';

const { compilerOptions } = tsconfig;

export default (env: NodeJS.ProcessEnv) => {
	const nodeEnv =
		(env.production != null ? 'production' : null) ??
		env.NODE_ENV ??
		'development';

	const isProduction = nodeEnv === 'production';

	const tsCompilerOptions = Object.assign(compilerOptions, {
		plugins: [
			{
				transform: 'log-spark',
				logSeverityMinimum: isProduction
					? ELogSeverity.Info
					: ELogSeverity.Trace,
				isProduction,
			},
		],
	});

	return {
		module: {
			rules: [
				{
					test: /\.ts$/u,
					use: [
						{
							loader: require.resolve('ts-loader'),
							options: {
								compiler: 'ts-patch/compiler',
								compilerOptions: tsCompilerOptions,
							},
						},
					],
				},
			],
		},
	};
};

Releases

No releases published

Packages

No packages published