https://github.com/zimbatm/u-log
U::Log - a different take on logging
https://github.com/zimbatm/u-log
Last synced: 5 months ago
JSON representation
U::Log - a different take on logging
- Host: GitHub
- URL: https://github.com/zimbatm/u-log
- Owner: zimbatm
- Created: 2014-05-12T11:21:23.000Z (about 12 years ago)
- Default Branch: master
- Last Pushed: 2023-12-15T17:53:13.000Z (over 2 years ago)
- Last Synced: 2025-12-16T17:29:13.974Z (6 months ago)
- Language: Ruby
- Homepage: http://www.rubydoc.info/gems/u-log/
- Size: 18.6 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
U::Log - a different take on logging
====================================
[](https://travis-ci.org/zimbatm/u-log)
An oppinionated logging library.
* Log everything in development AND production.
* Logs should be easy to read, grep and parse.
* Logging something should never fail.
* Let the system handle the storage. Write to syslog or STDERR.
* No log levels necessary. Just log whatever you want.
STATUS: ALPHA
=============
Doc is still scarce so it's quite hard to get started. I think reading the
lib/u-log.rb should give a good idea of the capabilities.
It would be nice to expose a method that resolves a context into a hash. It's
useful to share the context with other tools like an error reporter. Btw,
Sentry/Raven is great.
Quick intro
-----------
```ruby
require 'u-log'
# Setups the outputs. IO and Syslog are supported.
l = U::Log.new(
output: $stderr,
format: Lines,
context: {
at: ->{ Time.now.utc },
pid: ->{ Process.pid },
},
)
# First example
l.log(foo: 'bar') # logs: at=2013-07-14T14:19:28Z foo=bar
# If not a hash, the argument is transformed. A second argument is accepted as
# a hash
l.log("Hey", count: 3) # logs: at=2013-07-14T14:19:28Z msg=Hey count=3
# You can also keep a context
class MyClass < ActiveRecord::Base
attr_reader :logger
def initialize(logger)
@logger = logger.context(my_class_id: self.id)
end
def do_something
logger.log("Something happened")
# logs: at=2013-07-14T14:19:28Z msg='Something happeend' my_class_id: 2324
end
end
```
Features
--------
* Simple to use
* Thread safe (if IO#write is)
* Designed to not raise exceptions (unless it's an IO issue)
* A backward-compatible Logger is provided in case you want to retrofit
* require "u-log/active_record" for sane ActiveRecord logs
* "u-log/rack_logger" is a logging middleware for Rack
Known issues
------------
Syslog seems to truncate lines longer than 2056 chars and Lines makes if very
easy to put too much data.
Lines logging speed is reasonable but it could be faster. It writes at around
5000 lines per second to Syslog on my machine.
Protocols
---------
`U::Log::Logger` is governed by a couple of protocols that help keep the
library composable.
The first constructor argument is an output. An output object is any object
that accepts a method call `#<<` with a single String argument. No output is
expected. The `#<<` method should be thread-safe is multi-threading is
expected.
The second contructor argument is a data formatter. It used the same protocol
as Marshal and JSON where a `#dump` method is expected which accepts a ruby
Hash and returns a String. The formatter should not raise any exception but
instead transform faulty data in a readable output.
Conventions
-----------
While underscore (`_`) is commonly used to separate `CamelCase` modules to
`camel_case.rb` file-names, no convention exists when a while library is
prefixed by a global namespace. That's why I am taking the dash (`-`)
character for it so that `U::Log` maps to `u-log.rb`.
The `U` namespace is my prefix for very small and composable modules.
Inspired by
-----------
* Scrolls : https://github.com/asenchi/scrolls
* Lograge : https://github.com/roidrage/lograge
TODO
----
* Don't automatically install the logger when requiring u-log/active_record
* Provide logging for all of rails
* Integrate with Error reporting
* Integrate with metrics collection
* include U::Log to add a #log method in an object
I have to think about how log lines are going to be indexed. One issue I
encountered on the ELK stack is that JSON events can create an unknown number
of indexec when dumped directly into ElasticSearch, because the keys in each
event might vary depending on which source line has produced it.
What could be interesting is to extract only metrics. Let's say we select a
key format convention where all keys starting with `metrics.` are considered
of holding a numeric value. The all the other keys are just stored alongside
but not indexed. If we want to add more dimensions to the metrics then more
select keys are added as index, selectively. Let's say "pid", "hostname" and
"ts" for example.