Podcast: Play in new window | Download (20.8MB)
Panel
- Avdi Grimm
- Charles Max Wood
- James Edward Gray
- Tim Pease
Discussed in this Episode
- Any message of note generated by your application
- A message of note is something the conveys meaning or has importance to the developer
- Log4J
- Debugging
- “puts” debugging
- Debuggers
- puts
- Scroll blindness
- grep
- log levels
- logging
- log appenders
- Each object can have its own logger
- Set interesting classes to debug and everything else to info or warn
- Global loggers
- Do the simplest thing you need until it no longer works for you
- Set up rolling file appenders
- Ruby’s core Logger class
- logrotate
- shared file locks
- exclusive file locks
- rotation notation by number or by date
- copy then truncate when rotating logs – maintains the file reference
- signal to change log level to debug
- Only send FATAL messages when I’m about to kill the program
- An ERROR is “something bad has happened, but I can work around it”
- WARN – “this problem occurred”
- INFO – “the program is still running. I’m doing this and this and this.”
- DEBUG – “information on where things might be going wrong.”
- You should be between every other line being a log message and having no logging
- We like seeing the SQL in the Rails logs.
- Track interactions and requests to other services
- Log formatting
- Never create your date stamp format. EVER. EVER!
- ISO8601 Datestamp format standard
- Format messages for the consumer. Pretty printed for users. JSON for software.
- Splunk
- Newlines in log messages?
- Log context (to keep track of where you are in the application)
- Include the process id (PID) in forked applications
- How do you group messages related to the same request?
- SASS
- How do you deal with logs from different applications in different formats?
- SLF4J
- Where should I log to? A flat file? database? Twitter?
- syslog
- servolux
Picks
- repl.it (Avdi)
- screenr.com (Avdi)
- Freakonomics Radio (James)
- RadioLab (James)
- Apache Kafka (Tim)
- Community and Thanking People (Tim)
- Knowing your tools (Chuck)
- Linux (Chuck)
- Bash Shell (Chuck)







I have recently put together some material related to logging. Streams of Data Part I - logging basics video: http://vimeo.com/30931422 notes: https://gist.github.com/1305172 Part II - event streams slide deck: http://dl.dropbox.com/u/1579953/talks/streams_of_data_2.pdf
Oh, look, the previous commenter suggested that as well. (=
Haven't finished listening to the episode yet, but someone asked a question about how to trace log messages related to one specific request, when you might have several Rails processes writing to the same file. Coincidentally, I was just listening to a Pivotal Labs tech talk the other day ("Magic Scaling Sprinkles", link) where Nick Kallen suggests generating a GUID for each request that comes in from outside, and then passing it around with every message. His point was that, as you start doing more SOA-type stuff, it's really hard to associate all the different little bits of work that got done to service one request; having a GUID gives you something to tie all that stuff together with. However, that could help in a Rails-only scenario as well. (Another thought: in a SOA environment, it might be desirable to have an appender that shoves messages on a queue or a pub/sub topic.)
Log levels should die in the horrible death they deserve. Here is my death sentence to them: 1. Don't use logs to display the state/performance of your program. Replace all those logs by application metrics. See https://github.com/johnewart/ruby-metrics . 2. Don't use logs to display application errors. Replace all those logs by an external notification system like airbrake (no, not email!) 3. Don't use logs to verify the correct execution of your code. Use unit tests, introduce #assert checks in your code and use #fail for execution paths that should not happen. By now, the remaining logs should all be trails of interaction with external services (SQL, HTTP, ...). If anything else, I'm curious to hear about them :) . Put them all on LOG_INFO level. Done. Bonus for HTTP services: create a rack adapter that creates a unique ID for each request and insert it in all log message with the PID of the process of the whole request/response round-trip. Bonus 2: instead of interpolating the values in your log message, create a log function that keeps the argument separated. You can always put them together later if a human needs to read them. In the mean time, you can also build tools more elaborate than grep to analyze them. Example: log("http request from {source_ip}, ...", :source_ip => env["X_REQUESTED_WITH"])