From d6a402252872e1b1dc2ef4b3213732e4cce5ea71 Mon Sep 17 00:00:00 2001 From: Alex Mikhalev Date: Tue, 26 Sep 2017 12:43:25 -0600 Subject: [PATCH] Added pino logging --- app/state/index.ts | 2 +- package.json | 4 ++ server/app/serveApp.ts | 17 +++--- server/index.ts | 3 +- server/log.ts | 5 ++ server/logging/pino.d.ts | 22 +++++++ server/logging/prettyPrint.ts | 111 ++++++++++++++++++++++++++++++++++ server/tsconfig.json | 4 +- yarn.lock | 88 +++++++++++++++++++++++---- 9 files changed, 231 insertions(+), 25 deletions(-) create mode 100644 server/log.ts create mode 100644 server/logging/pino.d.ts create mode 100644 server/logging/prettyPrint.ts diff --git a/app/state/index.ts b/app/state/index.ts index a4708d2..ea0e2a0 100644 --- a/app/state/index.ts +++ b/app/state/index.ts @@ -1,5 +1,5 @@ import { MqttApiClient } from "@app/mqtt"; -import { ISprinklersApi, SprinklersDevice } from "@common/sprinklers"; +import { ISprinklersApi } from "@common/sprinklers"; import { UiMessage, UiStore } from "./ui"; export { UiMessage, UiStore }; diff --git a/package.json b/package.json index 9c26878..a0546fd 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "watch:server": "yarn build:server --watch", "start:dev-server": "webpack-dev-server --config ./app/webpack/dev.config.js", "start": "node dist/index.js", + "start:pretty": "yarn start | node dist/logging/prettyPrint.js", "lint:app": "tslint --project app --force --format verbose", "lint:server": "tslint --project server --force --format verbose", "lint": "run-p lint:*" @@ -27,12 +28,14 @@ }, "homepage": "https://github.com/amikhalev/sprinklers3#readme", "dependencies": { + "@types/chalk": "^0.4.31", "@types/classnames": "^2.2.0", "@types/core-js": "^0.9.43", "@types/express": "^4.0.37", "@types/node": "^8.0.6", "@types/object-assign": "^4.0.30", "@types/paho-mqtt": "^1.0.0", + "@types/pino": "^4.7.0", "@types/prop-types": "^15.5.1", "@types/react": "^16", "@types/react-dom": "^15.5.0", @@ -47,6 +50,7 @@ "mobx-react": "^4.2.1", "object-assign": "^4.1.1", "paho-mqtt": "^1.0.3", + "pino": "^4.7.2", "prop-types": "^15.5.10", "react": ">=15.6.1 <16", "react-dom": ">=15.6.1 <16", diff --git a/server/app/serveApp.ts b/server/app/serveApp.ts index 64f98f6..88398ba 100644 --- a/server/app/serveApp.ts +++ b/server/app/serveApp.ts @@ -3,28 +3,25 @@ import * as webpack from "webpack"; import * as webpackMiddleware from "webpack-dev-middleware"; import * as webpackHotMiddleware from "webpack-hot-middleware"; +import logger from "../log"; +const log = logger.child({ source: "webpack" }); + /* tslint:disable-next-line:no-var-requires */ const webpackConfig = require("../../app/webpack/config.js"); -type Logger = (message?: any, ...optionalParams: any[]) => void; - -function makeLogFunction(fn: Logger = console.log): Logger { - return (m, ...args) => fn("[webpack] " + m, ...args); -} - export default function serveApp(app: Express) { const compiler = webpack(webpackConfig); app.use(webpackMiddleware(compiler, { noInfo: true, publicPath: webpackConfig.output.publicPath, - log: makeLogFunction(), - warn: makeLogFunction(console.warn), - error: makeLogFunction(console.error), + log: log.info.bind(log), + warn: log.warn.bind(log), + error: log.error.bind(log), }, )); app.use(webpackHotMiddleware(compiler, { - log: makeLogFunction(), + log: log.info.bind(log), })); } diff --git a/server/index.ts b/server/index.ts index 1a7fafc..76c220f 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,5 +1,6 @@ import { Server } from "http"; import app from "./app"; +import log from "./log"; const server = new Server(app); @@ -7,5 +8,5 @@ const port = +(process.env.PORT || 8080); const host = process.env.HOST || "0.0.0.0"; server.listen(port, host, () => { - console.log(`listening at ${host}:${port}`); + log.info(`listening at ${host}:${port}`); }); diff --git a/server/log.ts b/server/log.ts new file mode 100644 index 0000000..233d383 --- /dev/null +++ b/server/log.ts @@ -0,0 +1,5 @@ +import * as pino from "pino"; + +const log = pino(); + +export default log; diff --git a/server/logging/pino.d.ts b/server/logging/pino.d.ts new file mode 100644 index 0000000..2dc005e --- /dev/null +++ b/server/logging/pino.d.ts @@ -0,0 +1,22 @@ +declare module "pino/pretty" { + import { Transform } from "stream"; + + interface Formatter { + (value: any): string; + } + + interface PrettyOptions { + timeTransOnly?: boolean; + formatter?: Formatter; + levelFirst?: boolean; + messageKey?: string; + forceColor?: boolean; + } + + interface Pretty { + (opts: PrettyOptions): Transform; + } + + const pretty: Pretty; + export = pretty; +} diff --git a/server/logging/prettyPrint.ts b/server/logging/prettyPrint.ts new file mode 100644 index 0000000..1932cab --- /dev/null +++ b/server/logging/prettyPrint.ts @@ -0,0 +1,111 @@ +import * as chalk from "chalk"; + +import pretty = require("pino/pretty"); + +type Level = "default" | 60 | 50 | 40 | 30 | 20 | 10; + +const levels = { + default: "USERLVL", + 60: "FATAL", + 50: "ERROR", + 40: "WARN", + 30: "INFO", + 20: "DEBUG", + 10: "TRACE", +}; + +const levelColors = { + default: chalk.white.underline, + 60: chalk.bgRed.underline, + 50: chalk.red.underline, + 40: chalk.yellow.underline, + 30: chalk.green.underline, + 20: chalk.blue.underline, + 10: chalk.grey.underline, +}; + +const standardKeys = ["pid", "hostname", "name", "level", "time", "v", "source", "msg"]; + +function formatter(value: any) { + let line = formatTime(value, " "); + line += formatSource(value); + line += asColoredLevel(value); + + // line += " ("; + // if (value.name) { + // line += value.name + "/"; + // } + // line += value.pid + " on " + value.hostname + ")"; + + line += ": "; + if (value.msg) { + line += chalk.cyan(value.msg); + } + line += "\n"; + if (value.type === "Error") { + line += " " + withSpaces(value.stack) + "\n"; + } else { + line += filter(value); + } + return line; +} + +function withSpaces(value: string): string { + const lines = value.split("\n"); + for (let i = 1; i < lines.length; i++) { + lines[i] = " " + lines[i]; + } + return lines.join("\n"); +} + +function filter(value: any) { + const keys = Object.keys(value); + const filteredKeys = standardKeys; + let result = ""; + + for (const key of keys) { + if (filteredKeys.indexOf(key) < 0) { + result += " " + key + ": " + withSpaces(JSON.stringify(value[key], null, 2)) + "\n"; + } + } + + return result; +} + +function asISODate(time: string) { + return new Date(time).toISOString(); +} + +function formatTime(value: any, after?: string) { + after = after || ""; + try { + if (!value || !value.time) { + return ""; + } else { + return "[" + asISODate(value.time) + "]" + after; + } + } catch (_) { + return ""; + } +} + +function formatSource(value: any) { + if (value.source) { + return chalk.magenta("(" + value.source + ") "); + } else { + return ""; + } +} + +function asColoredLevel(value: any) { + const level = value.level as Level; + if (levelColors.hasOwnProperty(level)) { + return levelColors[level](levels[level]); + } else { + return levelColors.default(levels.default); + } +} + +process.stdin.pipe(pretty({ + formatter, +})).pipe(process.stdout); diff --git a/server/tsconfig.json b/server/tsconfig.json index de6c9e4..e148ab3 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -14,7 +14,7 @@ ], "strict": true }, - "files": [ - "./index.ts" + "include": [ + "./**/*.ts" ] } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 1bb3883..4a8af6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,10 @@ # yarn lockfile v1 +"@types/chalk@^0.4.31": + version "0.4.31" + resolved "https://registry.yarnpkg.com/@types/chalk/-/chalk-0.4.31.tgz#a31d74241a6b1edbb973cf36d97a2896834a51f9" + "@types/classnames@^2.2.0": version "2.2.3" resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.3.tgz#3f0ff6873da793870e20a260cada55982f38a9e5" @@ -38,8 +42,8 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.27.tgz#13fbe7e92afeecebb843d7cea6c15b521e0000e1" "@types/node@^8.0.6": - version "8.0.28" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.28.tgz#86206716f8d9251cf41692e384264cbd7058ad60" + version "8.0.30" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.30.tgz#aa3c42946fc6357737eb215349fe728b38679d05" "@types/object-assign@^4.0.30": version "4.0.30" @@ -49,6 +53,12 @@ version "1.0.0" resolved "https://registry.yarnpkg.com/@types/paho-mqtt/-/paho-mqtt-1.0.0.tgz#9dc7d4d98dac7940187f6ccb77aab649249d0799" +"@types/pino@^4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@types/pino/-/pino-4.7.0.tgz#c95790496a82766a1b41050df9b322fe9639a129" + dependencies: + "@types/node" "*" + "@types/prop-types@^15.5.1": version "15.5.1" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.1.tgz#1ecf52621299e65b855374337fb11fd2d1066fc1" @@ -1309,6 +1319,12 @@ encoding@^0.1.11: dependencies: iconv-lite "~0.4.13" +end-of-stream@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" + dependencies: + once "^1.4.0" + enhanced-resolve@3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.3.0.tgz#950964ecc7f0332a42321b673b38dc8ff15535b3" @@ -1605,6 +1621,14 @@ fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" +fast-json-parse@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" + +fast-safe-stringify@^1.0.8, fast-safe-stringify@^1.1.11: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-1.2.0.tgz#ebd42666fd18fe4f2ba4f0d295065f3f85cade96" + fastparse@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" @@ -1687,6 +1711,10 @@ find-up@^2.0.0: dependencies: locate-path "^2.0.0" +flatstr@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.5.tgz#5b451b08cbd48e2eac54a2bbe0bf46165aa14be3" + flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" @@ -2715,14 +2743,14 @@ mobx-react-devtools@^4.2.13: resolved "https://registry.yarnpkg.com/mobx-react-devtools/-/mobx-react-devtools-4.2.15.tgz#881c038fb83db4dffd1e72bbaf5374d26b2fdebb" mobx-react@^4.2.1: - version "4.2.2" - resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-4.2.2.tgz#db9cc3cafefbd830d0584c1149af5aae67829201" + version "4.3.2" + resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-4.3.2.tgz#1ecbffa5690cc6460db6bb16c0c11034f0b783da" dependencies: hoist-non-react-statics "^1.2.0" mobx@^3.1.11: - version "3.2.2" - resolved "https://registry.yarnpkg.com/mobx/-/mobx-3.2.2.tgz#aa671459bededfd9880c948889a3f62bce09279c" + version "3.3.0" + resolved "https://registry.yarnpkg.com/mobx/-/mobx-3.3.0.tgz#1bc1dd7e78547065af04b49bdb7f2098cada47aa" ms@2.0.0: version "2.0.0" @@ -2960,7 +2988,7 @@ on-headers@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" -once@^1.3.0, once@^1.3.3: +once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: @@ -3162,6 +3190,18 @@ pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" +pino@^4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/pino/-/pino-4.7.2.tgz#56e8e712637669095f0a61b27a15649d62dec8cd" + dependencies: + chalk "^2.0.1" + fast-json-parse "^1.0.0" + fast-safe-stringify "^1.1.11" + flatstr "^1.0.4" + pump "^1.0.2" + quick-format-unescaped "^1.1.1" + split2 "^2.0.1" + portfinder@^1.0.9: version "1.0.13" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9" @@ -3491,6 +3531,13 @@ public-encrypt@^4.0.0: parse-asn1 "^5.0.0" randombytes "^2.0.1" +pump@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.2.tgz#3b3ee6512f94f0e575538c17995f9f16990a5d51" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" @@ -3534,6 +3581,12 @@ querystringify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" +quick-format-unescaped@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-1.1.1.tgz#e77555ef3e66e105d4039e13ef79201284fee916" + dependencies: + fast-safe-stringify "^1.0.8" + randomatic@^1.1.3: version "1.1.7" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" @@ -3645,7 +3698,7 @@ readable-stream@1.0, readable-stream@~1.0.2: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.6, readable-stream@^2.2.9: +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.6, readable-stream@^2.2.9: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" dependencies: @@ -3857,8 +3910,8 @@ semantic-ui-css@^2.2.10: jquery x.* semantic-ui-react@^0.73.0: - version "0.73.0" - resolved "https://registry.yarnpkg.com/semantic-ui-react/-/semantic-ui-react-0.73.0.tgz#4750473a51905b52a9745765b55c05582c93efb5" + version "0.73.1" + resolved "https://registry.yarnpkg.com/semantic-ui-react/-/semantic-ui-react-0.73.1.tgz#37d6a35f6baf941f440c7543d53caf8843661cc3" dependencies: babel-runtime "^6.25.0" classnames "^2.2.5" @@ -4125,6 +4178,12 @@ split-string@^2.1.0: dependencies: extend-shallow "^2.0.1" +split2@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/split2/-/split2-2.1.1.tgz#7a1f551e176a90ecd3345f7246a0cfe175ef4fd0" + dependencies: + through2 "^2.0.2" + split@0.3: version "0.3.3" resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" @@ -4318,6 +4377,13 @@ tar@^2.2.1: fstream "^1.0.2" inherits "2" +through2@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + through@2, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -4783,7 +4849,7 @@ xml-char-classes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/xml-char-classes/-/xml-char-classes-1.0.0.tgz#64657848a20ffc5df583a42ad8a277b4512bbc4d" -xtend@^4.0.0: +xtend@^4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"