loga 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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