README.md in l2meter-0.12.0 vs README.md in l2meter-0.13.0

- old
+ new

@@ -1,62 +1,63 @@ # L2meter [![Gem Version](https://img.shields.io/gem/v/l2meter.svg)](https://rubygems.org/gems/l2meter) -[![Build Status](https://img.shields.io/travis/rwz/l2meter.svg)](http://travis-ci.org/rwz/l2meter) -[![Code Climate](https://img.shields.io/codeclimate/github/rwz/l2meter.svg)](https://codeclimate.com/github/rwz/l2meter) +[![Build Status](https://travis-ci.com/heroku/l2meter.svg?branch=master)](http://travis-ci.com/heroku/l2meter) -L2meter is a little gem that helps you build loggers that outputs things in -l2met-friendly format. +L2meter is a little gem for building [logfmt]-compatiable loggers. +[logfmt]: https://www.brandur.org/logfmt + ### Basics A new logger might be created like so: ```ruby -Metrics = L2meter.build +logger = L2meter.build ``` -If you plan to use it globally across different components of your app,consider -making it constant. +Consider making the logger a constant to make it easier to use across different +components of the app or globally. -The base `log` method accepts two type of things: bare values and key-value +The base `log` method accepts two type of arguments: bare values and key-value pairs in form of hashes. ```ruby -Metrics.log "Hello world" # => hello-world -Metrics.log :db_query, result: :success # => db-query result=success +logger.log "Hello world" # => hello-world +logger.log :db_query, result: :success # => db-query result=success ``` -It can also take a block. In this case the message will be emitted twice, once -at the start of the execution and another at the end. The end result might look -like so: +The method also takes a block. In this case the message will be emitted twice, +once at the start of the execution and once at the end. The end result might +look like so: ```ruby -Metrics.log :doing_work do # => doing-work at=start - do_some_work # - Metrics.log :work_done # => work-done -end # => doing-work at=finish elapsed=1.2345 +logger.log :doing_work do # => doing-work at=start + do_some_work # + logger.log :work_done # => work-done +end # => doing-work at=finish elapsed=1.2345 ``` -In case the exception is raised inside the block, l2meter will report is like -so: +In case of the exception inside the block, all relevant information is logged +and then exception is re-raised. ```ruby -Metrics.log :doing_work do # => doing-work at=start +logger.log :doing_work do # => doing-work at=start raise ArgumentError, \ # "something is wrong" # end # => doing-work at=exception exception=ArgumentError message="something is wrong" elapsed=1.2345 + # ArgumentError: something is wrong ``` ## Context L2meter allows setting context for a block. It might work something like this: ```ruby def do_work_with_retries attempt = 1 begin - Metrics.context attempt: attempt do + logger.context attempt: attempt do do_some_work # => doing-work attempt=1 # => doing-work attempt=2 # => doing-work attempt=3 end rescue => error @@ -67,164 +68,170 @@ ``` L2meter supports dynamic contexts as well. You can pass a proc instead of raw value in order to use it. -The same example as above could be re-written like this instead: +The example above could be re-written like this instead: ```ruby def do_work_with_retries attempt = 1 - Metrics.context ->{{ attempt: attempt }} do + logger.context ->{{ attempt: attempt }} do begin do_some_work rescue => error attempt +=1 retry end end end ``` -## Contexted logging +It's possbile to create a dedicated copy of the logger with some specific +context attached to it. -Sometimes you want another copy of the logger with a specific context on it. -You can create one like so: - ```ruby -logger = Metrics.context(:super_worker, username: "joe") +worker_logger = logger.context(component: :worker, worker_id: 123) -SuperWorker.new(logger: logger).run # => super-worker username=joe some-other=superworker-output +MyWorker.new(logger: worker_logger).run # => component=worker worker_id=123 status="doing work" ``` ## Batching -There's also a way to batch several calls into a single log line: +There's a way to batch several calls into a single log line: ```ruby -Metrics.batch do - Metrics.log foo: :bar - Metrics.unique :registeration, "user@example.com" - Metrics.count :thing, 10 - Metrics.sample :other_thing, 20 +logger.batch do + logger.log foo: :bar + logger.unique :registration, "user@example.com" + logger.count :thing, 10 + logger.sample :other_thing, 20 end # => foo=bar unique#registration=user@example.com count#thing=10 sample#other-thing=20 ``` -## Other +## Metrics -Some other l2met-specific methods are supported. +Some [l2met]-specific metrics are supported. +[l2met]: https://r.32k.io/l2met-introduction + ```ruby -Metrics.count :user_registered # => count#user-registered=1 -Metrics.count :registered_users, 10 # => count#registered-users=10 +logger.count :user_registered # => count#user-registered=1 +logger.count :registered_users, 10 # => count#registered-users=10 -Metrics.measure :connection_count, 20 # => measure#connection-count=20 -Metrics.measure :db_query, 235, unit: :ms, # => measure#db-query.ms=235 +logger.measure :connection_count, 20 # => measure#connection-count=20 +logger.measure :db_query, 235, unit: :ms, # => measure#db-query.ms=235 -Metrics.sample :connection_count, 20, # => sample#connection-count=235 -Metrics.sample :db_query, 235, unit: :ms, # => sample#db-query.ms=235 +logger.sample :connection_count, 20, # => sample#connection-count=235 +logger.sample :db_query, 235, unit: :ms, # => sample#db-query.ms=235 -Metrics.unique :user, "bob@example.com" # => unique#user=bob@example.com +logger.unique :user, "bob@example.com" # => unique#user=bob@example.com ``` -L2meter also allows to append elapsed time to your log messages automatically. +## Measuring Time +L2meter allows to append elapsed time to log messages automatically. + ```ruby -Metrics.with_elapsed do +logger.with_elapsed do do_work_step_1 - Metrics.log :step_1_done # => step-1-done elapsed=1.2345 + logger.log :step_1_done # => step-1-done elapsed=1.2345 do_work_step_2 - Metrics.log :step_2_done # => step-2-done elapsed=2.3456 + logger.log :step_2_done # => step-2-done elapsed=2.3456 end ``` -### Configuration +## Configuration -L2meter supports configuration. Here's how you can configure things: +L2meter supports customizable configuration. ```ruby -Metrics = L2meter.build do |config| +logger = L2meter.build do |config| # configuration happens here end ``` -Here's the list of all configurable things: +Here's the full list of available settings. -#### Global context +### Global context Global context works similary to context method, but globally: ```ruby config.context = { app_name: "my-app-name" } # ... -Metrics.log foo: :bar # => app-name=my-app-name foo=bar +logger.log foo: :bar # => app-name=my-app-name foo=bar ``` Dynamic context is also supported: ```ruby config.context do - { request_id: CurrentContext.request_id } + { request_id: SecureRandom.uuid } end + +logger.log :hello # => hello request_id=4209ba28-4a7c-40d6-af69-c2c1ddf51f19 +logger.log :world # => world request_id=b6836b1b-5710-4f5f-926d-91ab9988a7c1 ``` -#### Sorting +### Sorting By default l2meter doesn't sort tokens before output, putting them in the order -they're passed. But you can make it sorted like so: +they're passed. But it's possible to sort them like so: ```ruby config.sort = true # ... -Metrics.log :c, :b, :a # => a b c +logger.log :c, :b, :a # => a b c ``` -#### Source +### Source Source is a special parameter that'll be appended to all emitted messages. ```ruby -config.source = "production" +config.source = "com.heroku.my-application.staging" # ... -Metrics.log foo: :bar # => source=production foo=bar +logger.log foo: :bar # => source=com.heroku.my-application.staging foo=bar ``` -#### Prefix +### Prefix -Prefix allows namespacing your measure/count/unique/sample calls. +Prefix allows to add namespacing to measure/count/unique/sample calls. ```ruby config.prefix = "my-app" # ... -Metrics.count :users, 100500 # => count#my-app.users=100500 +logger.count :users, 100500 # => count#my-app.users=100500 ``` -## Scrubbing +### Scrubbing L2meter allows plugging in custom scrubbing logic that might be useful in -environments where logging compliance is important. +environments where logging compliance is important to prevent accidentally +leaking sensitive information. ```ruby -config.scrubber = ->(key, value) do +config.scrubber = -> (key, value) do begin uri = URI.parse(value) - uri.password = "scrubbed" if uri.password + uri.password = "redacted" if uri.password uri.to_s rescue URI::Error value end end -Metric.log my_url: "https://user:password@example.com" +logger.log my_url: "https://user:password@example.com" # => my-url="https://user:redacted@example.com" ``` Note that returning nil value will make l2meter omit the field completely. @@ -232,32 +239,33 @@ There's a way to temporary silence the log emitter. This might be userful for tests for example. ```ruby -Metrics.silence do +logger.silence do # logger is completely silenced - Metrics.log "hello world" # nothing is emitted here + logger.log "hello world" # nothing is emitted here end # works normally again -Metrics.log :foo # => foo +logger.log :foo # => foo ``` The typical setup for RSpec might look like this: ```ruby RSpec.configure do |config| config.around :each do |example| - Metrics.silence &example + MyLogger.silence &example end end ``` -Note that this code will only silence logger in the current thread. It'll still -produce output if you fire up a new thread. To silence it completely, use -`disable!` method, like so: +Note that silence method will only suppress logging in the current thread. +It'll still produce output if you fire up a new thread. To silence it +completely, use `disable!` method. This will completely silence the logger +across all threads. ```ruby # spec/spec_helper.rb -Metrics.disable! +MyLogger.disable! ```