A simple logger for TypeScript projects
npm install @madooei/simple-loggerA lightweight, flexible logging system for CourseBook that supports namespace-based logging with different log levels.
Features:
- Written in TypeScript
- Builds to both modern ES modules and CommonJS formats
- Provides TypeScript type definitions
- ESLint for code linting
- Prettier for code formatting
- Vitest for testing
- Tsup for building
- Minimal dependencies
``bash`
npm install @madooei/simple-logger
A lightweight, flexible logging system for CourseBook that supports namespace-based logging with different log levels.
`typescript
import { LogManagerImpl, type Logger } from "@madooei/simple-logger";
// Get the logger instance
const logManager = LogManagerImpl.getInstance();
// Create a logger for your component
const logger: Logger = logManager.getLogger("myapp:component");
// Log at different levels
logger.trace("Detailed debugging");
logger.info("General information");
`
`typescript
// Set level for specific namespace
logManager.setLogLevel("myapp:component", "info");
// Set level for all components in 'myapp'
logManager.setLogLevel("myapp:*", "info");
// Use regex pattern
logManager.setLogLevel(/test:\d+/, "trace");
// Set default level for everything
logManager.setLogLevel("*", "info");
// Disable logging for specific namespace
logManager.setLogLevel("myapp:debug", "none");
`
- component: - Matches all loggers starting with 'component:'component:submodule
- - Matches exact namespace/component:\d+/
- - Matches using regex pattern*
- - Matches all namespaces
1. none - Disables all logging for the namespacetrace
2. - Verbose debugging informationinfo
3. - Informational messages and errors
When you set a log level, all levels of equal or higher severity will be logged:
- Setting level to 'none' disables all logging for that namespace
- Setting level to 'trace' shows trace and info logs
- Setting level to 'info' shows only info logs
The logging system uses a minimal three-level hierarchy: none, trace, and info.
- none allows you to completely disable logging for specific namespaces while keeping others activeinfo
- is the default level for regular logging, covering everything you would normally output with console.log, including warnings and errors that should be visible in productiontrace
- is solely for debugging and is typically enabled only for specific namespaces during development
This simple hierarchy keeps configuration straightforward while providing the flexibility to selectively disable noisy components or enable detailed debugging where needed.
`typescript
// Disable all logging globally
logManager.disable();
// Re-enable logging globally
logManager.enable();
// Disable logging for specific namespaces using "none" level
logManager.setLogLevel("myapp:debug", "none");
logManager.setLogLevel("noisy:*", "none");
// Re-enable by setting to a different level
logManager.setLogLevel("myapp:debug", "info");
`
Objects are automatically pretty-printed:
`typescript
logger.info("Processing config", {
server: "localhost",
port: 3000,
});
// Output:
// [INFO] [myapp:component] Processing config {
// "server": "localhost",
// "port": 3000
// }
`
`typescript
export class FileManager {
private logger: Logger;
constructor() {
this.logger = LogManagerImpl.getInstance().getLogger("filemanager");
}
async readFile(path: string): Promise
this.logger.trace("Reading file:", path);
try {
const content = await readFile(path);
this.logger.info("Successfully read file:", path);
return content;
} catch (error) {
this.logger.info("Failed to read file:", path, error);
throw error;
}
}
}
// Configure logging levels
const logManager = LogManagerImpl.getInstance();
// Enable trace logging for file operations during development
logManager.setLogLevel("filemanager", "trace");
// Disable logging for a noisy third-party component
logManager.setLogLevel("external:verbose-lib", "none");
// Keep default info level for everything else
logManager.setLogLevel("*", "info");
`
You can customize how logs are output by providing a custom log function:
`typescript
import { LogManagerImpl, type LogFunction } from "@madooei/simple-logger";
const logManager = LogManagerImpl.getInstance();
// Custom log function that formats differently
const customLogFunction: LogFunction = (level, namespace, ...args) => {
const timestamp = new Date().toISOString();
const message = ${timestamp} [${level.toUpperCase()}] ${namespace}: ${args.join(" ")};
console.log(message);
};
// Set the custom log function
logManager.setLogFunction(customLogFunction);
// Now all loggers will use your custom function
const logger = logManager.getLogger("myapp");
logger.info("This will use custom formatting");
// Reset to default console.log behavior
logManager.resetLogFunction();
`
#### VSCode Extension Example
`typescript
import * as vscode from "vscode";
import { LogManagerImpl, type LogFunction } from "@madooei/simple-logger";
const vscodeLogFunction: LogFunction = (level, namespace, ...args) => {
const message = [${level.toUpperCase()}] [${namespace}] ${args.join(" ")};
vscode.window.showInformationMessage(message);
};
const logManager = LogManagerImpl.getInstance();
logManager.setLogFunction(vscodeLogFunction);
// Now logs appear as VSCode information messages
const logger = logManager.getLogger("extension:main");
logger.info("Extension activated!");
`
#### Custom Formatting Examples
`typescript
// Colorized console output
const colorLogFunction: LogFunction = (level, namespace, ...args) => {
const colors = { trace: "\x1b[36m", info: "\x1b[32m" };
const reset = "\x1b[0m";
const color = colors[level] || "";
console.log(
${color}[${level.toUpperCase()}]${reset} ${namespace}:,
...args,
);
};
// JSON structured logging
const jsonLogFunction: LogFunction = (level, namespace, ...args) => {
const logEntry = {
timestamp: new Date().toISOString(),
level: level.toUpperCase(),
namespace,
message: args.join(" "),
};
console.log(JSON.stringify(logEntry));
};
// Multiple outputs
const multiOutputLogFunction: LogFunction = (level, namespace, ...args) => {
const message = [${level.toUpperCase()}] [${namespace}] ${args.join(" ")};
console.log(message); // Console
sendToLogServer(message); // External logging
writeToFile(message); // File logging
};
`
- Namespace-based Logging: Organize logs by component and operation
- Pattern Matching: Control log levels using string prefixes or regex patterns
- Log Level Hierarchy: none → trace → info
- Object Serialization: Automatically pretty-print objects
- Global Enable/Disable: Quickly toggle all logging
- Singleton Pattern: Centralized logging control
- Custom Log Functions: Replace default console.log with custom output handlers
- Flexible Output: Support for VSCode messages, file logging, external services, and more
To make your workflow more organized, it's a good idea to clone this repository into a directory named simple-logging-workspace. This helps differentiate the workspace from the simple-logger located in the packages directory.
`bash
git clone https://github.com/madooei/simple-logger simple-logging-workspace
cd simple-logging-workspace
`
- packages — Contains the primary package(s) for this repository (e.g., simple-logger). Each package is self-contained and can be copied out and used independently.examples
- — Contains examples of how to use the packages. Each example is a minimal, standalone project.playgrounds
- — Contains demos of the dependencies of the primary package(s). Each playground is a minimal, standalone project.docs
- — Contains various documentation for users and developers..github
- — Contains GitHub-specific files, such as workflows and issue templates.
- To work on a package, go to packages/ and follow its README.examples/
- To try an example, go to and follow its README.playground/
- To run the playground, go to and follow its README.docs
- For documentation, see the folder.
With Visual Studio Code, you can enhance your development experience by using a multi-root workspace to access packages, examples, and playgrounds simultaneously. This approach is more efficient than opening the root directory, or each package or example separately.
To set up a multi-root workspace:
1. Open Visual Studio Code.
2. Navigate to File > Open Workspace from File....simple-logger.code-workspace
3. Select the file located at the root of the repository. This action will open all specified folders in one workspace.
The simple-logger.code-workspace file can be customized to include different folders or settings. Here's a typical configuration:
`json`
{
"folders": [
{
"path": "packages/simple-logger"
},
{
"path": "examples/simple"
},
{
"path": "playgrounds/empty"
}
],
"settings": {
// Add any workspace-specific settings here, for example:
"git.openRepositoryInParentFolders": "always"
}
}
Change to the package directory and install dependencies:
`bash`
cd packages/simple-logger
npm install
- Read the Project Roadmap for project goals, status, evolution, and development guidelines.
- Read the Development Guide for detailed information on the package architecture, build configuration, and implementation patterns.
- Follow the Contributing Guide for contribution guidelines, coding standards, and best practices.
When you are ready to publish your package:
`bash``
npm run release
This single command will:
- Validate your code with the full validation pipeline
- Analyze commits to determine version bump
- Update package.json version and changelog
- Build the package
- Create and push git tag
- Create GitHub release
- Publish to NPM
> [!TIP]
> For detailed information about package publishing, versioning, and local development workflows, see the NPM Package Management Guide.