-
Notifications
You must be signed in to change notification settings - Fork 647
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementing logging #7
Comments
Create an adapter that wraps some framework and then inject it into your use case. On a brand new project I usually start by wrapping the // logger/logger.js
export default function makeLogger(spec) {
return Object.freeze({
debug: console.debug,
error: console.error,
info: console.info,
warn: console.warn
})
} // logger/index.js
import logger from './logger'
const logger = makeLogger()
export default logger |
Hm, I'd pass some kind of argument to allow a prefix. You could use loglevel or winston for example. |
There are many ways to extend/improve on the basic example I provided. It really depends on the needs of your application. The main point is, use an adapter and injection to avoid a direct dependency on a specific logging library. Logging is something that will get used everywhere so you have to be very careful about directly referencing a particular 3rd party library all over your code. |
Could you provide an example with singleton logger that uses 3rd party library like Bunyan? |
@PixsaOJ it might look something like this... // /logger/logger.js
export function makeLogger({thirdPartyLogger}) {
return Object.freeze({
info: (msg) => thirdPartyLogger.info(msg) // you should do more here (e.g. wrap proprietary errors).
// more method wrappers like .warn or .error
})
} // /logger/index.js
import ThirdPartyLogger from "third-party-logger" // this could be Bunyan
import {makeLogger} from "./logger"
const thirdPartyLogger = new ThirdPartyLogger({/* config */})
export const Logger = makeLogger({thirdPartyLogger}) // here's your singleton Now the rest of your app uses the logger exported from /logger/index.js and if you ever want or need to switch logging libraries you have one place to do it. |
Thanks for the response @arcdev1. What do you think, would it be a good idea to use our generated logger as dependency injection? Or just require/import it whenever we need to log. E.g. when we are writing tests, it could be easier to inject as dependency. However, I do not know how pretty it would be to that in actual code. I would have to inject in routes first, then in controllers, then in use-cases... EDIT: I currently have it as a global variable |
@PixsaOJ Logging tends to have side effects (e.g. writing to a file) so it's important to use dependency injection to avoid brittle tests. Reading between the lines of your question, it seems like you are logging in lots of places. If you find that you get a lot of value from doing that then it's all good. In my case, I've noticed that limiting logs to an exception handler seems to be enough. So, at the entry point(s) of my app, I have a single try/catch that sends Exceptions to an Exception Handler which logs the exception and makes some decisions about what else to do with the Exception based on its type. This means I only really have to inject the Logger in my Exception Handler. I've worked for clients that like to log a lot more than that and in those cases, we just accepted that you have to inject your logger everywhere. |
@arcdev1 Makes sense, thank you. |
Hi, how do we go about implementing logging? Do we just import a logger function anywhere in our use cases or pass it down from the frameworks & drivers layer?
The text was updated successfully, but these errors were encountered: