Writing every log.info content to a text file - node.js

I am using Pino and Pino pretty packages for displaying loggers. I would like to write all log.info contents (called from multiple js files in the same project) into a common text file
logger.ts
import pinoCaller from 'pino-caller'
import pino from 'pino'
const job_name="job123"
const pinoPretty = pino(
{
prettyPrint: {
messageFormat: `{"job_name":${job_name}, "message":{msg}}`,
},
})
export log=pinoCaller(pinoPretty)
Is there anyway I can write all log.info content from multiple files to a common text file.
lets say I have following files:
file1.ts
import {log} from 'logger'
const calculatesum = (a:any,b:any)=>{
log.info('**********')
log.info('sum begins')
const sum=a+b;
log.info('sum is '+sum)
log.info('sum ends')
}
file2.ts
import {log} from 'logger'
const calculateproduct = (a:any,b:any)=>{
log.info('product begins')
const product=a*b;
log.info('product is '+product)
log.info('product ends')
log.info('**********')
}
output of text file should look like below:
***************
sum begins
sum is x
sum ends
product begins
product is y
product ends
***************

If you're using Pino v7.x or later, you can make use of Pino transports.
const pinoPretty = pino({
prettyPrint: {
messageFormat: `{"job_name":${job_name}, "message":{msg}}`,
},
transport: {
targets: [
{ level: 'info', target: 'pino/file', options: { destination: '/path/to/store/logs', mkdir: true } },
{ target: 'pino-pretty', options: { destination: '/dev/null' }
]
}
})
Alternatively you can use pino-tee. An example of how to do it:
const pino = require('pino')
const pinoTee = pino.transport({
target: 'pino-tee',
options: {
filters: {
info: 'info.log'
}
}
})

Related

Node.js, logging with Pino: warning 'Possible EventEmitter memory leak detected'

To register any events in my project, I use pino. This is my 'Logger.js' file:
require('dotenv').config();
const pino = require('pino');
const logger = (
name,
level = (process.env.LOG_LEVEL || 'info'),
file = process.env.LOG_FILE || './log.log',
) => pino({
name,
level,
transport:
{
targets: [
{ // то screen
target: 'pino-pretty',
level,
options:
{
colorize: true,
translateTime: true,
sync: true,
},
},
{ // то file
target: 'pino-pretty',
level,
options:
{
colorize: false,
translateTime: true,
sync: true,
destination: file,
},
},
],
},
});
module.exports = logger;
Then I use this logger in any classes. For example, such as this class:
const logger = require('./Logger')('User');
class testClass1 {
constructor(a) {
this.a = a;
}
async increase(x) {
logger.debug(`x=${x}`);
this.a += x;
return this.a
}
}
module.exports = testClass1;
Classes can be used in project files, for example:
const testClass1 = require('./testClass1');
async function test() {
const test1 = new testClass1(2);
test1.increase(2);
}
test();
Everything works well. But if the number of used classes with logger is more than 10, I have a warning: Possible EventEmitter memory leak detected.
What can be done to avoid this?
Maybe there are some recommendations on how to keep a log?
Your logger.js file exports a function that creates a new logger.
I would try to create only one logger and if needed I would create child loggers for uses like the User.js file you have

How to sent log to Jaeger in NestJs?

In my nestjs project, I am using Winston as a logger. here is the example of my log.info:
logger.log(
'Error: test',
inout_data,
);
here is the logger:
var winston = require('winston');
const logger = winston.createLogger({
level: 'verbose',
format: winston.format.json(),
transports: [
new winston.transports.Console({
format: winston.format.json(),
}),
],
});
export default logger;
this is how I setup the Jaeger:
import { NodeSDK, tracing } from '#opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '#opentelemetry/auto-instrumentations-node';
import { JaegerExporter, ExporterConfig } from '#opentelemetry/exporter-jaeger';
import { BatchSpanProcessor } from '#opentelemetry/sdk-trace-base';
import { Resource } from '#opentelemetry/resources';
import { SemanticResourceAttributes } from '#opentelemetry/semantic-conventions';
interface Tag {
key: string;
value: TagValue;
}
declare type TagValue = string | number | boolean;
const options = {
tags: [], // optional
host: 'localhost',
port: 6832, // optional
maxPacketSize: 65000,
};
const exporter = new JaegerExporter(options);
export const sdk = new NodeSDK({
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'test,
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: '2',
}),
traceExporter: exporter,
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
I want to send the log to Jaeger, but I can not find a way to connect them. Am I missing anything here?

How to set env.development and env.production in Preact app

On react app, you can create .env.production and .env.development and enter different key and values like this.
REACT_APP_API_URL= "xyz"
to pick environment variables automatically based on commands used --> npm start or npm run build.
What is the equivalent process in preact?
It is my solution
env.js in the root of project:
import fs from 'fs';
import dotenv from 'dotenv';
function getAppEnvironment() {
const prefix = "PREACT";
return Object.keys(process.env)
.filter((key) => new RegExp(`^${prefix}_`, 'i').test(key))
.reduce((env, key) => {
env[key] = process.env[key];
return env;
}, {});
}
function resolveFile(file) {
const path = fs.realpathSync(process.cwd());
return `${path}/${file}`;
}
function getEnvFiles(production) {
const key = production ? 'production' : 'development';
return [
resolveFile(".env"),
resolveFile(".env.local"),
resolveFile(`.env.${key}`),
resolveFile(`.env.${key}.local`),
].filter(Boolean);
}
export function getEnvironment(production) {
const dotenvFiles = getEnvFiles(production);
dotenvFiles.forEach((dotenvFile) => {
if (fs.existsSync(dotenvFile)) {
dotenv.config({
path: dotenvFile,
override: true
})
}
});
return getAppEnvironment();
}
export default getEnvironment;
then create or modify your preact.config.js:
import getEnvironment from './env';
export default {
plugins: [],
webpack(config, env, helpers) {
config.plugins.push(
new helpers.webpack.DefinePlugin({
'process.env': JSON.stringify(getEnvironment(env.production))
}),
);
},
};

How to write a log file with winston on NodeJS

I'm building on my NodeJS API a custom logger using Winston.
I'm trying to log into a file but is it not working and cannot understand the issue.
I used some online resources to find out the solution but anything worked.
I used the transports.File() and added to my push but nothing happens.
My goal is to add the same logs I'm getting using the logger with the console into the file.
Same format and way of it.
My code
/* eslint-disable object-curly-newline */
/* eslint-disable arrow-parens */
/* eslint-disable comma-dangle */
// Logger
// This logger is used to show error/info messages about the status of the API
import winston from 'winston';
import moment from 'moment';
// import logSymbols from 'log-symbols';
import fs from 'fs-extra';
import { logger, NODE_ENV } from '../config';
const transports = [];
const dir = './logs';
// Creating the logs dir if does not exist
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
// For development in prod need to check for dev env
// in dev we want more info error tracking
// in prod essential info error message
if (NODE_ENV.env !== 'development') {
transports.push(
new winston.transports.Console({
format: winston.format.combine(
winston.format.cli(),
winston.format.splat()
),
}),
new winston.transports.File({
level: 'error',
filename: `${dir}/logs.log`,
})
);
} else {
transports.push(new winston.transports.Console());
}
// Parse meta keys
const parser = string => {
if (!string) {
return '';
}
if (typeof string === 'string') {
return string;
}
return Object.keys(string).length ? JSON.stringify(string, undefined, 2) : '';
};
// Logger instance
const LoggerInstance = winston.createLogger({
level: logger.level,
levels: winston.config.npm.levels,
format: winston.format.combine(
winston.format.colorize(),
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.splat(),
winston.format.printf(info => {
const { timestamp, level, message, meta } = info;
const ts = moment(timestamp)
.local()
.format('YYYY-MM-DD HH:MM:ss');
const metaMsg = meta ? `: ${parser(meta)}` : '';
// const symbol = level === 'error' ? logSymbols.error : logSymbols.success;
return `${ts} [${level}] ${parser(message)} ${metaMsg}`;
})
),
transports,
});
export default LoggerInstance;
While you set log level explicitly to 'error' in your winston transporter, you can not see any messages in debug level in the file. Please change your configuration so that your file. transporter accepts debug level messages too.
new winston.transports.File({
level: 'debug',
filename: `${dir}/logs.log`,
})

How do I output webpack as a string using Node

I am trying to use Webpack to bundle a bunch of files. I have the following in my node code...
webpack({
entry: "./src/test",
output: {
path: __dirname,
filename: "bundle.js"
},
}, function(err, stats){
console.log("I would like to output the created js here");
})
This works fine creating a file called bundle.js but I can't figure out how to output as a string instead.
Basically what you can do is to read the file, and then work with it as you want.
e.g.
import webpack from 'webpack';
const config = require('../webpack.config');
const compiler = webpack(config);
compiler.run((err, stats) => {
const data = stats.toJson();
const app = data.assetsByChunkName.app[0] //here you can get the file name
// if you don't have chunks then you should use data.assets;
const file = fs.readFileSync('path to your output ' + app); //read the file
//now you can work with the file as you want.
});
//Basic webpack.config.js
module.exports = {
devtool: 'source-map',
entry: {
app: 'Some path' // you can have different entries.
entrie2 : ''
.... more entries
},
output: {
path: 'Some path'
}
}
Hope this help.

Resources