Observed since 20 Oct, 19:19 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Node.js logger with ECS format. Ships logs to OpenTelemetry Collector (OTEL → Elasticsearch → Kibana).
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+
npm install 2steps-jslogger dotenv
.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
logger.jsrequire('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.
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).
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.
.env.production)No 2steps-jslogger link; uses local dist/:
npm run dev:test:prod
Env file: .env.production (repo root)
npm test
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
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);
LOGGER_ENVIRONMENT | Default |
|---|---|
development | DEBUG and above |
production | INFO and above |
Override: LOGGER_LEVEL=DEBUG or LOGGER_LEVEL=INFO
| Method | Level |
|---|---|
logger.debug() | DEBUG |
logger.info() | INFO |
logger.warning() / .warn() | WARNING |
logger.error() | ERROR |
logger.critical() | CRITICAL |
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.*
.envOTEL_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
import { CustomLogger } from '2steps-jslogger';
export const logger = new CustomLogger();
| Problem | Solution |
|---|---|
| No logs in Kibana | Check endpoint and headers; await logger.flush() |
| DEBUG missing | LOGGER_ENVIRONMENT=development or LOGGER_LEVEL=DEBUG |
No message field | OTEL_ELASTIC_MAPPING_MODE=bodymap |
| Wrong index | Fix elasticsearch.index in OTEL_RESOURCE_ATTRIBUTES |
| Export errors silent | Call await logger.flush() — errors log to stderr |
This repo uses @twostepsai/bumpit for semver and changelog.
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
main.patch | minor | major.npm publish → git tag → GitHub Release.Required secret: NPM_TOKEN (npm automation token with publish access).
npm run version:bump # bumps package.json + CHANGELOG.md
npm run build
npm publish --access public
git push origin HEAD --follow-tags
MIT
Download counts and popularity will appear here as the collector receives them.
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 19:19 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:657e1d7d9c44281ea28b7c08fd3c6029c0e659a111f2538ab64d2f1d2478e0d7