winston: Attempt to write logs with no transports - using default logger - javascript

I followed a tutorial to set up winston (2.x) default logger in my express app. When updating to the current version of winston (3.0.0) I have a problem with adding the transports. I have followed the latest docs but still I get the notice in console and no log files are created at all:
[winston] Attempt to write logs with no transports
logging.js
const winston = require('winston');
module.exports = function () {
const files = new winston.transports.File({ filename: 'logfile.log' });
const myconsole = new winston.transports.Console();
winston.add(myconsole);
winston.add(files);
}
index.js
const winston = require('winston');
...
require('./logging');
winston.info("Give some info");
[winston] Attempt to write logs with no transports
{"message":"Give some info","level":"info"}
What am I doing wrong?

In winston 3 you need to create a logger object, then add transports to it.
Winston 3 has many examples, but to adapt from the readme, do something like this:
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'logfile.log' })
]
});
logger.info('it works!!');

If you want to use the default logger in winston v3 then you simply have to add this piece of code in your main file
const winston = require('winston')
winston.add(new winston.transports.File({ filename: 'logfile.log' }))

I also had a similar issue. If I recall correctly, I had to call the requirement as a function in my index.js.
require('./logging')();

Related

createDeployment() with Kubernetes JavaScript client

I am trying to create a deployment or replicaSet with the Kubernetes Javascript client. The Kubernetes javascript client documentation is virtually non-existent.
Is there any way to achieve this?
Assuming that by:
createDeployment()
you are referring to: createNamespacedDeployment()
You can use below code snippet to create a Deployment using Javascript client library:
const k8s = require('#kubernetes/client-node');
const kc = new k8s.KubeConfig();
kc.loadFromDefault();
const k8sApi = kc.makeApiClient(k8s.AppsV1Api); // <-- notice the AppsV1Api
// Definition of the deployment
var amazingDeployment = {
metadata: {
name: 'nginx-deployment'
},
spec: {
selector: {
matchLabels: {
app: 'nginx'
}
},
replicas: 3,
template: {
metadata: {
labels: {
app: 'nginx'
}
},
spec: {
containers: [
{
name: 'nginx',
image: 'nginx'
} ]
}
}
}
};
// Sending the request to the API
k8sApi.createNamespacedDeployment('default', amazingDeployment).then(
(response) => {
console.log('Yay! \nYou spawned: ' + amazingDeployment.metadata.name);
},
(err) => {
console.log('Oh no. Something went wrong :(');
// console.log(err) <-- Get the full output!
}
);
Disclaimer!
This code assumes that you have your ~/.kube/config already configured!
Running this code for the first time with:
$ node deploy.js
should output:
Yay!
You spawned: nginx-deployment
You can check if the Deployment exists by:
$ kubectl get deployment nginx-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 6m57s
Running this code once again will output (deployment already exists!):
Oh no. Something went wrong :(
Additional resources:
Github.com: Kubernetes-client: Javascript
Be careful when you try to deploy a different kinds of resources such as deployment or service.
You need to correctly specify the API version.
const k8sApi = kc.makeApiClient(k8s.AppsV1Api) or (k8s.CoreV1Api) for namespace and etc.
First, you create a kube config object and then create the associated API type. I.e,
import k8s from '#kubernetes/client-node';
const kubeConfig = new k8s.KubeConfig();
kubeConfig.loadFromCluster(); // Or whatever method you choose
const api = kubeConfig.makeApiClient(k8s.CoreV1Api); // Or whatever API
// you'd like to
// use.
const namespace = 'default';
const manifest = new k8s.V1ConfigMap();
// ... additional manifest setup code...
await api.createNamespacedConfigMap(namespace, manifest);
This is the gist of it. If you'd like, I recently created a library with the intention of simplifying interactions with the kubernetes javascript api and it can be found here:
https://github.com/ThinkDeepTech/k8s
If it doesn't help you directly, perhaps it can serve as an example of how to interact with the API. I hope that helps!
Also, make sure the application executing this code has the necessary permissions (i.e, the K8s Role, RoleBinding and ServiceAccount configs) necessary to perform the actions you're attempting. Otherwise, it'll error out.

TypeError: require(...) is not a function Express.js

I need help. I have this error when I run npm start:
/Users/telecreative/Documents/cafemates micro-services/cafemates-users-services/database/index.js:8
const pgp = require("pg-promise")(options) ^
On another computer, script running, with node version and npm version was same:
TypeError: require(...) is not a function
const express = require("express")
const app = express()
require('dotenv').config({path:__dirname+'/./../../.env'})
const promise = require("bluebird")
const options = {
promiseLib: promise
}
const pgp = require("pg-promise")(options)
const config = {
user: process.env.DATABASE_USER,
host: process.env.DATABASE_HOST,
database: process.env.DATABASE,
password: process.env.DATABASE_PASSWORD,
port: process.env.DATABASE_PORT
}
const db = pgp(config);
module.exports = db
Try running npm install --save pg-promise bluebird from the project root and then reload the app.
This: require("pg-promise") simple does not return function.
Therefore when you use require("pg-promise")(...) it tries to use it as function and then fails, because it is not a function.
You can try console.log(require("pg-promise"))) to see whats inside.
Solved
wrong me, I copy the json package., from the existing one, the best way should be to install one by one.

Is it bad practice to use process.env.SOMETHING in a npm package?

Specifically, I have created a wrapper for winston, so only a few functions are available and it can always be swapped out for some other library.
In this wrapper I am creating a new logger with:
const logger = winston.createLogger({
level: process.env.MIN_LOG_LEVEL || 'debug', // Minimum logging level
transports: [new winston.transports.Console()],
format: winston.format.combine(winston.format.timestamp(), customFormat),
});
Is it a bad practice to use process.env.MIN_LOG_LEVEL here? Should it only be used in the "actual app" ? And if so, how would you solve this?

How do I get Winston to work with Webpack?

I have an electron application which is using node.js. I would like to use Winston for logging in the application. I've added winston to my package.json file, but when I run the build command for webpack I'm getting some warnings from the colors.js dependency in winston.
'...the request of a dependency is an expression...'
It then references winston and colors.js. Ignoring the warnings doesn't work, as the electron application gets an exception trying to load some files from winston.
I did some digging on SO and the github site and they say that colors.js has some dynamic require statements that webpack is having issues with. I've also seen that other sample projects seem to have winston up and running without any issues in their projects. Does anyone know how to correctly include the winston logging package with webpack in an electron app?
There are two sides to this issue:
1) winston directly or indirectly depends on color.js, so that dependency automatically gets included, once winston is there. In some older versions of it, it included a dynamic require statement, which leads to this:
2) a dependency has a dynamic require statement that Webpack cannot handle; you can either configure webpack so it can ignore this specific case, or also upgrade winston to a newer version, so color.js will be picked in a variant without that dynamic require (see https://github.com/winstonjs/winston/issues/984).
To tell Webpack to get along with the dynamic require, you need to tell Webpack that Winston is an external library.
Here's an example from my webpack.config.js:
externals: {
'electron': 'require("electron")',
'net': 'require("net")',
'remote': 'require("remote")',
'shell': 'require("shell")',
'app': 'require("app")',
'ipc': 'require("ipc")',
'fs': 'require("fs")',
'buffer': 'require("buffer")',
'winston': 'require("winston")',
'system': '{}',
'file': '{}'
},
To make the logger available in an angular 2 app using electron, create a logger.js file and then wrap it with a global logging service TypeScript file (i.e. logging.service.ts). The logger.js file creates the logger variable with the desired Winston configuration settings.
logger.js:
var winston = require( 'winston' ),
fs = require( 'fs' ),
logDir = 'log', // Or read from a configuration
env = process.env.NODE_ENV || 'development',
logger;
​
winston.setLevels( winston.config.npm.levels );
winston.addColors( winston.config.npm.colors );
if ( !fs.existsSync( logDir ) ) {
// Create the directory if it does not exist
fs.mkdirSync( logDir );
}
logger = new( winston.Logger )( {
transports: [
new winston.transports.Console( {
level: 'warn', // Only write logs of warn level or higher
colorize: true
} ),
new winston.transports.File( {
level: env === 'development' ? 'debug' : 'info',
filename: logDir + '/logs.log',
maxsize: 1024 * 1024 * 10 // 10MB
} )
],
exceptionHandlers: [
new winston.transports.File( {
filename: 'log/exceptions.log'
} )
]
} );
​
module.exports = logger;
logging.service.ts:
export var LoggerService = require('./logger.js');
Now the logging service is available for use throughout the application.
Example:
import {LoggerService} from '<path>';
...
LoggerService.log('info', 'Login successful for user ' + this.user.email);

Node logging and error handling

I've created Node js with express and currently I use the console.log to log message and morgan for expresss...for production use what is recommended approach to use for error handling and logging ,there is recommended modules to use?
Examples will be very useful!
I try with the following
module.exports = function () {
var logger = new winston.Logger({
levels: {
info: 1
},
transports: [
new (winston.transports.File)({
level: 'info',
filename: path.join(process.cwd(), '/logs/log.json'),
})
]
});
}
I have used winston in the past quite effectively. In the below excerpt we are creating a custom log level called info such that we can call logger.info to log messages. I believe there are numerous default levels defined on winston which are well documented.
The second part is to define a transport. In winston this is essentially a storage device for your logs. You can define multiple transports in the array including Console logging, File logging, Rotated file logging, etc... These are all well documented here. Im my example I have created a file transport where the log file is located under log/logs.json within the root of the application. Every time I now call logger.info('blah blah blah') I will see a new log entry in the file.
var winston = require('winston'),
, path = require('path')
// Log to file.
var logger = new winston.Logger({
levels: {
info: 1
},
transports: [
new (winston.transports.File)({
level: 'info',
filename: path.join(process.cwd(), '/log/logs.json'),
})
]
});
// Write to log.
logger.info("something to log");

Categories

Resources