npm package: @huncyrus/simple-serverless-logger
Description: Simple logger for serverless and tiny projects without large overhead but possibility to use adapters and other logger packages.
Author: Györk Bakonyi
Latest version: 1.0.2

# Simple Serverless Logger

<br>

[![GitHub release](https://img.shields.io/github/v/release/DrakStadenConsulting/simple-serverless-logger?sort=semver)](…/releases)
[![CI](https://github.com/DrakStadenConsulting/simple-serverless-logger/actions/workflows/ci.yml/badge.svg)](…/actions/workflows/ci.yml)

<br>

## Goal, reason

A simple `TypeScript` based logger that is easy to use with multiple serverless project but without overhead and features that rarely or never used.  
Inspired by the PHP's PSR-3 LoggerInterface.  

<br>

## Features

- Simple Logger Interface (easy to implement or extend)
- TypeScript support
- JavaScript support
- Adapters to use with `Pino`, `Winston` or anything else
- Logging level

### Explaining logging level

<br>

### API & methods

```JavaScript
  setLevel(level: "silent"|"error"|"warn"|"info"|"log"|"debug"|"verbose")
  getLevel()
  setVerbose(boolean) → when true, uses util.inspect (depth ∞, showHidden)
  isVerbose()
  log/info/warn/error/debug/verbose(message?: unknown, ...context: unknown[])
```

<br>

## Usage

### Requirements

 - NodeJS `20`+
 - Npm `6`+

<br>

### How to install

```bash
  npm i @huncyrus/simple-serverless-logger
```

#### ESM

```JavaScript
  import { ConsoleLogger } from '@huncyrus/simple-serverless-logger';
  const myGlobalContext = [{ some: 'test' }];
  const logger = new ConsoleLogger({ useTimestamps: false }, myGlobalContext);
  logger.info("hello from JS", { pid: process.pid });
```

> Note: The `global context` is optional.

#### CommonJS (require)

```JavaScript
  const { ConsoleLogger } = require("@huncyrus/simple-serverless-logger");
  const myGlobalContext = [{ some: 'test' }];
  const logger = new ConsoleLogger(myGlobalContext).setLevel("debug").setVerbose(false);
  logger.debug("works in CJS too", [1, 2, 3]);
```

<br>

### Usage example

Please visit the `Examples` directory.

```TypeScript
  import { ConsoleLogger } from "@huncyrus/simple-serverless-logger";

  const logger = new ConsoleLogger()
    .setLevel("verbose")
    .setVerbose(true);

  logger.log("message");
  logger.info("info level of log");
  logger.verbose("some verbose stuff");

  const someArray = [1, { nested: { x: 1 } }];
  logger.debug("text example", "context1", 2323, someArray, [], {}, null);

```

#### Example output

```bash
  [2025-10-13T08:26:39.202Z] INFO  Hello
```

#### Logger options

```TypeScript
  export interface ConsoleLoggerOptions {
    level?: LogLevel;
    useTimestamps?: boolean;
    console?: ConsoleLike;
    writeMethodInBracket?: boolean;
  }
```

##### Level

The log `level` indicates which level should be written by the logger. The levels are based on the RFC5424 but simplified.  
Available levels:  

- Verbose (via node util in the `ConsoleLogger`)
- Debug
- Info
- Log
- Warn
- Error

The error levels follows both the RFC and the NPM error level values:  

| Level name | Value |
|:----------:|:-----:|
| error | 0 |
| warn | 1 |
| info | 2 |
| log | 3 |
| debug | 4 |
| verbose | 5 |

##### Use Timestamp

The `useTimestamp` option (boolean) shall ensure the log has a timestamp (local timezone) added to the log line. Example: 

```bash
  [2025-10-13T08:26:39.202Z] [INFO]  Hello
```

This option is `false` by default (The original goal was to log into CloudWatch or any Serverless "built-in" logging solution that usually have ingestion timestamp) but for local files and special log stream/queues the timestamp ensures the log time is preserved.


##### Console

Global console, to support adapters and custom implementations.

##### Write Method in Brackets

Old, server log style, simple boolean, `false` by default. If it is enabled, then the log level shall use a bracket:  

```bash
  [2025-10-13T08:26:39.202Z] [INFO]  Hello
```

<br>

#### Note on verbose

The `ConsoleLogger` uses the `Node` util package `inspect` features to be able to fully log long and nested objects.

<br>

### Testing

```bash
  npm run build
  npm run test
  npm run test:run
```

Test coverate via Vitest:  

```bash
  npm run test:coverage
```

#### Tests via docker

```bash
  docker build -t simple-serverless-logger-tests .
  # or rebuild
  # docker build --no-cache -t simple-serverless-logger-tests .
```

Then run

```bash
  docker run --rm simple-serverless-logger-tests
```

Expected output: 

```bash
$ docker run --rm simple-serverless-logger-tests

> @huncyrus/simple-serverless-logger@1.0.1 build
> rimraf dist && npx tsc -p tsconfig.json && npx tsc -p tsconfig.cjs.json && node -e "require('node:fs').cpSync('cjs.package.json','dist/cjs/package.json')"


> @huncyrus/simple-serverless-logger@1.0.1 test:run
> npx vitest run


 RUN  v3.2.4 /usr/src/app

 ✓ tests/unit/emptyAdapter.spec.ts (6 tests) 29ms
 ✓ tests/e2e/consoleLogger.e2e.spec.ts (2 tests) 47ms
 ✓ tests/unit/consoleLogger.spec.ts (8 tests) 38ms
 ✓ tests/integration/pinoAdapter.spec.ts (1 test) 10ms
 ✓ tests/integration/winstonAdapter.spec.ts (1 test) 16ms
 ✓ tests/unit/interfaceContract.spec.ts (1 test) 11ms

 Test Files  6 passed (6)
      Tests  19 passed (19)
   Start at  17:28:35
   Duration  2.54s (transform 973ms, setup 0ms, collect 1.67s, tests 152ms, environment 7ms, prepare 2.46s)
```

## Roadmap, future features

- [ ] More examples
- [ ] Cleanup of the Readme file
- [ ] Document properly the API/callables
- [x] Document the log levels
- [x] Document the logger options
- [ ] Stream adapter
- [ ] Sentry adapter
- [ ] DataDog adapter
- [ ] Redis adapter
- [ ] ElasticMQ adapter
- [ ] AWS CloudWatch adapter
- [x] Add global context object to the costructor
- [x] Add docker to run tests

<br>

## Author

Author: [Györk Bakonyi](https://github.com/huncyrus)

## Contribution

[Contributing rules](CONTRIBUTING.md)

## References

- [Pino](https://github.com/pinojs/pino)
- [Winston](https://www.npmjs.com/package/winston)
- [PHP PSR-3 LoggerInterface](https://www.php-fig.org/psr/psr-3/)
- [Vitest](https://vitest.dev)