Catalog npm
PACKAGE EXPLORERView in registry

2steps-jslogger

npm

Node.js logger with ECS format. Ships logs to OpenTelemetry Collector (OTEL → Elasticsearch → Kibana).

ecselasticelasticsearchloggerlogging
Versions collected3
Direct dependencies10From release 1.2.0
Last observed20 Oct, 19:19 UTC

README

Current package documentation

2steps-jslogger

npm package for Twosteps Node.js apps. Install in any project — logs go to OTEL Collector → Elasticsearch → Kibana.

your-app  →  OTEL Collector  →  Elasticsearch  →  Kibana

Node.js 18+


Quick start

1. Install

npm install 2steps-jslogger dotenv

2. Create .env (project root)

OTEL_EXPORTER_OTLP_ENDPOINT=https://otel.your-host.example.com
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <your-token>"
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

OTEL_SERVICE_NAME=service-my-app
LOGGER_PROJECT_NAME=Project-my-app
LOGGER_ENVIRONMENT=development

OTEL_RESOURCE_ATTRIBUTES="environment=mac,host.name=my-host,elasticsearch.index=my-app-logs-v1"
OTEL_ELASTIC_MAPPING_MODE=bodymap

3. Create logger.js

require('dotenv').config();
const { CustomLogger } = require('2steps-jslogger');

const logger = new CustomLogger();

module.exports = { logger };

Service, project, environment, and index come from .env — no options needed in code.

4. Use in your app

const { logger } = require('./logger');

logger.info('Server started');
logger.info('User action', { user_id: 789, action: 'login' });
logger.warning('Slow API', { latency_ms: 420 });
logger.debug('Debug info', { step: 1 });
logger.error('Failed', { error_code: 'ERR_001' }, new Error('details'));

await logger.flush();
await logger.close();

Note: logger.info() and similar calls do not throw if OTLP export fails. Errors appear when you call flush() or close(). Always call both before process exit (scripts, tests, graceful shutdown).


Testing

A. This repo — OTEL logs to Kibana (examples/test-logger.js)

Uses require('2steps-jslogger') like real apps. One-time setup:

cd nodejs-logger
cp examples/.env.example examples/.env
# Edit examples/.env — token, elasticsearch.index, service name

Each test run:

npm run build
npm link
npm link 2steps-jslogger
node examples/test-logger.js

Or one command (build + link + run):

npm run test:logger

Env file: examples/.env
Kibana: data view {your-index}* from elasticsearch.index (e.g. jslogger-otel-v4*), time field @timestamp, last 15 minutes.

B. This repo — production env file (.env.production)

No 2steps-jslogger link; uses local dist/:

npm run dev:test:prod

Env file: .env.production (repo root)

C. Unit tests (no logs sent)

npm test

D. Your app (after npm install 2steps-jslogger)

npm install 2steps-jslogger dotenv
cp node_modules/2steps-jslogger/examples/test-logger.js scripts/test-logger.js
cp node_modules/2steps-jslogger/examples/.env.example scripts/.env
# Edit scripts/.env
node scripts/test-logger.js

Express example

const express = require('express');
const { logger } = require('./logger');

const app = express();

app.get('/health', (req, res) => {
  logger.info('Health check');
  res.json({ ok: true });
});

const server = app.listen(3000, () => logger.info('Listening on 3000'));

async function shutdown() {
  await logger.flush();
  await logger.close();
  server.close(() => process.exit(0));
}

process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);

Log levels

LOGGER_ENVIRONMENTDefault
developmentDEBUG and above
productionINFO and above

Override: LOGGER_LEVEL=DEBUG or LOGGER_LEVEL=INFO

MethodLevel
logger.debug()DEBUG
logger.info()INFO
logger.warning() / .warn()WARNING
logger.error()ERROR
logger.critical()CRITICAL

Extra fields

logger.info('Request', {
  request_id: 'abc',
  method: 'POST',
  endpoint: '/api/orders',
  duration_ms: 120,
});

logger.info('Login', {
  user_id: '123',
  email: 'user@example.com',
});

In Kibana: custom_fields.*, auth.*, request_context.*


Example .env

OTEL_EXPORTER_OTLP_ENDPOINT=https://otel.your-host.example.com
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <token>"
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

OTEL_SERVICE_NAME=service-my-app
LOGGER_PROJECT_NAME=Project-my-app
LOGGER_ENVIRONMENT=development

OTEL_RESOURCE_ATTRIBUTES="environment=mac,host.name=my-host,elasticsearch.index=my-app-logs-v1"
OTEL_ELASTIC_MAPPING_MODE=bodymap

TypeScript

import { CustomLogger } from '2steps-jslogger';

export const logger = new CustomLogger();

Troubleshooting

ProblemSolution
No logs in KibanaCheck endpoint and headers; await logger.flush()
DEBUG missingLOGGER_ENVIRONMENT=development or LOGGER_LEVEL=DEBUG
No message fieldOTEL_ELASTIC_MAPPING_MODE=bodymap
Wrong indexFix elasticsearch.index in OTEL_RESOURCE_ATTRIBUTES
Export errors silentCall await logger.flush() — errors log to stderr

Versioning & release (bumpit)

This repo uses @twostepsai/bumpit for semver and changelog.

Contributor workflow (before merge)

After your code changes, record release intent:

npx @twostepsai/bumpit add

Or non-interactive (CI / scripts):

npx @twostepsai/bumpit add --level patch --message "Fix OTLP header parsing"

Commit the generated .bumpit/*.md change file with your PR.

Check pending changes:

npm run version:status

Maintainer — publish via GitHub Actions

  1. Merge all PRs to main.
  2. GitHub → Actions → Release → Run workflow.
  3. Choose bump type: patch | minor | major.
  4. Workflow runs: test → bumpit bump → build → npm publish → git tag → GitHub Release.

Required secret: NPM_TOKEN (npm automation token with publish access).

Maintainer — publish locally (optional)

npm run version:bump    # bumps package.json + CHANGELOG.md
npm run build
npm publish --access public
git push origin HEAD --follow-tags

License

MIT

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 3

Collected releases
VersionPublishedDirect dependenciesOpen version
1.2.0Registry latest12 Jun 202610
1.1.012 Jun 202610
1.0.326 Mar 20264

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 19:19 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:657e1d7d9c44281ea28b7c08fd3c6029c0e659a111f2538ab64d2f1d2478e0d7