npm package: @madooei/simple-logger
Description: A simple logger for TypeScript projects
Author: Ali Madooei
Latest version: 0.3.2

# Simple Logger

A 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

## Installation

```bash
npm install @madooei/simple-logger
```

## Usage

A lightweight, flexible logging system for CourseBook that supports namespace-based logging with different log levels.

### Basic Usage

```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");
```

### Setting Log Levels

```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");
```

### Namespace Patterns

- `component:` - Matches all loggers starting with 'component:'
- `component:submodule` - Matches exact namespace
- `/component:\d+/` - Matches using regex pattern
- `*` - Matches all namespaces

### Log Levels

1. `none` - Disables all logging for the namespace
2. `trace` - Verbose debugging information
3. `info` - 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

### Simple Log Level Design

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 active
- `info` 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 production
- `trace` 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.

### Enable/Disable Logging

```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");
```

### Object Logging

Objects are automatically pretty-printed:

```typescript
logger.info("Processing config", {
  server: "localhost",
  port: 3000,
});

// Output:
// [INFO] [myapp:component] Processing config {
//   "server": "localhost",
//   "port": 3000
// }
```

### Example Component Integration

```typescript
export class FileManager {
  private logger: Logger;

  constructor() {
    this.logger = LogManagerImpl.getInstance().getLogger("filemanager");
  }

  async readFile(path: string): Promise<Buffer> {
    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");
```

### Custom Log Functions

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
};
```

## Features

- **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

## Cloning the Repository

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
```

## Repository Structure

- `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.

## How to Use This Repo

- To work on a package, go to `packages/<package-name>` and follow its README.
- To try an example, go to `examples/<example-name>` and follow its README.
- To run the playground, go to `playground/<package-name>` and follow its README.
- For documentation, see the `docs` folder.

### Using a VSCode Multi-root Workspace

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...`.
3. Select the `simple-logger.code-workspace` 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"
  }
}
```

## Developing the Package

Change to the package directory and install dependencies:

```bash
cd packages/simple-logger
npm install
```

- Read the [Project Roadmap](../../docs/ROADMAP.md) for project goals, status, evolution, and development guidelines.
- Read the [Development Guide](DEVELOPMENT.md) for detailed information on the package architecture, build configuration, and implementation patterns.
- Follow the [Contributing Guide](../../docs/CONTRIBUTING.md) for contribution guidelines, coding standards, and best practices.

## Package Management

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](../../docs/guides/npm-package.md).