Coder Social home page Coder Social logo

logjam_agent's Introduction

Logjam Agent

Client side library for logjam.

Hooks into Rails, collects log lines, performance metrics, error/exception infomation and Rack environment information and sends this data to Logjam.

Has experimental support for Sinatra.

Currently only one mechanism is available for data transport: ZeroMQ. Support for AMQP has been dropped.

Build

Usage

For ZeroMQ, add

gem "logjam_agent"
gem "ffi-rzmq"

to your Gemfile.

Add an initializer config/initializers/logjam_agent.rb to your app and configure class LogjamAgent.

module LogjamAgent
  # Configure the application name (required). Must not contain dots or hyphens.
  self.application_name = "myapp"

  # Configure the environment name (optional). Defaults to Rails.env.
  # self.environment_name = Rails.env

  # Configure the application revision (optional). Defaults to (git rev-parse HEAD).
  # self.application_revision = "f494e11afa0738b279517a2a96101a952052da5d"

  # Configure request data forwarder for ZeroMQ. Default options as given below.
  # The host parameter can be a comma separted list of zmq connection specifictions,
  # where the protocol prefix and port suffix are optional. rcv_timeo and
  # snd_timeo options only apply for sychronous messages.
  add_forwarder(:zmq,
                :host      => "localhost",
                :port      => 9604,
                :linger    => 1000,
                :snd_hwm   =>  100,
                :rcv_timeo => 5000,
                :snd_timeo => 5000)

  # Configure ip obfuscation. Defaults to no obfuscation.
  self.obfuscate_ips = true

  # Configure cookie obfuscation. Defaults to [/_session\z/].
  self.obfuscated_cookies = [/_session\z/]

  # Configure asset request logging and forwarding. Defaults to ignore
  # asset requests in development mode. Set this to false if you need
  # to debug asset request handling.
  self.ignore_asset_requests = Rails.env.development?

  # Configure a list of URL patterns for which no data should be sent
  # to logjam and nothing should be sent to the log device. Please not
  # that the log lines will still show up in dev mode on the console.
  # Defaults to the empty list.
  # self.ignored_request_urls = [%r{/_system/}]

  # Disable ActiveSupport::Notifications (and thereby logging) of ActionView
  # render events. Defaults to false.
  # self.ignore_render_events = Rails.env.production?

  # Configure log level for logging on disk: only lines with a log level
  # greater than or equal to the specified one will be logged to disk.
  # Defaults to Logger::INFO. Note that logjam_agent extends the standard
  # logger log levels by the constant NONE, which indicates no logging.
  # Also, setting the level has no effect on console logging in development.
  # self.log_device_log_level = Logger::WARN   # log warnings, errors, fatals and unknown log messages
  # self.log_device_log_level = Logger::NONE   # log nothing at all

  # Configure lines which will not be logged locally.
  # They will still be sent to the logjam server. Defaults to nil.
  self.log_device_ignored_lines = /^\s*Rendered/

  # It is also possible to ovveride this on a per request basis,
  # for example in a Rails before_action
  # LogjamAgent.request.log_device_ignored_lines = /^\s*(?:Rendered|REDIS)/

  # Configure maximum size of logged parameters and environment variables sent to
  # logjam. Defaults to 1024.
  # self.max_logged_param_size = 1024

  # Configure maximum size of logged parameters and environment variables sent to
  # logjam. Defaults to 1024 * 100.
  # self.max_logged_cookie_size = 1024 * 100

  # Configure maximum log line length. Defaults to 2048.
  # This setting only applies to the lines sent with the request.
  self.max_line_length = 2048

  # Configure max bytes allowed for all log lines. Defaults to 1Mb.
  # This setting only applies to the lines sent with the request.
  self.max_bytes_all_lines = 1024 * 1024

  # Configure compression method. Defaults to NO_COMPRESSION. Available
  # compression methods are ZLIB_COMPRESSION, SNAPPY_COMPRESSION, LZ4_COMPRESSION.
  # Snappy and LZ4 are faster and less CPU intensive than ZLIB, ZLIB achieves
  # higher compression rates. LZ4 is faster to decompress than Snappy
  # and recommended.
  # self.compression_method = ZLIB_COMPRESSION
  # self.compression_method = SNAPPY_COMPRESSION
  # self.compression_method = LZ4_COMPRESSION

  # Activate the split between hard and soft-exceptions. Soft exceptions are
  # all exceptions below a log level of Logger::ERROR. Logjam itself can then
  # display those soft exceptions differently. Defaults to `true`.
  # self.split_hard_and_soft_exceptions = true
end

Generating unique request ids

The agent generates unique request ids for all request handled using standard SecureRandom class shipped with Ruby.

Generating JSON

The agent will try to use the Oj to generate JSON. If this is not available in your application, it will fall back to the to_json method.

Sinatra

Supports both classic and modular Sinatra applications. Since Sinatra doesn't have built in action names like Rails, you'll have to declare them in your handlers, or in a before filter. Example:

require 'logjam_agent/sinatra'

use LogjamAgent::Sinatra::Middleware

class SinatraTestApp < Sinatra::Base
  register LogjamAgent::Sinatra

  configure do
    set :loglevel, :debug
    setup_logjam_logger

    LogjamAgent.application_name = "myapp"
    LogjamAgent.add_forwarder(:zmq, :host => "my-logjam-broker")
    LogjamAgent.parameter_filters << :password
  end

  before '/index' do
    action_name "Simple#index"
  end

  get '/index' do
    logger.info 'Hello World!'
    'Hello World!'
  end
end

The environment name is picked up from either the environment variable LOGJAM_ENV, or Sinatra's environment setting.

Set the environment variable APP_LOG_TO_STDOUT if you want to log to STDOUT. Otherwise, logs will appear in the subdirectory log of your application's root.

Selective Logging

The agent adds log lines to the request information sent via ZMQ on the logging bus and also writes log lines to the configured log device.

Using one of the logjam helpers LogjamAgent.logjam_only or LogjamAgent.logdevice_only it is possible to send information to only one of those log line sinks for the duration of a given block.

JSON Logging

When LogjamAgent.log_format is set to :json, the logjam agent logger will make sure that the content of line logged to the log device is converted to JSON.

Rails.logger.info("foobar is great!")
# ----->
{ "message": "foobar is great!"}

Rails.logger.info(message: "foobar", user: 5)
# ----->
{ "message": "foobar", "user": 5 }

e = Standard::Error.new()
Rails.logger.info(e)
# ----->
{ "message": "#{e.message}", "error": <execption with formatted backtrace> }

Troubleshooting

If the agent experiences problems when sending data, it will log information to a file named logjam_agent_error.log which you can find under Rails.root/log. If you set the RAILS_LOG_TO_STDOUT environment variable, those logs will be available through stderr.

This behavior is customizable via a module level call back method:

LogjamAgent.error_handler = lambda {|exception| ... }

logjam_agent's People

Contributors

0robustus1 avatar boosty avatar breunigs avatar edennis avatar freetwix avatar jhk avatar markschmidt avatar maxlaverse avatar mrsimo avatar paukul avatar pete2786 avatar pietbrauer avatar plu avatar promisedlandt avatar skaes avatar toy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

logjam_agent's Issues

circular require warning together with rails

$ RUBYOPT="-W2" bundle exec ruby -e "require 'rails'; require 'logjam_agent'"

Gives the following warning:

.rvm/gems/ruby-2.3.1/gems/logjam_agent-0.23.1/lib/logjam_agent/railtie.rb:3: warning: loading in progress, circular require considered harmful - .rvm/gems/ruby-2.3.1/gems/logjam_agent-0.23.1/lib/logjam_agent.rb
    from -e:1:in  `<main>'
    from -e:1:in  `require'
    from .rvm/gems/ruby-2.3.1/gems/logjam_agent-0.23.1/lib/logjam_agent.rb:41:in  `<top (required)>'
    from .rvm/gems/ruby-2.3.1/gems/logjam_agent-0.23.1/lib/logjam_agent.rb:41:in  `require'
    from .rvm/gems/ruby-2.3.1/gems/logjam_agent-0.23.1/lib/logjam_agent/railtie.rb:3:in  `<top (required)>'
    from .rvm/gems/ruby-2.3.1/gems/logjam_agent-0.23.1/lib/logjam_agent/railtie.rb:3:in  `require'

Cause seems to be that https://github.com/skaes/logjam_agent/blob/master/lib/logjam_agent.rb#L41 requires the railtie, which in reverse requires logjam_agent again.

is logjam_agent thread safe?

I've written some simple Sidekiq middleware to track our Sidekiq jobs in Logjam. However the importer regularly dies with something like this:

Feb 16 06:06:06 intern.greenlight-software.de logjam-importer[15735]: [E] subscriber: (src/importer-subscriber.c:277): dropped invalid message of size 7
Feb 16 06:06:06 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [021] greenlight-production
Feb 16 06:06:06 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [026] logs.greenlight.production
Feb 16 06:06:06 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [021] greenlight-production
Feb 16 06:06:06 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [026] logs.greenlight.production
Feb 16 06:06:06 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [933] {"request_id":"11d6c8cdc5c94ccd8f4210571edcdf9e","host":"intern.greenlight-software.de","process_id":17493,"lines":[[1,"2018-02-16T06:06:06.553007","Performing Briefing::UpdateColorCacheForPersonJob (Job ID: 20e04dc3-b8ea-4fef-bdb7-40a3f63cfbb1) from Sidekiq(greenlight_product
Feb 16 06:06:06 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [931] {"request_id":"9428054bb6424bf1bf5d65d1859e3936","host":"intern.greenlight-software.de","process_id":17493,"lines":[[1,"2018-02-16T06:06:06.555693","Performing Briefing::UpdateColorCacheForPersonJob (Job ID: daf26fce-bd87-4cb3-b8de-7ba0c6f91d18) from Sidekiq(greenlight_product
Feb 16 06:06:06 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [024] CABD000100000000000001619D3847ED0000000000000ABD
Feb 16 06:06:06 intern.greenlight-software.de logjam-importer[15735]: [E] subscriber: (src/importer-subscriber.c:277): dropped invalid message of size 1
Feb 16 06:06:06 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [024] CABD000100000000000001619D38480E0000000000000ABE
Feb 16 06:06:07 intern.greenlight-software.de logjam-importer[15735]: [E] subscriber: (src/importer-subscriber.c:277): dropped invalid message of size 5
Feb 16 06:06:07 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [021] greenlight-production
Feb 16 06:06:07 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [026] logs.greenlight.production
Feb 16 06:06:07 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [924] {"request_id":"90bfe1fde34e4177801f908c418ea08c","host":"intern.greenlight-software.de","process_id":17493,"lines":[[1,"2018-02-16T06:06:06.558386","Performing Briefing::UpdateColorCacheForPersonJob (Job ID: 7dabad03-4260-4ce2-bc6b-f05f370c25ac) from Sidekiq(greenlight_product
Feb 16 06:06:07 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [021] greenlight-production
Feb 16 06:06:07 intern.greenlight-software.de logjam-importer[15735]: [E] FRAME= [024] CABD000100000000000001619D3848660000000000000ABF
Feb 16 06:06:07 intern.greenlight-software.de logjam-importer[15735]: logjam-importer: src/zframe.c:173: zframe_size: Assertion `self' failed.
Feb 16 06:06:07 intern.greenlight-software.de systemd[1]: logjam-importer.service: Main process exited, code=killed, status=6/ABRT
Feb 16 06:06:07 intern.greenlight-software.de systemd[1]: logjam-importer.service: Unit entered failed state.
Feb 16 06:06:07 intern.greenlight-software.de systemd[1]: logjam-importer.service: Failed with result 'signal'.
Feb 16 06:06:18 intern.greenlight-software.de systemd[1]: logjam-importer.service: Service hold-off time over, scheduling restart.

For me that looks like the ZMQ frames are mixed together. But I'm far from familar with the code, any idea whats going on?

Here's the middleware I'm using: https://gist.github.com/roccoblues/6846822c2c349465f446220a9772a2f3

Error lines are truncated

It's very important to have the full line in Logjam available in case an error occurs. For example this exception has been truncated (using max_line_length):

NameError(undefined local variable or method `user' for #<#<Class:0x0000000ea1a5c8>:0x0000000ea18ac0>) /virtual/app/releases/20140826134247/app/views/rest/vendor/mobile/users/_user.mobile_v1.rb:2:in `_app_views_rest_vendor_mobile_users__user_mobile_v__rb___1277931153785341233_122701620'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/actionpack-4.0.9/lib/action_view/template.rb:143:in `block in render'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/activesupport-4.0.9/lib/active_support/notifications.rb:161:in `instrument'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/actionpack-4.0.9/lib/action_view/template.rb:141:in `render'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/actionpack-4.0.9/lib/action_view/renderer/partial_renderer.rb:306:in `render_partial'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/actionpack-4.0.9/lib/action_view/renderer/partial_renderer.rb:279:in `block in render'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/actionpack-4.0.9/lib/action_view/renderer/abstract_renderer.rb:38:in `block in instrument'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/activesupport-4.0.9/lib/active_support/notifications.rb:159:in `block in instrument'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/activesupport-4.0.9/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/activesupport-4.0.9/lib/active_support/notifications.rb:159:in `instrument'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/actionpack-4.0.9/lib/action_view/renderer/abstract_renderer.rb:38:in `instrument'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/actionpack-4.0.9/lib/action_view/renderer/partial_renderer.rb:278:in `render'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/actionpack-4.0.9/lib/action_view/renderer/renderer.rb:47:in `render_partial'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/actionpack-4.0.9/lib/action_view/renderer/renderer.rb:21:in `render'
/virtual/app/shared/bundle210/ruby/2.1.0/gems/actionpack-4.0.9/lib/action_view/helpers/rendering_helper.rb:24:in `r ... [LINE TRUNCATED]

I highly recommend not truncating error lines.

Is uuid4r still needed?

Hi, the code in https://github.com/skaes/logjam_agent/blob/master/lib/logjam_agent.rb#L208-L218 prefers uuid4r.uuid(4) over SecureRandom.uuid. I did some benchmark and SecureRandom is much faster than uuid4r.

Warming up --------------------------------------
              UUID4R     3.536k i/100ms
        SecureRandom    16.287k i/100ms
Calculating -------------------------------------
              UUID4R     37.250k (± 3.8%) i/s -    187.408k in   5.038382s
        SecureRandom    173.052k (± 5.5%) i/s -    879.498k in   5.098110s

Comparison:
        SecureRandom:   173051.9 i/s
              UUID4R:    37250.3 i/s - 4.65x  slower

Results from ruby 2.4.1, similar difference is in ruby 2.3.1, benchmark script used:

require 'benchmark/ips'
require 'securerandom'
require 'uuid4r'

Benchmark.ips do |bm|

  bm.report("UUID4R") do
    UUID4R::uuid(4)
  end

  bm.report("SecureRandom") do
    SecureRandom.uuid
  end

  bm.compare!
end

Additionally using delete('-') instead of gsub('-','') could speed up uuid generation by another 15%.

Calling silence on ActiveSupport::Deprecation is deprecated and will be removed from Rails

After updating an app to Rails 7.1 I'm getting the following warning:

DEPRECATION WARNING: Calling silence on ActiveSupport::Deprecation is deprecated and will be removed from Rails (use Rails.application.deprecators.silence instead)

This is because logjam_agent is calling silence on ActiveSupport::Deprecation in this line:

ActiveSupport::Deprecation.silence do

As of Rails 7.1 there's a new way to handle deprecations, more details here:
https://guides.rubyonrails.org/7_1_release_notes.html#add-rails-application-deprecators

should logjam_agent send time in application timezone?

During a migration I had the (unfortunate) situation that some logjam agents where sending requests and events in UTC time and some in CET. It looks like the data is stored with the timezone information in the logjam database but the view doesn't handle it correctly.

To fix that I hat to monkey patch logjam_agent to send all requests with the application timezone. I replace this two (https://github.com/skaes/logjam_agent/blob/master/lib/logjam_agent/rack/logger.rb#L29, https://github.com/skaes/logjam_agent/blob/master/lib/logjam_agent/rack/logger.rb#L51) Time.now occurences with Time.current which honors the application timezone.

For events I manually specified the start time: LogjamAgent.event(current_revision, started_at: Time.current.iso8601)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.