Winston outputs json instead of formatted string - javascript

I have set up a simple winston logger in my app like this:
function logger(success, msg) {
let now = new Date().toUTCString()
let logger = new (winston.Logger)({
transports: [
new (winston.transports.File)({
filename: 'log.log',
timestamp: function() {
return new Date().toUTCString();
},
formatter: function(options) {
return `>>>>>>>>>> ${options.timestamp()} - ${options.level.toUpperCase} - ${options.message}`;
}
})
]
});
if (success) {
logger.log('info', msg)
} else {
logger.log('error', msg)
}
}
But instead of logging the formatted string, it outputs the following:
{"level":"error","message":"Nothing to upload","timestamp":"Mon, 23 Apr 2018 13:53:01 GMT"}
Ideas? Am I missing something? (Of course I am)

As you can find out in winston documentation for File you can set property json to false if you don't want information in file to be JSON objects. By default this property is true.
json: If true, messages will be logged as JSON (default true).
Could you try to change your code like this:
function logger(success, msg) {
let now = new Date().toUTCString()
let logger = new (winston.Logger)({
transports: [
new (winston.transports.File)({
filename: 'log.log',
timestamp: function() {
return new Date().toUTCString();
},
json: false,
formatter: function(options) {
return `>>>>>>>>>> ${options.timestamp()} - ${options.level.toUpperCase} - ${options.message}`;
}
})
]
});
if (success) {
logger.log('info', msg)
} else {
logger.log('error', msg)
}
}

Related

SQL Tedious Loop through object of array and execute insert statement function error Request is not a constructor

I'm new to Js, and would appreciate some help.
Currently, via tedious js, I've written a sql function that passes an insert statement that loops through an array of objects and inserts each property in each object in array to SQL.
To do this, I've written a loop to iterate through the array, and insert each property as a new entry into sql.
However, when i try to execute the function after the connect, the function returns error Request is not a constructor
Here is the full code below. Is there some scope issue here, or am I not correctly handling the tedious js events properly or is there some sort of issue with my for loop?
var jsonArray = [];
let jsonobj = {
test: "1",
test2: "2"
}
let jsonobj1 = {
test: "23",
test2: "54"
}
jsonArray.push(jsonobj)
jsonArray.push(jsonobj1)
jsonArray.push(jsonobj)
var config = {
server: '123', //update me
authentication: {
type: 'default',
options: {
userName: '123', //update me
password: '1234' //update me
}
},
options: {
// If you are on Microsoft Azure, you need encryption:
//encrypt: true,
requestTimeout: 30 * 1000,
trustServerCertificate: true,
database: 'db', //update me
rowCollectionOnRequestCompletion: true,
rowCollectionOnDone: true
}
};
var connection = new Connection(config);
connection.on('debug', function(err) { console.log('debug:', err);})
connection.on('connect', function(err) {
});
for (var i = 0; i < jsonArray.length; i++){
var sql = `insert into store (storekey,ip,port) values ( \'${jsonArray[i].test2}\' , '2' , '6');`
executeStatement1(sql)
}
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
function executeStatement1(sql) {
request = new Request(sql, function(err) {
if (err) {
console.log(err);}
});
request.on('row', function(columns) {
columns.forEach(function(column) {
if (column.value === null) {
console.log('NULL');
} else {
console.log(" success " + column.value);
}
});
});
connection.execSql(request);
}

Mongoose.model('model_name') return empty object when function is required in the mongoose model schema file

I apologize if the title of the question is misleading, because I am not too sure how to explain this. I have 2 files, matchedTransaction.js and player.js.
sharedApi/player.js
const MatchedTransactionModel = require('../models/matchedTransaction');
// #1: If I try to console log here, the output will be an empty object "{}"
console.log(MatchedTransactionModel);
async function banPlayer(userId) {
// ...
// Because MatchedTransactionModel is an empty object,
// the code below will crash with the following error:
// "MatchedTransactionModel.findOne is not a function"
const pendingMatchedTransaction = await MatchedTransactionModel.findOne({
$and: [
{
$or: [
{ reserverAccountId: `${account._id}` },
{ sellerAccountId: `${account._id}` },
],
},
{
$or: [
{ status: 'pendingReserverPayment' },
{ status: 'pendingSellerConfirmation' },
],
},
],
});
// ...
}
module.exports = {
banPlayer,
};
models/matchedTransaction.js
const mongoose = require('mongoose');
const { banPlayer } = require('../sharedApi/player');
const MatchedTransactionSchema = new mongoose.Schema([
{
createdDate: {
type: Date,
required: true,
},
// ...
},
]);
MatchedTransactionSchema.post('init', async function postInit() {
// ...
await banPlayer(userId);
});
const MatchedTransactionModel = mongoose.model('matchedTransactions', MatchedTransactionSchema);
module.exports = MatchedTransactionModel;
Notice that in player.js when I tried to console.log the required MatchedTransactionModel, it returns an empty object. However, if I made the following changes to matchedTransaction.js:
models/matchedTransaction.js
// Instead of requiring banPlayer outside, I only require it when it is used
// const { banPlayer } = require('../sharedApi/player');
MatchedTransactionSchema.post('init', async function postInit() {
// ...
const { banPlayer } = require('../sharedApi/player');
await banPlayer(userId);
});
// ...
The output of the previously mentioned console.log will be a non-empty object, and MatchedTransactionModel.findOne is working as expected.
Why does that happen?
The only problem I see with your code is that when you define the schema on matchedTransaction.js, you passed an array which I think is problematic and does not make sense. You must pass an object there:
const MatchedTransactionSchema = new mongoose.Schema({
createdDate: {
type: Date,
required: true,
},
// ...
});

nodejs add line number to winston based logger

How can I add line number to this following winston-based logger?
So that the line number appears at the end of the file path.
const winston = require('winston');
winston.emitErrs = true;
const logger = function (module) {
let parts, path;
parts = module.filename.split('\\');
path = parts[parts.length - 2] + '\\' + parts.pop();
return new winston.Logger({
transports: [
new winston.transports.Console({
level: 'debug',
handleExceptions: true,
json: false,
colorize: true,
label: path,
timestamp: true
})
],
exitOnError: false
});
};
module.exports = logger;
update
current output example is like:
2018-06-10T00:13:33.344Z - info: [app\main.js] Here is my log
the desired format is:
2018-06-10T00:13:33.344Z - info: [app\main.js:150] Here is my log
in which 150 is appended to the file path.
You can use this code in a new file winston.js. and the Use it by requiring it anywhere.
var winston = require('winston')
var path = require('path')
var PROJECT_ROOT = path.join(__dirname, '..')
var appRoot = require('app-root-path');
const options = {
file: {
level: 'info',
filename: `${appRoot}/logs/app.log`,
handleExceptions: true,
json: true,
maxsize: 5242880, // 5MB
maxFiles: 5,
colorize: false,
timestamp: true
},
console: {
level: 'debug',
handleExceptions: true,
json: true,
colorize: true,
timestamp: true
}
};
var logger = new winston.Logger({
transports: [
new winston.transports.File(options.file),
new winston.transports.Console(options.console)
],
exitOnError: false // do not exit on handled exceptions
});
logger.stream = {
write: function (message) {
logger.info(message)
}
}
// A custom logger interface that wraps winston, making it easy to instrument
// code and still possible to replace winston in the future.
module.exports.debug = module.exports.log = function () {
logger.debug.apply(logger, formatLogArguments(arguments))
}
module.exports.info = function () {
logger.info.apply(logger, formatLogArguments(arguments))
}
module.exports.warn = function () {
logger.warn.apply(logger, formatLogArguments(arguments))
}
module.exports.error = function () {
logger.error.apply(logger, formatLogArguments(arguments))
}
module.exports.stream = logger.stream
/**
* Attempts to add file and line number info to the given log arguments.
*/
function formatLogArguments (args) {
args = Array.prototype.slice.call(args)
var stackInfo = getStackInfo(1)
if (stackInfo) {
// get file path relative to project root
var calleeStr = '(' + stackInfo.relativePath + ':' + stackInfo.line + ')'
if (typeof (args[0]) === 'string') {
args[0] = calleeStr + ' ' + args[0]
} else {
args.unshift(calleeStr)
}
}
return args
}
/**
* Parses and returns info about the call stack at the given index.
*/
function getStackInfo (stackIndex) {
// get call stack, and analyze it
// get all file, method, and line numbers
var stacklist = (new Error()).stack.split('\n').slice(3)
// stack trace format:
// http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
// do not remove the regex expresses to outside of this method (due to a BUG in node.js)
var stackReg = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/gi
var stackReg2 = /at\s+()(.*):(\d*):(\d*)/gi
var s = stacklist[stackIndex] || stacklist[0]
var sp = stackReg.exec(s) || stackReg2.exec(s)
if (sp && sp.length === 5) {
return {
method: sp[1],
relativePath: path.relative(PROJECT_ROOT, sp[2]),
line: sp[3],
pos: sp[4],
file: path.basename(sp[2]),
stack: stacklist.join('\n')
}
}
}

Moment not working for winston.transports.File

From the below post i got the idea to use moment with winston to change date format.
winston:how to change timestamp format
but this is working for winston.transports.Console and its not working for winston.transports.File
PFB my code :
var logger = new winston.Logger({
level: 'debug',
timestamp: function () {
return moment().format('YYYY-MM-DD hh:mm:ss')
},
transports: [
new(winston.transports.MongoDB)({
db : 'dbpath',
collection : 'Logs',
level : 'error',
capped : true,
timestamp: function () {
return moment().format('YYYY-MM-DD hh:mm:ss')
}
}),
new winston.Logger({
level: 'debug',
transports: [
new(winston.transports.File)
({ filename: 'filename' })
],
timestamp: function () {
return moment().format('YYYY-MM-DD hh:mm:ss')
}
}),
new winston.transports.Console({
timestamp: function () {
return moment().format('YYYY-MM-DD hh:mm:ss')
}
})
]
})
I am getting this in my output file:
{"level":"info","message":"info Hello","timestamp":"2018-04-16T06:42:12.819Z"}
{"level":"error","message":"error Hello","timestamp":"2018-04-16T06:42:12.847Z"}
{"level":"debug","message":"debug Hello","timestamp":"2018-04-16T06:42:12.861Z"}
{"level":"warn","message":"debug Hello","timestamp":"2018-04-16T06:42:12.900Z"}
it's neither working for mongodb transport

Angular 2 get json data from url

let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
let ep = './data.json';
this.events = this.http
.get(ep, { headers: headers })
.map(res => res.json())
.map(({results}: { results: Data[] }) => {
return results.map((data: Data) => {
return {
title: data.title,
start: new Date(data.from),
colors.yellow,
};
});
});
Here is my code in Angular 2. I want to get data from a JSON file and show it in the angular-calendar.
Here is angular-calendar Demo: How can I do that?
You can make a service that contains the data for the calendar.
getList(): any
{
var date = new Date( '2017-01-12' );
var date2 = new Date( '2017-03-17' );
return (
[
{ title: 'Beauty And The Beast', start: date2, color: { primary: '#e3bc08', secondary: '#FDF1BA' } },
{ title: 'La La Land', start: date, color: { primary: '#e3bc08', secondary: '#FDF1BA' } }
]
)
}
Then you will have to remove the async pipe from the template.
Before:
[events]="(events | async ) || []
After:
[events]="(events) || []
Then call the service in the component:
fetchEvents()
{
this.events= this._data_Service.getList()
}
2. To get data.json file with Http you need to put the JSON file in the assets folder: ./assets/data.jsom, so that it can be accessed by the application: localhost:8080/data.json.
Then you simply make a get request.
fetchEvents(): void {
this.events = this.http
.get('../../assets/data.json') // the path may vary depending
// on your directory structure.
.map(res => res.json())
.map((results) => { // this might be different depending on
// your json and type definition.
return results.map((data: Data) => {
console.log({title: data.title,
start: new Date(data.from),
color: colors.yellow})
return {
title: data.title,
start: new Date(data.from),
color: colors.yellow,data
};
});
});
}// fetchEvents
Here is the JSON I used:
[
{"title":"La La Land","from":1490475722305},
{"title":"Beauty And The Beast","from":1490475722305}
]
finally, you can include the type definition in your component:
interface Data {
title: string;
from:string;
}
interface DataEvent extends CalendarEvent {
data: Data;
}

Categories

Resources