Created examples of logging

This commit is contained in:
fkereki
2018-05-27 01:23:22 -04:00
parent e7ed04f19f
commit 277403163e
12 changed files with 216 additions and 468 deletions
+148 -6
View File
@@ -294,6 +294,14 @@
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
"dev": true
},
"async": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
"integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
"requires": {
"lodash": "4.17.10"
}
},
"async-each": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
@@ -1463,6 +1471,22 @@
"object-visit": "1.0.1"
}
},
"color": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/color/-/color-0.8.0.tgz",
"integrity": "sha1-iQwHw/1OZJU3Y4kRz2keVFi2/KU=",
"requires": {
"color-convert": "0.5.3",
"color-string": "0.3.0"
},
"dependencies": {
"color-convert": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz",
"integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0="
}
}
},
"color-convert": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
@@ -1475,8 +1499,20 @@
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"color-string": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz",
"integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=",
"requires": {
"color-name": "1.1.3"
}
},
"colornames": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/colornames/-/colornames-0.0.2.tgz",
"integrity": "sha1-2BH9bIT1kClJmorEQ2ICk1uSvjE="
},
"colors": {
"version": "0.6.2",
@@ -1484,6 +1520,15 @@
"integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=",
"dev": true
},
"colorspace": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.0.1.tgz",
"integrity": "sha1-yZx5btMRKLmHalLh7l7gOkpxl0k=",
"requires": {
"color": "0.8.0",
"text-hex": "0.0.0"
}
},
"component-emitter": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
@@ -1752,6 +1797,16 @@
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"diagnostics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.0.tgz",
"integrity": "sha1-4QkJALSVI+hSe+IPCBJ1IF8q42o=",
"requires": {
"colorspace": "1.0.1",
"enabled": "1.0.2",
"kuler": "0.0.0"
}
},
"dns-prefetch-control": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz",
@@ -1832,6 +1887,14 @@
"integrity": "sha1-dk6IfKkQTQGgrI6r7n38DizhQQQ=",
"dev": true
},
"enabled": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz",
"integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=",
"requires": {
"env-variable": "0.0.4"
}
},
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
@@ -1846,6 +1909,11 @@
"iconv-lite": "0.4.21"
}
},
"env-variable": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.4.tgz",
"integrity": "sha512-+jpGxSWG4vr6gVxUHOc4p+ilPnql7NzZxOZBxNldsKGjCF+97df3CbuX7XMaDa5oAVkKQj4rKp38rYdC4VcpDg=="
},
"error-ex": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
@@ -2448,6 +2516,11 @@
}
}
},
"fecha": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
"integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg=="
},
"figures": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
@@ -4123,8 +4196,7 @@
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
"dev": true
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
},
"is-symbol": {
"version": "1.0.1",
@@ -4283,6 +4355,14 @@
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
"dev": true
},
"kuler": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/kuler/-/kuler-0.0.0.tgz",
"integrity": "sha1-tmu0a5NOVQ9Z2BiEjgq7pPf1VTw=",
"requires": {
"colornames": "0.0.2"
}
},
"latest-version": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
@@ -4359,8 +4439,7 @@
"lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
"dev": true
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
},
"lodash.assign": {
"version": "4.2.0",
@@ -4408,6 +4487,29 @@
"resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
"integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs="
},
"logform": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/logform/-/logform-1.7.0.tgz",
"integrity": "sha512-IyyAkQiA0I3LEar69J0bR5kg7204883jsWW4os9ypXiEsHueuPwfEClC3aSelhG+pIbMD0l23nAkz5VRXZYMWA==",
"requires": {
"colors": "1.3.0",
"fecha": "2.3.3",
"ms": "2.1.1",
"triple-beam": "1.3.0"
},
"dependencies": {
"colors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz",
"integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw=="
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}
}
},
"loose-envify": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
@@ -4817,6 +4919,11 @@
"wrappy": "1.0.2"
}
},
"one-time": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz",
"integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4="
},
"onetime": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
@@ -5912,6 +6019,11 @@
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
"stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
"integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="
},
"static-extend": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
@@ -6119,6 +6231,11 @@
}
}
},
"text-hex": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-0.0.0.tgz",
"integrity": "sha1-V4+8haapJjbkLdF7QdAhjM6esrM="
},
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -6215,6 +6332,11 @@
"integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
"dev": true
},
"triple-beam": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
"integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
},
"type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
@@ -6552,6 +6674,26 @@
"integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=",
"dev": true
},
"winston": {
"version": "3.0.0-rc5",
"resolved": "https://registry.npmjs.org/winston/-/winston-3.0.0-rc5.tgz",
"integrity": "sha512-BRYS7jsNkfLAqGu4dZW3kp6CmqiWKrComvfsIMYdsnpPre7g8BIw63nWRyX69vxyLYvZdszcEyxJkJmILXd/pA==",
"requires": {
"async": "2.6.1",
"diagnostics": "1.1.0",
"is-stream": "1.1.0",
"logform": "1.7.0",
"one-time": "0.0.4",
"stack-trace": "0.0.10",
"triple-beam": "1.3.0",
"winston-transport": "3.2.1"
}
},
"winston-transport": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-3.2.1.tgz",
"integrity": "sha512-WPqbdAmMK/kfWCWKM2bA1o997wWPZ0jg5NpO8JPqoaDZgCiZnFpIEddcf7Ur4UZV2sYRUdySVBWKx0+gQQ/jrg=="
},
"wordwrap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+2 -1
View File
@@ -78,7 +78,8 @@
"express": "^4.16.3",
"helmet": "^3.12.1",
"jsonwebtoken": "^8.2.1",
"mariasql": "^0.2.6"
"mariasql": "^0.2.6",
"winston": "^3.0.0-rc5"
},
"devDependencies": {
"babel-eslint": "^8.2.2",
-15
View File
@@ -1,15 +0,0 @@
/* @flow */
"use strict";
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors());
app.get("/", (req, res) => res.send("Server alive, with CORS!"));
app.listen(8080, () =>
console.log("CORS server ready at http://localhost:8080/!")
);
-18
View File
@@ -1,18 +0,0 @@
/* @flow */
"use strict";
const express = require("express");
const app = express();
const http = require("http");
http.createServer(app).listen(8080);
app.use((req, res, next) => {
if (req.secure) {
next();
} else {
res.redirect(
`https://${req.headers.host.replace(/8080/, "8443")}${req.url}`
);
}
});
-17
View File
@@ -1,17 +0,0 @@
/* @flow */
"use strict";
const express = require("express");
const app = express();
const https = require("https");
const fs = require("fs");
const path = require("path");
const keysPath = path.join(__dirname, "../../certificates");
const ca = fs.readFileSync(`${keysPath}/modernjsbook.csr`);
const cert = fs.readFileSync(`${keysPath}/modernjsbook.crt`);
const key = fs.readFileSync(`${keysPath}/modernjsbook.key`);
https.createServer({ ca, cert, key }, app).listen(8443);
app.get("/", (req, res) => res.send("Secure server!"));
-69
View File
@@ -1,69 +0,0 @@
/* @flow */
"use strict";
const express = require("express");
const app = express();
const jwt = require("jsonwebtoken");
const bodyParser = require("body-parser");
const validateUser = require("./validate_user.js");
const SECRET_JWT_KEY = "modernJSbook";
app.use(bodyParser.urlencoded({ extended: false }));
app.get("/public", (req, res) => {
res.send("the /public endpoint needs no token!");
});
app.post("/gettoken", (req, res) => {
validateUser(req.body.user, req.body.password, (idErr, userid) => {
if (idErr !== null) {
res.status(401).send(idErr);
} else {
jwt.sign(
{ userid },
SECRET_JWT_KEY,
{ algorithm: "HS256", expiresIn: "1h" },
(err, token) => res.status(200).send(token)
);
}
});
});
app.use((req, res, next) => {
// First check for the Authorization header
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith("Bearer ")) {
return res.status(401).send("No token specified");
}
// Now validate the token itself
const token = authHeader.split(" ")[1];
jwt.verify(token, SECRET_JWT_KEY, (err, decoded) => {
if (err) {
// Token bad formed, or expired, or other problem
return res.status(403).send("Token expired or not valid");
} else {
// Token OK; get the user id from it
req.userid = decoded.userid;
// Keep processing the request
next();
}
});
});
app.get("/private", (req, res) => {
res.send("the /private endpoint needs JWT, but it was provided: OK!");
});
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
console.error("Error....", err.message);
res.status(500).send("INTERNAL SERVER ERROR");
});
app.listen(8080, () =>
console.log("Mini JWT server ready, at http://localhost:8080/!")
);
-30
View File
@@ -1,30 +0,0 @@
/* @flow */
"use strict";
const express = require("express");
const app = express();
app.use((req, res, next) => {
console.log("Logger... ", new Date(), req.method, req.path);
next();
});
app.use((req, res, next) => {
if (req.method === "DELETE") {
next(new Error("DELETEs are not accepted!"));
} else {
res.send("Server alive, with Express!");
}
});
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
console.error("Error....", err.message);
res.status(500).send("INTERNAL SERVER ERROR");
});
app.listen(8080, () =>
console.log(
"Mini server (with Express) ready at http://localhost:8080/!"
)
);
-20
View File
@@ -1,20 +0,0 @@
/* @flow */
"use strict";
const mariaSQL = require("mariasql");
const { promisify } = require("util");
const DB_HOST = "127.0.0.1";
const DB_USER = "fkereki";
const DB_PASS = "modernJS!!";
const DB_SCHEMA = "world";
const getDbConnection = (host, user, password, db) => {
const dbConn = new mariaSQL({ host, user, password, db });
dbConn.query = promisify(dbConn.query);
return dbConn;
};
const dbConn = getDbConnection(DB_HOST, DB_USER, DB_PASS, DB_SCHEMA);
module.exports = dbConn;
-182
View File
@@ -1,182 +0,0 @@
/* @flow */
"use strict";
const getRegion = async (
res: any,
dbConn: any,
country: ?string,
region: ?string
) => {
try {
let sqlQuery = "";
if (country == null) {
sqlQuery = `
SELECT rr.*
FROM regions rr
JOIN countries cc
ON cc.countryCode=rr.countryCode
ORDER BY cc.countryCode, rr.regionCode
`;
} else if (region == null) {
sqlQuery = `
SELECT 1
FROM countries
WHERE countryCode="${country}"
`;
const countries = await dbConn.query(sqlQuery);
if (countries.length === 0) {
return res.status(404).send("Country not found");
}
sqlQuery = `
SELECT rr.*
FROM regions rr
JOIN countries cc
ON cc.countryCode=rr.countryCode
WHERE rr.countryCode="${country}"
ORDER BY rr.regionCode
`;
} else {
sqlQuery = `
SELECT rr.*
FROM regions rr
JOIN countries cc
ON cc.countryCode=rr.countryCode
WHERE rr.countryCode="${country}"
AND rr.regionCode="${region}"
`;
}
const regions = await dbConn.query(sqlQuery);
if (regions.length > 0 || region === null) {
res
.status(200)
.set("Content-Type", "application/json")
.send(JSON.stringify(regions));
} else {
res.status(404).send("Not found");
}
} catch (e) {
res.status(500).send("Server error");
}
};
const deleteRegion = async (
res: any,
dbConn: any,
country: string,
region: string
) => {
try {
const sqlCities = `
SELECT 1 FROM cities
WHERE countryCode="${country}"
AND regionCode="${region}"
LIMIT 1
`;
const cities = await dbConn.query(sqlCities);
if (cities.length > 0) {
res.status(405).send("Cannot delete a region with cities");
} else {
const deleteRegion = `
DELETE FROM regions
WHERE countryCode="${country}"
AND regionCode="${region}"
`;
const result = await dbConn.query(deleteRegion);
if (result.info.affectedRows > 0) {
res.status(204).send();
} else {
res.status(404).send("Region not found");
}
}
} catch (e) {
res.status(500).send("Server error");
}
};
const postRegion = async (
res: any,
dbConn: any,
country: string,
name: string
) => {
if (!name) {
return res.status(400).send("Missing name");
}
try {
const sqlCountry = `
SELECT 1
FROM countries
WHERE countryCode="${country}"
`;
const countries = await dbConn.query(sqlCountry);
if (countries.length === 0) {
res.status(403).send("Country must exist");
}
const sqlGetId = `
SELECT MAX(CAST(regionCode AS INTEGER)) AS maxr
FROM regions
WHERE countryCode="${country}"
`;
const regions = await dbConn.query(sqlGetId);
const newId =
regions.length === 0 ? 1 : 1 + Number(regions[0].maxr);
const sqlAddRegion = `
INSERT INTO regions SET
countryCode="${country}",
regionCode="${newId}",
regionName="${name}"
`;
const result = await dbConn.query(sqlAddRegion);
if (result.info.affectedRows > 0) {
res
.status(201)
.header("Location", `/regions/${country}/${newId}`)
.send("Region created");
} else {
res.status(409).send("Region not created");
}
} catch (e) {
res.status(500).send("Server error");
}
};
const putRegion = async (
res: any,
dbConn: any,
country: string,
region: string,
name: string
) => {
if (!name) {
return res.status(400).send("Missing name");
}
try {
const sqlUpdateRegion = `
UPDATE regions
SET regionName="${name}"
WHERE countryCode="${country}"
AND regionCode="${region}"
`;
const result = await dbConn.query(sqlUpdateRegion);
if (result.info.affectedRows > 0) {
res.status(204).send();
} else {
res.status(409).send("Region not updated");
}
} catch (e) {
res.status(500).send("Server error");
}
};
module.exports = { getRegion, deleteRegion, postRegion, putRegion };
-87
View File
@@ -1,87 +0,0 @@
/* @flow */
"use strict";
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const dbConn = require("./restful_db.js");
app.get("/", (req, res) => res.send("Secure server!"));
/*
Add here the logic for CORS
const cors = require("cors");
app.use(cors());
*/
app.use(bodyParser.urlencoded({ extended: false }));
/*
Add here the logic for providing a JWT at /gettoken
and the logic for validating a JWT, as shown earlier
*/
const {
getRegion,
deleteRegion,
postRegion,
putRegion
} = require("./restful_regions.js");
app.get("/regions/", (req, res) => getRegion(res, dbConn));
app.get(
"/regions/:country/",
(req, res) => (
console.log(req), getRegion(res, dbConn, req.params.country)
)
);
app.get("/regions/:country/:region/", (req, res) =>
getRegion(res, dbConn, req.params.country, req.params.region)
);
app.delete("/regions/:country/:region", (req, res) =>
deleteRegion(res, dbConn, req.params.country, req.params.region)
);
app.post("/regions/:country", (req, res) =>
postRegion(res, dbConn, req.params.country, req.body.name)
);
app.put("/regions/:country/:region", (req, res) =>
putRegion(
res,
dbConn,
req.params.country,
req.params.region,
req.body.name
)
);
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
console.error("Error....", err.message);
res.status(500).send("INTERNAL SERVER ERROR");
});
/*
Add here the logic for HTTPS
const https = require("https");
const fs = require("fs");
const path = require("path");
const keysPath = path.join(__dirname, "../../certificates");
const ca = fs.readFileSync(`${keysPath}/modernjsbook.csr`);
const cert = fs.readFileSync(`${keysPath}/modernjsbook.crt`);
const key = fs.readFileSync(`${keysPath}/modernjsbook.key`);
https.createServer({ ca, cert, key }, app).listen(8443);
and remove the following line if HTTPS is used
*/
app.listen(8080, () =>
console.log("Routing ready at http://localhost:8080")
);
-23
View File
@@ -1,23 +0,0 @@
/* @flow */
"use strict";
/*
In real life, validateUser could check a database,
look into an Active Directory, call another service,
etc. -- but for this demo, let's keep it quite
simple and only accept a single hardcoded user.
*/
const validateUser = (
userName: string,
password: string,
callback: (?string, ?string) => void
) => {
if (userName === "fkereki" && password === "modernjsbook") {
callback(null, "fkereki"); // OK, send userName back
} else {
callback("Not valid user", null);
}
};
module.exports = validateUser;
+66
View File
@@ -0,0 +1,66 @@
/* @flow */
"use strict";
const express = require("express");
const app = express();
const winston = require("winston");
const logger = winston.createLogger({
level: "info",
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize({ all: true }),
winston.format.label({ label: "w_s" }),
winston.format.timestamp(),
winston.format.printf(
msg =>
`${msg.timestamp} [${msg.label}] ${msg.level} ${
msg.message
}`
)
)
}),
new winston.transports.File({
filename: "w_s_error.txt.log",
level: "error",
format: winston.format.combine(
winston.format.timestamp(),
winston.format.printf(
msg => `${msg.timestamp} ${msg.level} ${msg.message}`
)
)
}),
new winston.transports.File({
filename: "w_s_error.json.log",
level: "error"
})
]
});
logger.level = "debug";
logger.error("This is an error");
logger.info("This is an info");
logger.warn("This is a warning");
logger.debug("This is debugging info");
app.get("/", (req, res) => {
logger.info("Request for root /");
res.send("Winston server!");
});
app.get("*", (req, res) => {
logger.error(`UNKNOWN ROUTE ${req.originalUrl}`);
res.status(404).send("NOT FOUND");
});
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
logger.error(`GENERAL ERROR ${err.message}`);
res.status(500).send("INTERNAL SERVER ERROR");
});
app.listen(8081, () => logger.info("Ready at http://localhost:8080"));