npm winston set log level for basic logging instance - node.js

Setting winston log level to 'debug' in 'easy mode' was not well documented so I've shown an example below (and will submit a PR soon).
the answer is winston.level = 'debug'
I want to use the winston logging package in a node script and not bother with any config, just be able to call winston.debug, winston.info, winston.error and then pass in the log level as a command line param. The docs for 'easy mode' did not include how to set log level so I've shown it below.
The code:
var winston = require('winston');
winston.transports.Console.level = "debug";
winston.log("error", "error test 1");
winston.log("info", "info test 1");
winston.log("debug", "debug test 1");
winston.level = "debug";
winston.log("error", "error test 2");
winston.log("info", "info test 2");
winston.log("debug", "debug test 2");
Will output:
error: error test 1
info: info test 1
error: error test 2
info: info test 2
debug: debug test 2
Hope this helps

the answer is winston.level = 'debug'

Related

How use a "commander" CLI flag to set the the "winston" logging level in a node library

Given this sample commander application:
// index.ts
// Config Winston:
winston.configure({
level: 'info',
format: winston.format.combine(winston.format.splat(), winston.format.cli()),
transports: [new winston.transports.Console({})],
});
winston.info('Started CLI')
// Configure commander
const cli = new Command()
.option('--debug', 'Debug mode', false) // Or --verbose, it doesn't really matter.
.action(actionCallback); // Imported.
cli.parse();
How can I set the winston logging level given the provided commander's option --debug?
I could use a DEBUG env var, but that kinda breaks the purpose of the --debug flag in the CLI. Any suggestion?
The easiest solution, actually workaround, is to check for the --debug flag myself:
const debugLevel = process.argv.indexOf('--debug') != -1 ? 'debug' : 'info';
winston.configure({
level: debugLevel,
format: winston.format.combine(winston.format.splat(), winston.format.cli()),
transports: [new winston.transports.Console({})],
});

Serilog MinimumLevel Override with AspNetCore

Serilog with ASP NET 5 Razor Pages.
Reducing log verbosity is very useful for Informational logs.
However for debug logs, how to get a MinimumLevel.Override("Microsoft.AspNetCore") to be specific to a debug file sink?
Creating 2 configurations could be a solution, but feels like something more elegant may be possible?
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.FromLogContext()
// for debug file sink I want the override to be Debug
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Debug)
.WriteTo.File("debug.txt", restrictedToMinimumLevel: LogEventLevel.Debug)
// for info and warning file sinks I want the override to be Warning
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
.WriteTo.File("info.txt", restrictedToMinimumLevel: LogEventLevel.Information)
.WriteTo.File("warning.txt", restrictedToMinimumLevel: LogEventLevel.Warning)
.CreateLogger();
Everything works as expected using just one override. But not together.
In the example above the Warning override takes precedence and no AspNetCore Debug event logs are written to debug.txt
Edit
In summary, I'd like my debug log to include Information event level from Microsoft.AspNetCore and my info log file to include Warning event level from Microsoft.AspNetCore
I got the 2 logs files how I wanted by commenting out and in 1. and 2. below
// 1. for debug file sink I want AspNetCore.Information or Debug level override
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Information)
.WriteTo.File($#"{logFilePath}debugx.txt", restrictedToMinimumLevel: LogEventLevel.Debug, rollingInterval: RollingInterval.Day)
// 2. for info and warning file sinks below I want only AspNetCore warnings
//.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
It's an interesting one
You want to filter log data and want to populate into different file sinks.
For Example /Logs/Error/Errlog.txt and /Logs/Info/InfoLog.txt
You can achieve this by using Serilog.Expressions nuget package. If time permits, I will paste a working example here.
Serilog.Expressions sample from Serilog
https://github.com/serilog/serilog-expressions/blob/dev/example/Sample/Program.cs
In below example it will exclude Name=User line and only print second line on console
using var log = new LoggerConfiguration()
.Filter.ByExcluding("#m like 'Welcome!%' and Name = 'User'")
.WriteTo.Console()
.CreateLogger();
// Logged normally
log.Information("Welcome!, {Name}", "User");
// Excluded by the filter
log.Information("Welcome!, {Name}", "Domain\\UserName");
Here is the filtering example for \Logs\Info\Info-20210720.txt which filters Error, Fatal or Warning levels. More information here
var exprInfo = "#l='Error' or #l='Fatal' or #l='Warning'";
var loggerInfo = new LoggerConfiguration()
.WriteTo.File(
#"C:\Temp\Logs\Info\Info-.txt",
fileSizeLimitBytes: 1_000_000,
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] [{SourceContext}] [{EventId}] {Message}{NewLine}{Exception}",
rollingInterval: RollingInterval.Day,
rollOnFileSizeLimit: true,
shared: true,
flushToDiskInterval: TimeSpan.FromSeconds(1))
.MinimumLevel.Override("Microsoft", LogEventLevel.Debug)
.Filter.ByExcluding(exprInfo)
.CreateLogger();
try
{
loggerInfo.Debug("TEST");
SelfLog.Enable(Console.Out);
var sw = System.Diagnostics.Stopwatch.StartNew();
for (var i = 0; i < 100; ++i)
{
loggerInfo.Information("Hello, file logger!>>>>>>{Count}", i);
loggerInfo.Information("Writing to log file with INFORMATION severity level.");
loggerInfo.Debug("Writing to log file with DEBUG severity level.");
loggerInfo.Warning("Writing to log file with WARNING severity level.");
loggerInfo.Error("Writing to log file with ERROR severity level.");
loggerInfo.Fatal("Writing to log file with CRITICAL severity level.");
}
sw.Stop();
Console.WriteLine($"Elapsed: {sw.ElapsedMilliseconds} ms");
Console.WriteLine($"Size: {new FileInfo("log.txt").Length}");
Console.WriteLine("Press any key to delete the temporary log file...");
Console.ReadKey(true);
}
catch (Exception ex)
{
loggerInfo.Fatal(ex, "Application Start-up for Serilog failed");
throw;
}
finally
{
Log.CloseAndFlush();
}
I solved it by using sub loggers and filters as described in here: How can I override Serilog levels differently for different sinks?
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.FromLogContext()
// Includes Debug from Microsoft.AspNetCore (noisy)
// useful for deep debugging
.WriteTo.File($#"logs/debug.txt", rollingInterval: RollingInterval.Day)
// Info-with-framework (useful for debugging)
.WriteTo.Logger(lc => lc
.MinimumLevel.Information()
.Filter.ByExcluding("RequestPath in ['/health-check', '/health-check-db']")
.WriteTo.File("logs/info-with-framework.txt", rollingInterval: RollingInterval.Day)
.WriteTo.Console()
)
// Info
// framework minimum level is Warning (normal everyday looking at logs)
.WriteTo.Logger(lc => lc
.MinimumLevel.Information()
.Filter.ByExcluding("RequestPath in ['/health-check', '/health-check-db']")
.Filter.ByExcluding("SourceContext = 'Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware'")
.Filter.ByExcluding(logEvent =>
logEvent.Level < LogEventLevel.Warning &&
Matching.FromSource("Microsoft.AspNetCore").Invoke(logEvent))
.WriteTo.File("logs/info.txt", rollingInterval: RollingInterval.Day))
// Warning (bad things - Warnings, Error and Fatal)
.WriteTo.Logger(lc => lc
.MinimumLevel.Warning()
// stopping duplicate stacktraces, see blog 2021/03/10/a11-serilog-logging-in-razor-pages
.Filter.ByExcluding("SourceContext = 'Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware'")
.WriteTo.File("logs/warning.txt", rollingInterval: RollingInterval.Day))
// SignalR - tweak levels by filtering on these namespaces
// Microsoft.AspNetCore.SignalR
// Microsoft.AspNetCore.Http.Connections
.CreateLogger();
Although this works, there may be a better way https://nblumhardt.com/2016/07/serilog-2-write-to-logger/
I feel like you don't need those minium level override calls. The restricted to minimum level parameter in the sinks will take are of filtering.
You do need to set the minimum level to info so the info sink can work.

Winston logger profiler time unit

I'm using winston logger profiling.
my question is how can I change the time unit of the profiler.
My code:
this.logger.profile(`some ${jobId}`);
// do the job ....
this.logger.profile(`some ${jobId}`);
In the result I see:
{ ...,"message": "some 1", "durationMs":2500 ... }
My question is how (is) it possible to configure the time unit from ms to seconds/minuets etc...
So that I'll see
{ ...,"message": "some 1", "durationSeconds: 2.5" ... }
The answer is unfortunately no: winston doesn't provide an option of providing the duration in a unit other than ms, see:
https://github.com/winstonjs/winston/blob/master/lib/winston/profiler.js#L47

Grails 2.4.3 considers FATAL log level as ERROR

I'm learning about log4j configuration in Grails. Below is my Config.groovy. The logger grails.app.controllers.logging.FatalController is configured to log fatal level only.
log4j.main = {
// Example of changing the log pattern for the default console appender:
//
//appenders {
// console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
//}
fatal 'grails.app.controllers.logging.FatalController'
error 'org.codehaus.groovy.grails.web.servlet', // controllers
'org.codehaus.groovy.grails.web.pages', // GSP
'org.codehaus.groovy.grails.web.sitemesh', // layouts
'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
'org.codehaus.groovy.grails.web.mapping', // URL mapping
'org.codehaus.groovy.grails.commons', // core / classloading
'org.codehaus.groovy.grails.plugins', // plugins
'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
'org.springframework',
'org.hibernate',
'net.sf.ehcache.hibernate'
warn 'grails.app.services.logging.WarnService',
'grails.app.controllers.logging.WarnController'
This is my FatalController.groovy:
package logging
class FatalController {
def index(){
log.debug("This is not shown")
log.warn("neither this")
log.error("or that")
log.fatal("but this does")
render "logged"
}
}
Now, when I execute this I expected it to log "but this does". However it doesn't. When I changed Config.groovy line:
fatal 'grails.app.controllers.logging.FatalController'
to this:
all 'grails.app.controllers.logging.FatalController'
The output I get is this:
2014-10-15 12:33:04,070 [http-bio-8080-exec-2] DEBUG logging.FatalController - This is not shown
2014-10-15 12:33:04,071 [http-bio-8080-exec-2] WARN logging.FatalController - neither this
| Error 2014-10-15 12:33:04,072 [http-bio-8080-exec-2] ERROR logging.FatalController - or that
| Error 2014-10-15 12:33:04,072 [http-bio-8080-exec-2] ERROR logging.FatalController - but this does
Notice that the message "but this does" is defined in FatalController.groovy to be logged as fatal
log.fatal("but this does")
And what the log message say is that it is a ERROR level message log:
| Error 2014-10-15 12:33:04,072 [http-bio-8080-exec-2] ERROR logging.FatalController - but this does
So there are two problems: 1) FATAL log messages are not shown when the logger level is defined as FATAL and 2) when I code log.fatal("something"), the log shows it as an ERROR level message.
What am I doing wrong here?
I think it's a Grails bug (I'm using Grails 2.4.5).
I found a workaround: try to use log4j in "old way".
import org.apache.log4j.Logger
class FatalController {
Logger log = Logger.getLogger(getClass())
def index() {
// ...
}
}

NodeJs WinstonJS very weird start

I just started using winstonJS for NodeJS app logging.
My code goes like this :
var winston = require('winston');
var logger = new winston.Logger({
levels: { error: 0, warn: 1, info: 2, debug: 3, trace: 4 },
transports: [
new (winston.transports.Console)()
]
});
logger.log('error', 'log0');
logger.log('warn', 'log1');
logger.log('info', 'log2');
logger.log('debug', 'log3');
logger.log('trace', 'log4');
and the ONLY logs that I get in my console are :
info: log2
trace: log4
debug: log3
Note the wrong order as well.
Am I missing something obvious ?
Thanks
You have to consider 2 things:
Console transport is created always with default level "info" unless you specify a different level
when you specify a level for a transport, the logger will print all the message with level >= than the specified level
Also consider that the default logging levels for winston are: silly=0, debug=1, verbose=2, info=3, warn=4, error=5
Analyzing your code I can see you defined a new "info" level, with value of 2: this means the console log will print only messages with levels >= 2, and in your example these levels are exactly info, debug and trace (I guess you define your levels in the wrong order).
If you change your code like this, you will see all the message printed:
transports: [
new (winston.transports.Console)({level: 'error'})
]
About the wrong output order I can't reproduce it, my output is always
info: log2
debug: log3
trace: log4
PS: if you define levels like this error: 0, warn: 1, infoz: 2, debug: 3, trace: 4 with anything different replacing info, the logger will print nothing at all because the default console transport level will remain info. You can discover your transport level with a simple
console.log(logger.transports.console.level);

Resources