Live data from Hacker News

Log level 'error' should mean that something needs to be fixed

utcc.utoronto.ca

211–220 of 313 posts

Re: Log level 'error' should mean that something needs to be fixed

#211

Input errors do not need fixing, so no.

If they cause your customers to ditch your product but calling them and saying "your calls are all getting 4xx because you are not putting the state code into the call parameters" would keep them as customers, then you would be wise to make that communication.

Re: Log level 'error' should mean that something needs to be fixed

#212
post #92
post #76

> When implementing logging, it's important to distinguish between an error from the perspective of an individual operation and an error from the perspective of the overall program or system. Individual operations may well experience errors that are not error level log events for the overall program. You could say that an operation error is anything that prevents an operation from completing successfully, while a pro…

This is why it’s almost always wrong for library functions to log anything, even on ”errors”. Pass the status up through return values or exceptions. As a library author you have no clue as how an application might use it. Multi threading, retry loops and expected failures will turn what’s a significant event in one context into what’s not even worthy of a debug log in another. No rule without exceptions of course, o…

It may be unwise to log errors at low layers but logging informational and debug messages are useful (at least, when the caller enables them).

Re: Log level 'error' should mean that something needs to be fixed

#213
post #26

Earlier quoted context omitted.

> the database is owned by a separate oncall rotation Not OP, but this part hits the same for me. In the case your client app is killing the DB through too many calls (e.g. your cache is not working) you should be able to detect it and react, without waiting for the DB team to come to you after they investigated the whole thing. But you can't know in advance if the DB connection errors are your fault or not, so loggi…

I agree that you should detect this, just through a metric rather than putting DB timeouts in the ERROR loglevel.

But what's the base of your metric ?

I feel you're thinking about system wide downtime with everything timing out consistently, which would be detected by the generic database server vitals and basic logs.

But what if the timeouts are sparse and only 10 or 20% more than usual from the DB POV, but it affects half of your registration services' requests ? You need it logged application side so the aggregation layer has any chance of catching it.

On writing to ERROR or not, the hresholds should be whatever your dev and oncall teams decides. Nobody outside of them will care, I feel it's like arguing which drawer the socks should go.

I was in an org where any single error below CRITICAL was ignored by the oncall team , and everything below that only triggered alerts on aggregation or special conditions. Pragmatically, we ended up slicing it as ERROR=goes to the APM, anything below=no aggregation, just available when a human wants to look at it for whatever reason. I'd expect most orgs to come with that kind of split, where the levels are hooked to processes, and not some base meaning.

Re: Log level 'error' should mean that something needs to be fixed

#214

Earlier quoted context omitted.

How about wrapping the log.trace param in a lambda and monkeypatching log.trace to take a function that returns a string, and of course pushing the conditional to the monkeypatched func.

Then you still have the overhead of the log.trace function call and the lambda construction (which is not cheap because it has closure over the params being logged and is passed as a param to a function call, so probably gets allocated on the heap)

>Then you still have the overhead of the log.trace function call

That's not an overhead at all. Even if it were it's not compareable to string concatenation.

Regarding overhead of lambda and copying params. Depends on the language, but usually strings are pass by ref and pass by values are just 1 word long, so we are talking one cycle per variable and 8 bytes of memory. Which were already paid anyways.

That said, logging functions that just take a list of vars are even better, like python's print()

> printtrace("var x and y",x,y)

> def printtrace(*kwargs):

>> print(kwargs) if trace else None

Python gets a lot of slack for being a slow language, but you get so much expressiveness that you can invest in optimization after paying a flat cycle cost.

Re: Log level 'error' should mean that something needs to be fixed

#215
post #170

Earlier quoted context omitted.

You can log your IO and as long as your functions are idempotent that should be enough info to replicate.

Assuming everything is idempotent is a tall order. There are a lot of libraries that haven non-idempotent actions. There are a lot of inputs that can be problematic to log, too.

Say like opening a file?

I guess in those cases standard practice is for lib to return a detailed error yeah.

As far as traces, trying to solve issues that depend on external systems is indeed a tall order for your code. Isn't it beyond the scope of the thing being programmed.

Re: Log level 'error' should mean that something needs to be fixed

#216

Earlier quoted context omitted.

That is why the popular `tracing` crate in Rust uses macros for logging instead of functions. If the log level is too low, it doesn't evaluate the body of the macro

Does that mean the log level is a compilation parameter? Ideally, log levels shouldn't even be startup parameters, they should be changeable on the fly, at least for any server side code. Having to restart if bad enough, having to recompile to get debug logs would be an extraordinary nightmare (not only do you need to get your customers to reproduce the issue with debug logs, you actually have to ship them new binari…

I know this is standard practice, but I personally think it's more professional to attach a gdb like debugger to a process instead of depending on coded log statements.

Re: Log level 'error' should mean that something needs to be fixed

#217
post #76

> When implementing logging, it's important to distinguish between an error from the perspective of an individual operation and an error from the perspective of the overall program or system. Individual operations may well experience errors that are not error level log events for the overall program. You could say that an operation error is anything that prevents an operation from completing successfully, while a pro…

I've been thinking about this all day. I think the best approach is probably twofold:

1) Thrown errors should track the original error to retain its context. In JavaScript errors have a `cause` option which is perfect for this. You can use the `cause` to hold a deep stack trace even if the error has been handled and wrapped in a different error type that may have a different semantics in the application.

2) For logging that does not stop program execution, I think this is a great case for dependency injection. If a library allows its consumer to provide a logger, the application has complete control over how and when the library logs, and can even change it at runtime. If you have a disagreement with a library, for example it logs errors that you want to treat as warnings, your injected logger can handle that.

Re: Log level 'error' should mean that something needs to be fixed

#218

I just started playing in the Erlang ecosystem and they have EIGHT levels of logging messages. it seems crazily over-specific, but they are the champions of robust systems. I could live with 4 Error - alert me now. Warning - examine these later, Info - important context for investigations. Debug - usually off in prod.

I need Notice (between Info and Warning), for important events such as start and shutdown, and successfully connecting to the database, and ready to start serving. These otherwise would be in Info; and enabling Info level produces a torrent of uninteresting muck.

Re: Log level 'error' should mean that something needs to be fixed

#219

Earlier quoted context omitted.

Depending on the language and logging framework, debug/trace logging can be acceptable in a library. But you have to be extra careful to make sure that it's ultimately a no-op. A common problem in Java is someone will drop a log that looks something like this `log.trace("Doing " + foo + " to " + bar);` The problem is, especially in a hot loop, that throw away string concatenation can ultimately be a performance probl…

Ideally a logging library should at least not make it easy to make that kind of mistake.

This isn't really something the logging library can do. If the language provides a string interpolation mechanism then that mechanism is what the programmers will reach for first. And the library cannot know that interpolation happened because the language creates the final string before passing it in.

If you want the builtin interpolation to become a noop in the face runtime log disabling then the logging library has to be a builtin too.

Re: Log level 'error' should mean that something needs to be fixed

#220
post #76

> When implementing logging, it's important to distinguish between an error from the perspective of an individual operation and an error from the perspective of the overall program or system. Individual operations may well experience errors that are not error level log events for the overall program. You could say that an operation error is anything that prevents an operation from completing successfully, while a pro…

> Should only “top-level” code ever log an error? That can make it difficult to identify the low-level root causes of a top-level failure. Some languages (e.g. Java) include a stack trace when reporting an error, which is extremely useful when logging the error. It shows at exactly which point in the code the error was generated, and what the full call stack was to get there. It's a real shame that "modern" languages…

The idiomatic practice in Go for libraries is to wrap returned errors and errors can be unwrapped with stdlib tooling. This is more useful to handle errors at runtime than digging into a stack trace.
Post reply on HN