Winston log format - json

i am using Winston ^3.0.0-rc6 as below :
var options = {
file: {
level: 'info',
filename: `${appRoot}/logs/app.log`,
handleExceptions: true,
json: true,
prettyPrint: true,
maxsize: 5242880, // 5MB
maxFiles: 5,
colorize: true,
}
};
const jsonFormatter = (logEntry) => {
if (logEntry.type) {
const base = {
timestamp: new Date()
};
const json = Object.assign(base, logEntry);
logEntry[MESSAGE] = JSON.stringify(json);
} else {
logEntry = "";
}
return logEntry;
}
const logger = winston.createLogger({
format: winston.format(jsonFormatter)(),
transports: [
new winston.transports.File(options.file)
],
exceptionHandlers: [
new winston.transports.File(options.uncaughtExceptions)
]
});
my log output :
{"timestamp":"2018-06-10T07:41:03.387Z","type":"Authentication","status":"failed","level":"error","message":"Incorrect password"}
but i want them to be like :
{
"timestamp": "2018-06-10T07:41:03.387Z",
"type": "Authentication",
"status": "failed",
"level": "error",
"message": "Incorrect password"
}
i tried to play around with json : true , and prettyPrint but it did not do the trick .
Can any one help please
Thanks.

I noticed in your code that on the line
logEntry[MESSAGE] = JSON.stringify(json);
you're using JSON.stringify() which takes two more optional arguments
JSON.stringify(value[, replacer[, space]])
If you set space to the amount of spaces you'd like you'll get the output you're looking for. So change the initial line to be:
logEntry[MESSAGE] = JSON.stringify(json, null, 2); // or 4 ;)
(The replacer argument is null because we don't want to change the default behavior.)

This is deprecated: You can check the link here.
I tried to play around with json: true, and prettyPrint but it did not do the trick.
Simple code like this work for you:
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
//
// - Write to all logs with level `info` and below to `combined.log`
// - Write all logs error (and below) to `error.log`.
//
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
If this does not work, let me know so that I can improvise.

Related

Is there a way to successfully loop an Angular service call

How can I successfully run the following code?
onSubmit() {
let pdfData = [
{
field_name: 'data.Date',
value: this.freshDeskData.date,
placeholder: '',
page_no: 1,
},
{
field_name: 'data.Fullname',
value: "Bob Jones",
placeholder: '',
page_no: 1,
},
];
for(let i=0;i<pdfData.length;i++){
this.signHub.addPDFInfo(pdfData[i]).subscribe((data) => {
this.responseData = data[i]
});
}
}
Add PDF Service:
addPDFInfo(pdfInfo): Observable<PDFInfo> {
return this.http.put<PDFInfo>(
`${environment.apiUrl}/api/workflow/add-text-block?package_ID=${this.package_ID.data.package_id}&current_Document_ID=${this.current_Document_ID.data.documentid}`,
pdfInfo
);
}
The service is meant to loop through the JSON object and POST the information on the selected item to populate the related field on a PDF document. However, only one field is populated via the loop. The other remains empty.
You could achieve this by using the RxJs merge-operator, eg.:
onSubmit() {
let pdfData = [
{
field_name: 'data.Date',
value: this.freshDeskData.date,
placeholder: '',
page_no: 1,
},
{
field_name: 'data.Fullname',
value: "Bob Jones",
placeholder: '',
page_no: 1,
},
];
const requests = [];
for(let i=0;i<pdfData.length;i++){
requests.push(this.signHub.addPDFInfo(pdfData[i]));
}
merge(...requests).subscribe((data) => {
this.responseData = data[i]
})
}
granted you'd need to combine the results of each "next result" (that you're currently assigning to this.responseData). A candidate to solve that issue could be the reduce-operator
But, it's difficult to give a precise answer, without having knowledge about more of your codebase.

How to get data from database in array format using node js and MySql

I am using node.js as server language and Mysql as database so I am running query and getting data from database but is is showing in format like this
[ BinaryRow { name: 'Dheeraj', amount: '77.0000' },
BinaryRow { name: 'Raju', amount: '255.0000' } ]
What I want is
['Dheeraj', 77.0000],
['Raju', 66255.000030],
This what I am doing in my backend (node.js):
My model:
static getChartData(phoneNo, userType) {
let sql = 'select businessname as name,sum(billamt) amount from cashbackdispdets where consphoneno =' + phoneNo + ' group by businessid order by tstime desc limit 10'
return db.execute(sql, [phoneNo]);
My controller:
exports.getColumnChart = function(req, res) {
const phoneNo = req.body.userId
const userType = req.body.userType
console.log(phoneNo)
dashboardModule.getChartData(phoneNo, userType)
.then(([rows]) => {
if (rows.length > 0) {
console.log(rows)
return res.json(rows)
} else {
console.log("error")
return res.status(404).json({ error: 'Phone No. already taken' })
}
})
.catch((error) => {
console.log(error)
return res.status(404).json({ error: 'Something went wrong !!' })
})
}
I am sending this data to Ui and when I am receiving it on UI it is in the form of object inside array which is not the required data type I want
axios().post('/api/v1/Dashboard/DashboardColumnChart',this.form)
.then(res=>{
console.log(res.data)
debugger
this.chartData= res.data
})
The above code consoles on browser like
I am not getting any idea how o do it should I do it with backend or with front end and how
Nodejs will send you a JSON response if you want to change it. It is better to change or maniuplate it in a Front end framework. But if you want to change it in backend as you have asked Make sure that the rows is in the format that you want to recive.
let data = [
{ "name": "Dheeraj", "amount": "77.0000" },
{ "name": "Raju", "amount": "255.0000" }
]
// empty array to store the data
let testData = [];
data.forEach(element => {
testData.push(element.name)
});
You can format it using array.map and Object.values. map functions loops over each element and returns a modified element according to the callback provided. Object.values simply returns all the values of an object in an array.
const data = [ { "name": "Dheeraj", "amount": "77.0000" }, { "name": "Raju", "amount": "255.0000" } ];
const formattedData = data.map(obj => Object.values(obj));
console.log("Initial Data: ", data);
console.log("Formatted Data: ", formattedData);
// Map function example
const a = [1,2,3]
const mappedA = a.map(e => e * 2)
console.log(a, " mapped to: ", mappedA);
// Object.values example
const b = { firstName: 'John', lastName: 'Doe', number: '120120' }
console.log(Object.values(b));

How to solve Unexpected token p in JSON at position 3 using angular2 or typescript

When i go to save the survey content after editing, i get this error,
SyntaxError: Unexpected token p in JSON at position 3
at JSON.parse (<anonymous>)
Please anyone help me to solve this issue, I am hereby pasting my codes, please help.
ts code:
Surveypost = () => {
let token = this.auth.getAccessTokenId();
console.log(token)
let currentUser = this.auth.getCurrentUserData();
console.log(this.editor.text)
console.log(this.survey_val)
// let survey_json = JSON.parse(this.editor.text);
let survey_json:any;
try{
survey_json = JSON.parse(this.editor.text);
} catch(e) {
/*Handle the error scenario here*/
}
let survey_data = {
"value": survey_json,
};
console.log(survey_data)
this.AdminAPI
.createandSet(survey_data, token)
.subscribe(
survey => {
console.log(survey)
}, error => {
console.log(error);
}
);
}
I am getting the consoled output till, console.log(this.editor.text), then error comes.
The consoled output of console.log(this.editor.text) starts like this,
{
pages: [
{
name: "page1",
elements: [
{
type: "radiogroup",
name: "price",
title: "How long have you been a customer at {companyname}?",
isRequired: true,
choices: [
{
value: "less",
text: "0 - 3 months."
},
{
value: "medium",
text: "3 - 12 months."
},
{
value: "High",
text: "12 + months."
}
]
this.editor.text contains an invalid JSON.
When trying to parse that invalid JSON the error occurs. So in short terms, the following line is the one that crash: let survey_json = JSON.parse(this.editor.text);
Grab the output from the console.log(this.editor.text), run it trough a JSON validator/formatter like:
https://jsonformatter.curiousconcept.com/
And then you should be able to easily see why the error occurs, and why the program is not able to parse the JSON
EDIT FROM WHEN JSON HAS BEEN ADDED
AS you can see from the link mentioned above, the JSON is not valid, and that is the reason for the error message on the line: let survey_json = JSON.parse(this.editor.text);.
For instance a basic JSON should have the following structure:
{
"key" : "value",
"key2" : "value2"
}
You are also not ending the JSON correctly. I've formatted the JSON to a valid JSON here:
{
"pages":[
{
"name":"page1",
"elements":[
{
"type":"radiogroup",
"name":"price",
"title":"How long have you been a customer at {companyname}?",
"isRequired":true,
"choices":[
{
"value":"less",
"text":"0 - 3 months."
},
{
"value":"medium",
"text":"3 - 12 months."
},
{
"value":"High",
"text":"12 + months."
}
]
}
]
}
]
}
When you are trying to parse some text sent from a 3rd party source, it is a good idea to wrap the parse logic with a try catch block.
But do remember that this should be done only after fixing the trivial bugs in the remote source(that is, if you have access, of course).
replace,
let survey_json = JSON.parse(this.editor.text);
with,
let survey_json;
try{
survey_json = JSON.parse(this.editor.text);
} catch(e) {
/*Handle the error scenario here*/
/*Lets assign an empty object(or possibly a default value) instead*/
survey_json = {};
}

Mongoose .populate() only showing 1 document

I am trying to output just the hometeam name's to the page so that I can try to understand how to work with my code better. It is only printing one team to the page, and it is printing all the details of that team to the page, whereas I only want it to print one part.
This is my code, I want it to print the name's of each hometeam to the page
app.get('/home', function(req, res) {
Match.findOne({}).populate('hometeam.name').exec(function(err, teams){
util.log(teams);
res.send(teams);
});
});
But when I load the page all I get is the first piece of data from this list of Matches
[
{
"hometeam": "5106e7ef9afe3a430e000007",
"_id": "5113b7ca71ec596125000005",
"__v": 0,
"key": 1360246730427
},
{
"hometeam": "5113c13e0eea687b28000001",
"_id": "5113e951354fe70330000001",
"__v": 0,
"key": 1360259409361
},
{
"hometeam": "5113c13e0eea687b28000001",
"_id": "5113e999354fe70330000002",
"__v": 0,
"key": 1360259481412
}
]
Also, if I try to put util.log(teams.hometeam.name) I get the following:
TypeError: Cannot call method 'toString' of undefined
But I would want it to be able to print the name which belongs to hometeam here. As hometeam is just the objectId of a Team in my database, am I missing something with the DBreferencing here?
Update:
Team Schema
var Team = new Schema({
'key' : {
unique : true,
type : Number,
default: getId
},
'name' : { type : String,
validate : [validatePresenceOf, 'Team name is required'],
index : { unique : true }
}
});
module.exports.Schema = Team;
module.exports.Model = mongoose.model('Team', Team);
Match Schema
var Team = require('../schemas/Team').Schema;
var Match = new Schema({
'key' : {
unique: true,
type: Number,
default: getId
},
'hometeam' : { type: Schema.ObjectId, ref: 'Team' },
'awayteam' : { type: Schema.ObjectId, ref: 'Team' }
});
module.exports = mongoose.model('Match', Match);
Populate takes the property name of the property you are trying to retrieve. This means that you should use 'hometeam' instead of 'hometeam.name'. However, you want to retrieve the name of the team so you could filter for that. The call would then become..
Match.findOne({}).populate('hometeam', {name: 1}).exec(function(err, teams)
Now you have a property called 'hometeam' with in that the name. Have fun :)
EDIT
Showing how to have a single mongoose instance in more files to have correct registration of schemas.
app.js
var mongoose = require('mongoose');
var Team = require('./schemas/team-schema')(mongoose);
var Match = require('./schemas/match-schema')(mongoose);
// You can only require them like this ONCE, afterwards FETCH them.
var Team = mongoose.model('Team'); // LIKE THIS
schemas/match-schema.js
module.exports = function(mongoose) {
var Match = new mongoose.Schema({
'key' : {
unique: true,
type: Number,
default: getId
},
'hometeam' : { type: mongoose.Schema.ObjectId, ref: 'Team' },
'awayteam' : { type: mongoose.Schema.ObjectId, ref: 'Team' }
});
return mongoose.model('Match', Match);
};
schemas/team-schema.js
module.exports = function(mongoose) {
var Team = new mongoose.Schema({
'key' : {
unique : true,
type : Number,
default: getId
},
'name' : { type : String,
validate : [validatePresenceOf, 'Team name is required'],
index : { unique : true }
}
});
return mongoose.model('Team', Team);
};

ServiceStack.Text.JsonObject.Parse vs. NewtonSoft.Json.Linq.JObject.Parse for nested tree of 'dynamic' instances?

I'd like to try ServiceStack's json parsing, but I've already figured out how to do something I need via Newtonsoft. Can this same thing by done via ServiceStack?
I've tried with the commented out code but it gives exceptions, see below for exception details.
Thanks!
Josh
[Test]
public void TranslateFromGitHubToCommitMessage()
{
const string json =
#"
{
'commits':
[
{
'author': {
'email': 'dev#null.org',
'name': 'The Null Developer'
},
'message': 'okay i give in'
},
{
'author': {
'email': 'author#github.com',
'name': 'Doc U. Mentation'
},
'message': 'Updating the docs, that\'s my job'
},
{
'author': {
'email': 'author#github.com',
'name': 'Doc U. Mentation'
},
'message': 'Oops, typos'
}
]
}
";
dynamic root = JObject.Parse(json);
//dynamic root = ServiceStack.Text.JsonSerializer.DeserializeFromString<JsonObject>(json);
//dynamic root = ServiceStack.Text.JsonObject.Parse(json);
var summaries = new List<string>();
foreach (var commit in root.commits)
{
var author = commit.author;
var message = commit.message;
summaries.Add(string.Format("{0} <{1}>: {2}", author.name, author.email, message));
}
const string expected1 = "The Null Developer <dev#null.org>: okay i give in";
const string expected2 = "Doc U. Mentation <author#github.com>: Updating the docs, that's my job";
const string expected3 = "Doc U. Mentation <author#github.com>: Oops, typos";
Assert.AreEqual(3, summaries.Count);
Assert.AreEqual(expected1, summaries[0]);
Assert.AreEqual(expected2, summaries[1]);
Assert.AreEqual(expected3, summaries[2]);
}
Exceptions Detail
When using the first commented out line:
dynamic root = ServiceStack.Text.JsonSerializer.DeserializeFromString<JsonObject>(json);
This exception occurs when the method is called.
NullReferenceException:
at ServiceStack.Text.Common.DeserializeListWithElements`2.ParseGenericList(String value, Type createListType, ParseStringDelegate parseFn)
at ServiceStack.Text.Common.DeserializeEnumerable`2.<>c__DisplayClass3.<GetParseFn>b__0(String value)
at ServiceStack.Text.Common.DeserializeSpecializedCollections`2.<>c__DisplayClass7. <GetGenericEnumerableParseFn>b__6(String x)
at ServiceStack.Text.Json.JsonReader`1.Parse(String value)
at ServiceStack.Text.JsonSerializer.DeserializeFromString[T](String value)
at GitHubCommitAttemptTranslator.Tests.GitHubCommitAttemptTranslatorTests.TranslateFromGitHubToCommitMessage()
And, the second:
dynamic root = ServiceStack.Text.JsonObject.Parse(json);
var summaries = new List<string>();
foreach (var commit in root.commits) // <-- Happens here
'ServiceStack.Text.JsonObject' does not contain a definition for 'commits'
Note: the message is 'string' does not contain a definition for 'commits' if I use code from line one, but change the type to or to instead of
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at GitHubCommitAttemptTranslator.Tests.GitHubCommitAttemptTranslatorTests.TranslateFromGitHubToCommitMessage()
After using DynamicJson from .NET 4.0 ServiceStack
Referring to mythz's comment:
This test case works, but if I modify it like below:
var dog = new { Name = "Spot", Parts = new { Part1 = "black", Part2 = "gray" }, Arr = new [] { "one", "two", "three"} };
var json = DynamicJson.Serialize(dog);
var deserialized = DynamicJson.Deserialize(json);
Then, deserialized.Name and Parts are fine, but Arr is of type string.
Also:
If I use ' quotes it doesn't appear to work. Is that normal? json2 works (to the degree that Arr is also still a string), but json3 does not work at all. It just returns
Immediate Window:
deserialized = DynamicJson.Deserialize(json3);
{}
base {System.Dynamic.DynamicObject}: {}
_hash: Count = 1
----- code: -----
var json2 =
#"
{
""Name"": ""Spot"",
""Parts"": {
""Part1"": ""black"",
""Part2"": ""gray""
},
""Arr"": [
""one"",
""two"",
""three""
]
}";
var json3 =
#"
{
'Name': 'Spot',
'Parts': {
'Part1': 'black',
'Part2': 'gray'
},
'Arr': [
'one',
'two',
'three'
]
}";
var deserialized = DynamicJson.Deserialize(json1);
ServiceStack's JSON Serializer also supports dynamic parsing, see examples of how to parse GitHub's JSON in the Dynamic JSON section of the wiki page.