loga 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +25 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +19 -0
  5. data/.rubocop_todo.yml +33 -0
  6. data/Appraisals +14 -0
  7. data/Gemfile +8 -0
  8. data/README.md +147 -0
  9. data/Rakefile +9 -0
  10. data/circle.yml +23 -0
  11. data/gemfiles/rails32.gemfile +11 -0
  12. data/gemfiles/rails40.gemfile +11 -0
  13. data/gemfiles/sinatra14.gemfile +11 -0
  14. data/gemfiles/unit.gemfile +9 -0
  15. data/lib/loga.rb +33 -0
  16. data/lib/loga/configuration.rb +96 -0
  17. data/lib/loga/event.rb +21 -0
  18. data/lib/loga/ext/rails/rack/logger3.rb +21 -0
  19. data/lib/loga/ext/rails/rack/logger4.rb +13 -0
  20. data/lib/loga/formatter.rb +104 -0
  21. data/lib/loga/parameter_filter.rb +65 -0
  22. data/lib/loga/rack/logger.rb +102 -0
  23. data/lib/loga/rack/request.rb +77 -0
  24. data/lib/loga/rack/request_id.rb +44 -0
  25. data/lib/loga/railtie.rb +139 -0
  26. data/lib/loga/tagged_logging.rb +76 -0
  27. data/lib/loga/utilities.rb +7 -0
  28. data/lib/loga/version.rb +3 -0
  29. data/loga.gemspec +31 -0
  30. data/spec/fixtures/README.md +8 -0
  31. data/spec/fixtures/rails32/Rakefile +7 -0
  32. data/spec/fixtures/rails32/app/controllers/application_controller.rb +28 -0
  33. data/spec/fixtures/rails32/app/helpers/application_helper.rb +2 -0
  34. data/spec/fixtures/rails32/app/views/layouts/application.html.erb +14 -0
  35. data/spec/fixtures/rails32/app/views/user.html.erb +1 -0
  36. data/spec/fixtures/rails32/config.ru +4 -0
  37. data/spec/fixtures/rails32/config/application.rb +71 -0
  38. data/spec/fixtures/rails32/config/boot.rb +6 -0
  39. data/spec/fixtures/rails32/config/environment.rb +5 -0
  40. data/spec/fixtures/rails32/config/environments/development.rb +26 -0
  41. data/spec/fixtures/rails32/config/environments/production.rb +50 -0
  42. data/spec/fixtures/rails32/config/environments/test.rb +35 -0
  43. data/spec/fixtures/rails32/config/initializers/backtrace_silencers.rb +7 -0
  44. data/spec/fixtures/rails32/config/initializers/inflections.rb +15 -0
  45. data/spec/fixtures/rails32/config/initializers/mime_types.rb +5 -0
  46. data/spec/fixtures/rails32/config/initializers/secret_token.rb +7 -0
  47. data/spec/fixtures/rails32/config/initializers/session_store.rb +8 -0
  48. data/spec/fixtures/rails32/config/initializers/wrap_parameters.rb +10 -0
  49. data/spec/fixtures/rails32/config/locales/en.yml +5 -0
  50. data/spec/fixtures/rails32/config/routes.rb +64 -0
  51. data/spec/fixtures/rails32/public/404.html +26 -0
  52. data/spec/fixtures/rails32/public/422.html +26 -0
  53. data/spec/fixtures/rails32/public/500.html +25 -0
  54. data/spec/fixtures/rails32/public/favicon.ico +0 -0
  55. data/spec/fixtures/rails32/public/index.html +241 -0
  56. data/spec/fixtures/rails32/public/robots.txt +5 -0
  57. data/spec/fixtures/rails32/script/rails +6 -0
  58. data/spec/fixtures/rails40/Rakefile +6 -0
  59. data/spec/fixtures/rails40/app/controllers/application_controller.rb +30 -0
  60. data/spec/fixtures/rails40/app/helpers/application_helper.rb +2 -0
  61. data/spec/fixtures/rails40/app/views/layouts/application.html.erb +14 -0
  62. data/spec/fixtures/rails40/app/views/user.html.erb +1 -0
  63. data/spec/fixtures/rails40/bin/bundle +3 -0
  64. data/spec/fixtures/rails40/bin/rails +4 -0
  65. data/spec/fixtures/rails40/bin/rake +4 -0
  66. data/spec/fixtures/rails40/config.ru +4 -0
  67. data/spec/fixtures/rails40/config/application.rb +37 -0
  68. data/spec/fixtures/rails40/config/boot.rb +4 -0
  69. data/spec/fixtures/rails40/config/environment.rb +5 -0
  70. data/spec/fixtures/rails40/config/environments/development.rb +24 -0
  71. data/spec/fixtures/rails40/config/environments/production.rb +65 -0
  72. data/spec/fixtures/rails40/config/environments/test.rb +39 -0
  73. data/spec/fixtures/rails40/config/initializers/backtrace_silencers.rb +7 -0
  74. data/spec/fixtures/rails40/config/initializers/filter_parameter_logging.rb +4 -0
  75. data/spec/fixtures/rails40/config/initializers/inflections.rb +16 -0
  76. data/spec/fixtures/rails40/config/initializers/mime_types.rb +5 -0
  77. data/spec/fixtures/rails40/config/initializers/secret_token.rb +12 -0
  78. data/spec/fixtures/rails40/config/initializers/session_store.rb +3 -0
  79. data/spec/fixtures/rails40/config/initializers/wrap_parameters.rb +9 -0
  80. data/spec/fixtures/rails40/config/locales/en.yml +23 -0
  81. data/spec/fixtures/rails40/config/routes.rb +62 -0
  82. data/spec/fixtures/rails40/public/404.html +58 -0
  83. data/spec/fixtures/rails40/public/422.html +58 -0
  84. data/spec/fixtures/rails40/public/500.html +57 -0
  85. data/spec/fixtures/rails40/public/favicon.ico +0 -0
  86. data/spec/fixtures/rails40/public/robots.txt +5 -0
  87. data/spec/integration/rails/railtie_spec.rb +64 -0
  88. data/spec/integration/rails/request_spec.rb +42 -0
  89. data/spec/integration/sinatra_spec.rb +54 -0
  90. data/spec/spec_helper.rb +39 -0
  91. data/spec/support/helpers.rb +16 -0
  92. data/spec/support/request_spec.rb +183 -0
  93. data/spec/support/timecop_shared.rb +7 -0
  94. data/spec/unit/loga/configuration_spec.rb +123 -0
  95. data/spec/unit/loga/event_spec.rb +20 -0
  96. data/spec/unit/loga/formatter_spec.rb +186 -0
  97. data/spec/unit/loga/parameter_filter_spec.rb +76 -0
  98. data/spec/unit/loga/rack/logger_spec.rb +114 -0
  99. data/spec/unit/loga/rack/request_spec.rb +70 -0
  100. data/spec/unit/loga/utilities_spec.rb +16 -0
  101. data/spec/unit/loga_spec.rb +41 -0
  102. metadata +357 -0
@@ -0,0 +1,139 @@
1
+ require 'loga'
2
+
3
+ module Loga
4
+ class Railtie < Rails::Railtie
5
+ class InitializeLogger
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call
11
+ loga.tap do |config|
12
+ config.sync = sync
13
+ config.level = app.config.log_level
14
+ end
15
+ loga.initialize!
16
+ app.config.logger = loga.logger
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :app
22
+
23
+ def loga
24
+ app.config.loga
25
+ end
26
+
27
+ def sync
28
+ Rails::VERSION::MAJOR > 3 ? app.config.autoflush_log : true
29
+ end
30
+
31
+ def constantized_log_level
32
+ Logger.const_get(app.config.log_level.to_s.upcase)
33
+ end
34
+ end
35
+
36
+ config.loga = Loga::Configuration.new
37
+
38
+ initializer :loga_initialize_logger, before: :initialize_logger do |app|
39
+ InitializeLogger.new(app).call if app.config.loga.enabled
40
+ end
41
+
42
+ class InitializeMiddleware
43
+ module ExceptionsCatcher
44
+ # Sets up an alias chain to catch exceptions when Rails middleware does
45
+ def self.included(base) #:nodoc:
46
+ base.send(:alias_method, :render_exception_without_loga, :render_exception)
47
+ base.send(:alias_method, :render_exception, :render_exception_with_loga)
48
+ end
49
+
50
+ private
51
+
52
+ def render_exception_with_loga(env, exception)
53
+ env['loga.exception'] = exception
54
+ render_exception_without_loga(env, exception)
55
+ end
56
+ end
57
+
58
+ def initialize(app)
59
+ @app = app
60
+ end
61
+
62
+ def call
63
+ insert_loga_rack_logger
64
+ disable_rails_rack_logger
65
+ insert_exceptions_catcher
66
+ end
67
+
68
+ private
69
+
70
+ attr_reader :app
71
+
72
+ def insert_exceptions_catcher
73
+ if defined?(ActionDispatch::DebugExceptions)
74
+ ActionDispatch::DebugExceptions.send(:include, ExceptionsCatcher)
75
+ elsif defined?(ActionDispatch::ShowExceptions)
76
+ ActionDispatch::ShowExceptions.send(:include, ExceptionsCatcher)
77
+ end
78
+ end
79
+
80
+ # Removes start of request log
81
+ # (e.g. Started GET "/users" for 127.0.0.1 at 2015-12-24 23:59:00 +0000)
82
+ def disable_rails_rack_logger
83
+ return unless app.config.loga.silence_rails_rack_logger
84
+
85
+ case Rails::VERSION::MAJOR
86
+ when 3 then require 'loga/ext/rails/rack/logger3.rb'
87
+ when 4 then require 'loga/ext/rails/rack/logger4.rb'
88
+ end
89
+ end
90
+
91
+ def insert_loga_rack_logger
92
+ app.middleware.insert_after Rails::Rack::Logger,
93
+ Loga::Rack::Logger,
94
+ app.config.logger,
95
+ app.config.log_tags
96
+ end
97
+ end
98
+
99
+ initializer :loga_initialize_middleware do |app|
100
+ InitializeMiddleware.new(app).call if app.config.loga.enabled
101
+ app.config.colorize_logging = false
102
+ end
103
+
104
+ class InitializeInstrumentation
105
+ def call
106
+ remove_existing_log_subscriptions
107
+ end
108
+
109
+ private
110
+
111
+ def remove_existing_log_subscriptions
112
+ ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
113
+ case subscriber
114
+ when defined?(ActionView::LogSubscriber) && ActionView::LogSubscriber
115
+ unsubscribe(:action_view, subscriber)
116
+ end
117
+ end
118
+ end
119
+
120
+ def unsubscribe(component, subscriber)
121
+ events = subscriber.public_methods(false).reject { |method| method.to_s == 'call' }
122
+ events.each do |event|
123
+ ActiveSupport::Notifications
124
+ .notifier
125
+ .listeners_for("#{event}.#{component}")
126
+ .each do |listener|
127
+ if listener.instance_variable_get('@delegate') == subscriber
128
+ ActiveSupport::Notifications.unsubscribe listener
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ config.after_initialize do |app|
136
+ InitializeInstrumentation.new.call if app.config.loga.enabled
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,76 @@
1
+ # Copy of ActiveSupport::TaggedLogging
2
+ #
3
+ # Copyright and license information: https://github.com/rails/rails/blob/master/activesupport/MIT-LICENSE
4
+ # Original contributors: https://github.com/rails/rails/commits/master/activesupport/lib/active_support/tagged_logging.rb
5
+
6
+ require 'active_support/core_ext/module/delegation'
7
+ require 'active_support/core_ext/object/blank'
8
+ require 'logger'
9
+
10
+ module Loga
11
+ # rubocop:disable Metrics/LineLength
12
+ # Wraps any standard Logger object to provide tagging capabilities.
13
+ #
14
+ # logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
15
+ # logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
16
+ # logger.tagged('BCX', "Jason") { logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
17
+ # logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
18
+ #
19
+ # This is used by the default Rails.logger as configured by Railties to make
20
+ # it easy to stamp log lines with subdomains, request ids, and anything else
21
+ # to aid debugging of multi-user production applications.
22
+ # rubocop:enable Metrics/LineLength
23
+ module TaggedLogging
24
+ module Formatter # :nodoc:
25
+ def tagged(*tags)
26
+ new_tags = push_tags(*tags)
27
+ yield self
28
+ ensure
29
+ pop_tags(new_tags.size)
30
+ end
31
+
32
+ def push_tags(*tags)
33
+ tags.flatten.reject(&:blank?).tap do |new_tags|
34
+ current_tags.concat new_tags
35
+ end
36
+ end
37
+
38
+ def pop_tags(size = 1)
39
+ current_tags.pop size
40
+ end
41
+
42
+ def clear_tags!
43
+ current_tags.clear
44
+ end
45
+
46
+ def current_tags
47
+ Thread.current[:loga_tagged_logging_tags] ||= []
48
+ end
49
+
50
+ private
51
+
52
+ def tags_text
53
+ tags = current_tags
54
+ tags.collect { |tag| "[#{tag}] " }.join if tags.any?
55
+ end
56
+ end
57
+
58
+ def self.new(logger)
59
+ # Ensure we set a default formatter so we aren't extending nil!
60
+ # logger.formatter ||= ::Logger::SimpleFormatter.new
61
+ logger.formatter.extend Formatter
62
+ logger.extend(self)
63
+ end
64
+
65
+ delegate :push_tags, :pop_tags, :clear_tags!, to: :formatter
66
+
67
+ def tagged(*tags)
68
+ formatter.tagged(*tags) { yield self }
69
+ end
70
+
71
+ def flush
72
+ clear_tags!
73
+ super if defined?(super)
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,7 @@
1
+ module Loga
2
+ module Utilities
3
+ def duration_in_ms(started_at, ended_at)
4
+ ((ended_at - started_at) * 1000).round
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Loga
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'loga/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'loga'
8
+ spec.version = Loga::VERSION
9
+ spec.authors = ['Funding Circle']
10
+ spec.email = ['engineering@fundingcircle.com']
11
+ spec.summary = 'Facilitate log aggregation via unified logging'
12
+ spec.description = 'Log aggregation through unified logging middleware, while respecting the original log format.'
13
+ spec.homepage = 'https://github.com/FundingCircle/loga'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(/^bin/) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(/^(test|spec|features)/)
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_dependency 'activesupport', '>= 2.3.8'
21
+ spec.add_dependency 'rack'
22
+
23
+ spec.add_development_dependency 'appraisal', '~> 2.0.2'
24
+ spec.add_development_dependency 'bundler', '~> 1.6'
25
+ spec.add_development_dependency 'pry'
26
+ spec.add_development_dependency 'rack-test'
27
+ spec.add_development_dependency 'rake'
28
+ spec.add_development_dependency 'rspec', '~> 3.0.0'
29
+ spec.add_development_dependency 'rubocop', '~> 0.30.0'
30
+ spec.add_development_dependency 'timecop'
31
+ end
@@ -0,0 +1,8 @@
1
+ # Generating fixture Apps
2
+
3
+ ## Rails 3.2
4
+ `appraisal rails_3.2 rails new spec/fixtures/rails32 --skip-gemfile --skip-git --skip-active-record --skip-sprockets --skip-javascript --skip-test-unit`
5
+
6
+
7
+ ## Rails 4.0
8
+ `appraisal rails_4.0 rails new spec/fixtures/rails40 --skip-gemfile --skip-git --skip-keeps --skip-active-record --skip-action-view --skip-sprockets --skip-spring --skip-javascript --skip-test-unit`
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
3
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
+
5
+ require File.expand_path('../config/application', __FILE__)
6
+
7
+ Rails32::Application.load_tasks
@@ -0,0 +1,28 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+
4
+ def ok
5
+ render text: 'Hello Rails'
6
+ end
7
+
8
+ def error
9
+ nil.name
10
+ end
11
+
12
+ def show
13
+ render json: params
14
+ end
15
+
16
+ def create
17
+ render json: params
18
+ end
19
+
20
+ def new
21
+ redirect_to :ok
22
+ end
23
+
24
+ def update
25
+ @id = params[:id]
26
+ render '/user'
27
+ end
28
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Rails32</title>
5
+ <%= stylesheet_link_tag "application", :media => "all" %>
6
+ <%= javascript_include_tag "application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1 @@
1
+ <p>User <%= @id %></p>
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Rails32::Application
@@ -0,0 +1,71 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ # Pick the frameworks you want:
4
+ # require "active_record/railtie"
5
+ require "action_controller/railtie"
6
+ require "action_mailer/railtie"
7
+ require "active_resource/railtie"
8
+ # require "sprockets/railtie"
9
+ # require "rails/test_unit/railtie"
10
+
11
+ if defined?(Bundler)
12
+ # If you precompile assets before deploying to production, use this line
13
+ Bundler.require(*Rails.groups(:assets => %w(development test)))
14
+ # If you want your assets lazily compiled in production, use this line
15
+ # Bundler.require(:default, :assets, Rails.env)
16
+ end
17
+
18
+ STREAM = StringIO.new unless defined?(STREAM)
19
+
20
+ module Rails32
21
+ class Application < Rails::Application
22
+ # Settings in config/environments/* take precedence over those specified here.
23
+ # Application configuration should go into files in config/initializers
24
+ # -- all .rb files in that directory are automatically loaded.
25
+
26
+ # Custom directories with classes and modules you want to be autoloadable.
27
+ # config.autoload_paths += %W(#{config.root}/extras)
28
+
29
+ # Only load the plugins named here, in the order given (default is alphabetical).
30
+ # :all can be used as a placeholder for all plugins not explicitly named.
31
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
32
+
33
+ # Activate observers that should always be running.
34
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
35
+
36
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
37
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
38
+ # config.time_zone = 'Central Time (US & Canada)'
39
+
40
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
41
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
42
+ # config.i18n.default_locale = :de
43
+
44
+ # Configure the default encoding used in templates for Ruby 1.9.
45
+ config.encoding = "utf-8"
46
+
47
+ # Configure sensitive parameters which will be filtered from the log file.
48
+ config.filter_parameters += [:password]
49
+
50
+ # Enable escaping HTML in JSON.
51
+ config.active_support.escape_html_entities_in_json = true
52
+
53
+ # Use SQL instead of Active Record's schema dumper when creating the database.
54
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
55
+ # like if you have constraints or database-specific column types
56
+ # config.active_record.schema_format = :sql
57
+
58
+ # Enforce whitelist mode for mass assignment.
59
+ # This will create an empty whitelist of attributes available for mass-assignment for all models
60
+ # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
61
+ # parameters by using an attr_accessible or attr_protected declaration.
62
+ # config.active_record.whitelist_attributes = true
63
+ config.log_tags = [:uuid]
64
+ config.loga.configure do |loga|
65
+ loga.service_name = 'hello_world_app'
66
+ loga.service_version = '1.0'
67
+ loga.host = 'bird.example.com'
68
+ loga.device = STREAM
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+
3
+ # Set up gems listed in the Gemfile.
4
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5
+
6
+ require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
@@ -0,0 +1,5 @@
1
+ # Load the rails application
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the rails application
5
+ Rails32::Application.initialize!
@@ -0,0 +1,26 @@
1
+ Rails32::Application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb
3
+
4
+ # In the development environment your application's code is reloaded on
5
+ # every request. This slows down response time but is perfect for development
6
+ # since you don't have to restart the web server when you make code changes.
7
+ config.cache_classes = true
8
+
9
+ # Log error messages when you accidentally call methods on nil.
10
+ config.whiny_nils = true
11
+
12
+ # Show full error reports and disable caching
13
+ config.consider_all_requests_local = true
14
+ config.action_controller.perform_caching = false
15
+
16
+ # Don't care if the mailer can't send
17
+ config.action_mailer.raise_delivery_errors = false
18
+
19
+ # Print deprecation notices to the Rails logger
20
+ config.active_support.deprecation = :log
21
+
22
+ # Only use best-standards-support built into browsers
23
+ config.action_dispatch.best_standards_support = :builtin
24
+
25
+
26
+ end