[deploy] Refactor:Remove No Longer Needed Timber Logging (#9555)
This commit is contained in:
parent
a589529269
commit
e2e034b910
83 changed files with 1 additions and 2242 deletions
5
Envfile
5
Envfile
|
|
@ -167,11 +167,6 @@ variable :STACK_EXCHANGE_APP_KEY, :String, default: ""
|
|||
group :production do
|
||||
variable :SECRET_KEY_BASE, :String
|
||||
|
||||
# Timber
|
||||
# (https://docs.timber.io/)
|
||||
variable :SEND_LOGS_TO_TIMBER, :String # Defaults to true in production, false in development
|
||||
variable :TIMBER, :String # Only required if above is "true" or unset
|
||||
|
||||
# Sendgrid
|
||||
# (https://sendgrid.com/docs/API_Reference/api_v3.html)
|
||||
variable :SENDGRID_USERNAME_ACCEL, :String
|
||||
|
|
|
|||
2
Gemfile
2
Gemfile
|
|
@ -100,8 +100,6 @@ gem "staccato", "~> 0.5" # Ruby Google Analytics Measurement
|
|||
gem "storext", "~> 3.1" # Add type-casting and other features on top of ActiveRecord::Store.store_accessor
|
||||
gem "stripe", "~> 5.22" # Ruby library for the Stripe API
|
||||
gem "strong_migrations", "~> 0.7" # Catch unsafe migrations
|
||||
gem "timber", "~> 3.0" # Great Ruby logging made easy
|
||||
gem "timber-rails", github: "timberio/timber-ruby-rails", branch: "master" # Timber integration for Rails
|
||||
gem "twilio-ruby", "~> 5.39" # The official library for communicating with the Twilio REST API
|
||||
gem "twitter", "~> 7.0" # A Ruby interface to the Twitter API
|
||||
gem "uglifier", "~> 4.2" # Uglifier minifies JavaScript files
|
||||
|
|
|
|||
17
Gemfile.lock
17
Gemfile.lock
|
|
@ -6,16 +6,6 @@ GIT
|
|||
acts_as_follower (0.2.1)
|
||||
activerecord (>= 4.0)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/timberio/timber-ruby-rails.git
|
||||
revision: 250326b0926d33207f0e1147a594dd8fe4487466
|
||||
branch: master
|
||||
specs:
|
||||
timber-rails (1.0.2)
|
||||
rails (>= 3.0.0)
|
||||
timber (~> 3.0)
|
||||
timber-rack (~> 1.0)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
|
|
@ -775,11 +765,6 @@ GEM
|
|||
thor (0.20.3)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.10)
|
||||
timber (3.0.1)
|
||||
msgpack (~> 1.0)
|
||||
timber-rack (1.0.1)
|
||||
rack (>= 1.2, < 3.0)
|
||||
timber (~> 3.0)
|
||||
timecop (0.9.1)
|
||||
twilio-ruby (5.39.2)
|
||||
faraday (>= 0.9, < 2.0)
|
||||
|
|
@ -990,8 +975,6 @@ DEPENDENCIES
|
|||
stripe-ruby-mock (~> 3.0)
|
||||
strong_migrations (~> 0.7)
|
||||
test-prof (~> 0.12)
|
||||
timber (~> 3.0)
|
||||
timber-rails!
|
||||
timecop (~> 0.9)
|
||||
twilio-ruby (~> 5.39)
|
||||
twitter (~> 7.0)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module Metrics
|
|||
model.estimated_count
|
||||
end
|
||||
|
||||
Rails.logger.info("db_table_size", table_info: { table_name: model.table_name, table_size: db_count })
|
||||
Rails.logger.info(message: "db_table_size", table_info: { table_name: model.table_name, table_size: db_count })
|
||||
DatadogStatsClient.gauge("postgres.db_table_size", db_count, tags: ["table_name:#{model.table_name}"])
|
||||
|
||||
next unless model.const_defined?(:SEARCH_CLASS)
|
||||
|
|
|
|||
|
|
@ -107,14 +107,6 @@ Rails.application.configure do
|
|||
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
||||
end
|
||||
|
||||
if (ENV["SEND_LOGS_TO_TIMBER"] || "true") == "true"
|
||||
# Timber.io logger
|
||||
log_device = Timber::LogDevices::HTTP.new(ENV["TIMBER"])
|
||||
logger = Timber::Logger.new(log_device)
|
||||
logger.level = config.log_level
|
||||
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
||||
end
|
||||
|
||||
# Do not dump schema after migrations.
|
||||
config.active_record.dump_schema_after_migration = false
|
||||
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
# Timber.io Ruby Configuration - Simple Structured Logging
|
||||
#
|
||||
# ^ ^ ^ ^ ___I_ ^ ^ ^ ^ ^ ^ ^
|
||||
# /|\/|\/|\ /|\ /\-_--\ /|\/|\ /|\/|\/|\ /|\/|\
|
||||
# /|\/|\/|\ /|\ / \_-__\ /|\/|\ /|\/|\/|\ /|\/|\
|
||||
# /|\/|\/|\ /|\ |[]| [] | /|\/|\ /|\/|\/|\ /|\/|\
|
||||
# -------------------------------------------------------------------
|
||||
# Website: https://timber.io
|
||||
# Documentation: https://timber.io/docs
|
||||
# Support: support@timber.io
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
config = Timber::Config.instance
|
||||
config.integrations.action_view.silence = true
|
||||
config.integrations.active_record.silence = !Rails.env.development?
|
||||
config.integrations.rack.http_events.collapse_into_single_event = true
|
||||
|
||||
config.integrations.rack.http_events.silence_request = lambda do |_rack_env, rack_request|
|
||||
rack_request.path.match?(%r{^/page_views/\d{1,9}})
|
||||
end
|
||||
|
||||
config.integrations.rack.user_context.custom_user_hash = lambda do |rack_env|
|
||||
session_user_id = rack_env["rack.session"].to_h["warden.user.user.key"]&.first&.first
|
||||
if session_user_id
|
||||
{
|
||||
id: session_user_id
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# Add additional configuration here.
|
||||
# For a full list of configuration options and their explanations see:
|
||||
# http://www.rubydoc.info/github/timberio/timber-ruby/Timber/Config
|
||||
|
|
@ -1,19 +1,9 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Metrics::RecordDataCountsWorker, type: :worker do
|
||||
default_logger = Rails.logger
|
||||
|
||||
include_examples "#enqueues_on_correct_queue", "low_priority", 1
|
||||
|
||||
describe "#perform" do
|
||||
# Override the default Rails logger as these tests require the Timber logger.
|
||||
before do
|
||||
timber_logger = Timber::Logger.new(nil)
|
||||
Rails.logger = ActiveSupport::TaggedLogging.new(timber_logger)
|
||||
end
|
||||
|
||||
after { Rails.logger = default_logger }
|
||||
|
||||
it "calls count on each model" do
|
||||
allow(User).to receive(:count)
|
||||
allow(User).to receive(:estimated_count)
|
||||
|
|
|
|||
BIN
vendor/cache/timber-3.0.1.gem
vendored
BIN
vendor/cache/timber-3.0.1.gem
vendored
Binary file not shown.
BIN
vendor/cache/timber-rack-1.0.1.gem
vendored
BIN
vendor/cache/timber-rack-1.0.1.gem
vendored
Binary file not shown.
|
|
@ -1,14 +0,0 @@
|
|||
/.bundle/
|
||||
/.yardoc
|
||||
/_yardoc/
|
||||
/coverage/
|
||||
/doc/
|
||||
/pkg/
|
||||
/spec/reports/
|
||||
/tmp/
|
||||
|
||||
# rspec failure tracking
|
||||
.rspec_status
|
||||
|
||||
# Ignore gemset
|
||||
/.gem
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
--format documentation
|
||||
--color
|
||||
--require spec_helper
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
sudo: false
|
||||
language: ruby
|
||||
cache: bundler
|
||||
rvm:
|
||||
- 1.9.3
|
||||
- 2.2.10
|
||||
- 2.3.8
|
||||
- 2.4.7
|
||||
- 2.5.6
|
||||
- 2.6.4
|
||||
- jruby-9.2.8.0
|
||||
before_install: gem install bundler -v 1.17.3
|
||||
gemfile:
|
||||
- gemfiles/rails-3.2.gemfile
|
||||
- gemfiles/rails-4.0.gemfile
|
||||
- gemfiles/rails-4.1.gemfile
|
||||
- gemfiles/rails-4.2.gemfile
|
||||
- gemfiles/rails-5.0.gemfile
|
||||
- gemfiles/rails-5.1.gemfile
|
||||
- gemfiles/rails-5.2.gemfile
|
||||
- gemfiles/rails-6.0.gemfile
|
||||
- gemfiles/rails-edge.gemfile
|
||||
env:
|
||||
global: RAILS_ENV=test
|
||||
before_script:
|
||||
- echo $BUNDLE_GEMFILE
|
||||
- bundle install
|
||||
script:
|
||||
- bundle exec rspec --format documentation
|
||||
matrix:
|
||||
fast_finish: true
|
||||
exclude:
|
||||
- rvm: 1.9.3
|
||||
- gemfile: gemfiles/rails-edge.gemfile
|
||||
- rvm: 2.2.10
|
||||
gemfile: gemfiles/rails-6.0.gemfile
|
||||
- rvm: 2.3.8
|
||||
gemfile: gemfiles/rails-6.0.gemfile
|
||||
- rvm: 2.4.7
|
||||
gemfile: gemfiles/rails-4.0.gemfile
|
||||
- rvm: 2.4.7
|
||||
gemfile: gemfiles/rails-4.1.gemfile
|
||||
- rvm: 2.4.7
|
||||
gemfile: gemfiles/rails-6.0.gemfile
|
||||
- rvm: 2.5.6
|
||||
gemfile: gemfiles/rails-3.2.gemfile
|
||||
- rvm: 2.5.6
|
||||
gemfile: gemfiles/rails-4.0.gemfile
|
||||
- rvm: 2.5.6
|
||||
gemfile: gemfiles/rails-4.1.gemfile
|
||||
- rvm: 2.6.4
|
||||
gemfile: gemfiles/rails-4.0.gemfile
|
||||
- rvm: 2.6.4
|
||||
gemfile: gemfiles/rails-4.1.gemfile
|
||||
include:
|
||||
- rvm: 2.5.6
|
||||
gemfile: gemfiles/rails-edge.gemfile
|
||||
- rvm: 1.9.3
|
||||
gemfile: gemfiles/rails-3.2.gemfile
|
||||
allow_failures:
|
||||
- rvm: 1.9.3 # bundler wont install the gems
|
||||
- gemfile: gemfiles/rails-edge.gemfile
|
||||
- rvm: jruby-9.2.8.0
|
||||
notifications:
|
||||
email: false
|
||||
slack:
|
||||
rooms:
|
||||
secure: F4BGVLUnaDqJ3YXfuIwx+m6047E8YstCUXs33Tfcs7SUlSuOSChuXqvCfVtnfNy2muF7xgB6VRL3xpFIRm7qNStqGUWCQJXmKq2OEgq1DYGkhAVle4d/LBtVcfBgeLelsoi+1TI9MrUtpZDHPl0li3PLoC+dq7rzSuhrxQ9EOhZlZGVn6LTeVcgNw6cLNzHSWJJ8zpYWLjBWUXgJ75MQvo5qaNbQxyfzm7GzEgRNfSzabFBwpKwB1Tog9X9TKTtPrn30O9Ur9+wmTu6EnwaDWZjaTK6I+AbxE8huIfUGvSrq1aV2JaDIra6zHEQ+d4j0oRYutgFM4YfyN9124MbPE2yH/5lXNQHMpUOsP0bl2U+KGDzq/V5APyrZ6irsvwGYpo3fSXrW8nDIAK4Mh8KB+Ta0zN5H8PmIRK76wJ+wG2zAtrfl+ailxMrdpK6J04fl3pCBuO6eW+AKEJ7Wfi5GiE7a9lk/YewAeDHyyLSnUNFIP0/iFAbTtRh5denCk0ZUS1XyfZNQuFoku7jk5lpe41SNItqOO0jv/jXPF+wensNa2UgMBIP0XkRw55LKn9eY0MKm9P+zp9ePaXs0T0Ttv4e0T4Jxrgf5QBynefgHwAsOI1nHr7GhlPaFQ6u8iNmjNYLB9v1JZMlO08LkytzZFpUuJoHbYYoBaRtUtEosBHg=
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
gemspec
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
# License
|
||||
|
||||
Copyright (c) 2019, Timber Technologies, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
with or without fee is hereby granted, provided that the above copyright notice
|
||||
and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
# 🌲 Timber Integration For Rails
|
||||
|
||||
[](LICENSE.md)
|
||||
[](http://www.rubydoc.info/github/timberio/timber-ruby-rails)
|
||||
[](https://travis-ci.org/timberio/timber-ruby-rails)
|
||||
|
||||
This library integrates the
|
||||
[`timber` Ruby library](https://github.com/timberio/timber-ruby) with the
|
||||
[rails](https://github.com/rails/rails) framework, turning your rails logs into
|
||||
rich structured events.
|
||||
|
||||
- **Sign-up: [https://app.timber.io](https://app.timber.io)**
|
||||
- **Documentation:
|
||||
[https://docs.timber.io/setup/languages/ruby/integrations/rails](https://docs.timber.io/setup/languages/ruby/integrations/rails)**
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
require "bundler/gem_tasks"
|
||||
require "rspec/core/rake_task"
|
||||
|
||||
RSpec::Core::RakeTask.new(:spec)
|
||||
|
||||
task :default => :spec
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require "bundler/setup"
|
||||
require "timber-rails"
|
||||
|
||||
# You can add fixtures and/or initialization code here to make experimenting
|
||||
# with your gem easier. You can also use a different console, if you like.
|
||||
|
||||
# (If you use this, don't forget to add pry to your Gemfile!)
|
||||
# require "pry"
|
||||
# Pry.start
|
||||
|
||||
require "irb"
|
||||
IRB.start(__FILE__)
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
set -vx
|
||||
|
||||
bundle install
|
||||
|
||||
# Do any other automated setup that you need to do here
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '~> 3.0.0'
|
||||
|
||||
gem 'timber',
|
||||
gem 'timber-rack'
|
||||
|
||||
gemspec :path => '../'
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '~> 3.1.0'
|
||||
|
||||
gem 'timber'
|
||||
gem 'timber-rack'
|
||||
|
||||
gemspec :path => '../'
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '~> 3.2.0'
|
||||
|
||||
gem 'timber'
|
||||
gem 'timber-rack'
|
||||
|
||||
gemspec :path => '../'
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '~> 4.0.0'
|
||||
|
||||
gem 'timber'
|
||||
gem 'timber-rack'
|
||||
|
||||
if RUBY_PLATFORM == "java"
|
||||
gem 'mime-types', '2.6.2'
|
||||
end
|
||||
|
||||
gemspec :path => '../'
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '~> 4.1.0'
|
||||
|
||||
gem 'timber'
|
||||
gem 'timber-rack'
|
||||
|
||||
if RUBY_PLATFORM == "java"
|
||||
gem 'mime-types', '2.6.2'
|
||||
end
|
||||
|
||||
gemspec :path => '../'
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '~> 4.2.0'
|
||||
|
||||
gem 'timber'
|
||||
gem 'timber-rack'
|
||||
|
||||
if RUBY_PLATFORM == "java"
|
||||
gem 'mime-types', '2.6.2'
|
||||
end
|
||||
|
||||
gemspec :path => '../'
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '~> 5.0.0'
|
||||
|
||||
gem 'timber'
|
||||
gem 'timber-rack'
|
||||
|
||||
if RUBY_PLATFORM == "java"
|
||||
gem 'mime-types', '2.6.2'
|
||||
end
|
||||
|
||||
gemspec :path => '../'
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '~> 5.1.0'
|
||||
|
||||
gem 'timber'
|
||||
gem 'timber-rack'
|
||||
|
||||
if RUBY_PLATFORM == "java"
|
||||
gem 'mime-types', '2.6.2'
|
||||
end
|
||||
|
||||
gemspec :path => '../'
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '~> 5.2.0'
|
||||
|
||||
gem 'timber'
|
||||
gem 'timber-rack'
|
||||
|
||||
if RUBY_PLATFORM == "java"
|
||||
gem 'mime-types', '2.6.2'
|
||||
end
|
||||
|
||||
gemspec :path => '../'
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '~> 6.0.0'
|
||||
|
||||
gem 'timber'
|
||||
gem 'timber-rack'
|
||||
|
||||
if RUBY_PLATFORM == "java"
|
||||
gem 'mime-types', '2.6.2'
|
||||
end
|
||||
|
||||
gemspec :path => '../'
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rack', git: 'https://github.com/rack/rack', branch: 'master'
|
||||
gem 'arel', git: 'https://github.com/rails/arel', branch: 'master'
|
||||
gem 'rails', git: 'https://github.com/rails/rails', branch: 'master'
|
||||
|
||||
gem 'timber'
|
||||
gem 'timber-rack'
|
||||
|
||||
gemspec :path => '../'
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
require "timber-rails/overrides"
|
||||
|
||||
require "timber"
|
||||
require "rails"
|
||||
require "timber-rails/active_support_log_subscriber"
|
||||
require "timber-rails/config"
|
||||
require "timber-rails/railtie"
|
||||
|
||||
require "timber-rack/http_context"
|
||||
require "timber-rack/http_events"
|
||||
require "timber-rack/user_context"
|
||||
require "timber-rails/session_context"
|
||||
require "timber-rails/rack_logger"
|
||||
require "timber-rails/error_event"
|
||||
|
||||
require "timber-rails/action_controller"
|
||||
require "timber-rails/action_dispatch"
|
||||
require "timber-rails/action_view"
|
||||
require "timber-rails/active_record"
|
||||
|
||||
|
||||
require "timber-rails/logger"
|
||||
|
||||
module Timber
|
||||
module Integrations
|
||||
# Module for holding *all* Rails integrations. This module does *not*
|
||||
# extend {Integration} because it's dependent on {Rack::HTTPEvents}. This
|
||||
# module simply disables the default HTTP request logging.
|
||||
module Rails
|
||||
def self.enabled?
|
||||
Timber::Integrations::Rack::HTTPEvents.enabled?
|
||||
end
|
||||
|
||||
def self.integrate!
|
||||
return false if !enabled?
|
||||
|
||||
ActionController.integrate!
|
||||
ActionDispatch.integrate!
|
||||
ActionView.integrate!
|
||||
ActiveRecord.integrate!
|
||||
RackLogger.integrate!
|
||||
end
|
||||
|
||||
def self.enabled=(value)
|
||||
Timber::Integrations::Rails::ErrorEvent.enabled = value
|
||||
Timber::Integrations::Rack::HTTPContext.enabled = value
|
||||
Timber::Integrations::Rack::HTTPEvents.enabled = value
|
||||
Timber::Integrations::Rack::UserContext.enabled = value
|
||||
SessionContext.enabled = value
|
||||
|
||||
ActionController.enabled = value
|
||||
ActionView.enabled = value
|
||||
ActiveRecord.enabled = value
|
||||
end
|
||||
|
||||
# All enabled middlewares. The order is relevant. Middlewares that set
|
||||
# context are added first so that context is included in subsequent log lines.
|
||||
def self.middlewares
|
||||
@middlewares ||= [Timber::Integrations::Rack::HTTPContext, SessionContext, Timber::Integrations::Rack::UserContext,
|
||||
Timber::Integrations::Rack::HTTPEvents, Timber::Integrations::Rails::ErrorEvent].select(&:enabled?)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
require "timber-rails/action_controller/log_subscriber"
|
||||
|
||||
module Timber
|
||||
module Integrations
|
||||
# Module for holding *all* ActionController integrations. See {Integration} for
|
||||
# configuration details for all integrations.
|
||||
module ActionController
|
||||
extend Integration
|
||||
|
||||
def self.integrate!
|
||||
return false if !enabled?
|
||||
|
||||
LogSubscriber.integrate!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
module Timber
|
||||
module Integrations
|
||||
module ActionController
|
||||
# Responsible for removing the default ActionController::LogSubscriber and installing
|
||||
# the TimberLogSubscriber
|
||||
#
|
||||
# @private
|
||||
class LogSubscriber < Integrator
|
||||
def initialize
|
||||
require "action_controller/log_subscriber"
|
||||
require "timber-rails/action_controller/log_subscriber/timber_log_subscriber"
|
||||
rescue LoadError => e
|
||||
raise RequirementNotMetError.new(e.message)
|
||||
end
|
||||
|
||||
def integrate!
|
||||
return true if Timber::Integrations::Rails::ActiveSupportLogSubscriber.subscribed?(:action_controller, TimberLogSubscriber)
|
||||
|
||||
Timber::Integrations::Rails::ActiveSupportLogSubscriber.unsubscribe!(:action_controller, ::ActionController::LogSubscriber)
|
||||
TimberLogSubscriber.attach_to(:action_controller)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
module Timber
|
||||
module Integrations
|
||||
module ActionController
|
||||
class LogSubscriber < Integrator
|
||||
# The log subscriber that replaces the default `ActionController::LogSubscriber`.
|
||||
# The intent of this subscriber is to, as transparently as possible, properly
|
||||
# track events that are being logged here. This LogSubscriber will never change
|
||||
# default behavior / log messages.
|
||||
#
|
||||
# @private
|
||||
class TimberLogSubscriber < ::ActionController::LogSubscriber
|
||||
def start_processing(event)
|
||||
return true if silence?
|
||||
|
||||
info do
|
||||
payload = event.payload
|
||||
params = payload[:params].except(*INTERNAL_PARAMS)
|
||||
format = extract_format(payload)
|
||||
format = format.to_s.upcase if format.is_a?(Symbol)
|
||||
|
||||
Events::ControllerCall.new(
|
||||
controller: payload[:controller],
|
||||
action: payload[:action],
|
||||
format: format,
|
||||
params: params
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def extract_format(payload)
|
||||
if payload.key?(:format)
|
||||
payload[:format] # rails > 4.X
|
||||
elsif payload.key?(:formats)
|
||||
payload[:formats].first # rails 3.X
|
||||
end
|
||||
end
|
||||
|
||||
def silence?
|
||||
ActionController.silence?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
require "timber-rails/action_dispatch/debug_exceptions"
|
||||
|
||||
module Timber
|
||||
module Integrations
|
||||
# Module for holding *all* ActionDispatch integrations. This
|
||||
# module simply disables the exception tracking middleware so that our middleware
|
||||
# works as expected.
|
||||
module ActionDispatch
|
||||
def self.enabled?
|
||||
Rails::ErrorEvent.enabled?
|
||||
end
|
||||
|
||||
def self.integrate!
|
||||
return false if !enabled?
|
||||
|
||||
DebugExceptions.integrate!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
module Timber
|
||||
module Integrations
|
||||
module ActionDispatch
|
||||
# Reponsible for disabled logging in the ActionDispatch::DebugExceptions
|
||||
# Rack middleware. We cannot simply remove the middleware because it is
|
||||
# coupled with displaying an exception debug screen if debug exceptions is enabled.
|
||||
#
|
||||
# @private
|
||||
class DebugExceptions < Integrator
|
||||
|
||||
# Patch for disabling logging
|
||||
#
|
||||
# @private
|
||||
module InstanceMethods
|
||||
def self.included(klass)
|
||||
klass.class_eval do
|
||||
private
|
||||
def logger(*args)
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def initialize
|
||||
begin
|
||||
# Rails >= 3.1
|
||||
require "action_dispatch/middleware/debug_exceptions"
|
||||
rescue LoadError
|
||||
# Rails < 3.1
|
||||
require "action_dispatch/middleware/show_exceptions"
|
||||
end
|
||||
rescue LoadError => e
|
||||
raise RequirementNotMetError.new(e.message)
|
||||
end
|
||||
|
||||
def integrate!
|
||||
if defined?(::ActionDispatch::DebugExceptions) && !::ActionDispatch::DebugExceptions.include?(InstanceMethods)
|
||||
::ActionDispatch::DebugExceptions.send(:include, InstanceMethods)
|
||||
end
|
||||
|
||||
if defined?(::ActionDispatch::ShowExceptions) && !::ActionDispatch::ShowExceptions.include?(InstanceMethods)
|
||||
::ActionDispatch::ShowExceptions.send(:include, InstanceMethods)
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
require "timber-rails/action_view/log_subscriber"
|
||||
|
||||
module Timber
|
||||
module Integrations
|
||||
# Module for holding *all* ActionView integrations. See {Integration} for
|
||||
# configuration details for all integrations.
|
||||
module ActionView
|
||||
extend Integration
|
||||
|
||||
def self.integrate!
|
||||
return false if !enabled?
|
||||
|
||||
LogSubscriber.integrate!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
module Timber
|
||||
module Integrations
|
||||
module ActionView
|
||||
# Reponsible for uninstalling the default `ActionView::LogSubscriber` and installing
|
||||
# the TimberLogSubscriber.
|
||||
#
|
||||
# @private
|
||||
class LogSubscriber < Integrator
|
||||
def initialize
|
||||
require "action_view/log_subscriber"
|
||||
require "timber-rails/action_view/log_subscriber/timber_log_subscriber"
|
||||
rescue LoadError => e
|
||||
raise RequirementNotMetError.new(e.message)
|
||||
end
|
||||
|
||||
def integrate!
|
||||
return true if Timber::Integrations::Rails::ActiveSupportLogSubscriber.subscribed?(:action_view, TimberLogSubscriber)
|
||||
|
||||
Timber::Integrations::Rails::ActiveSupportLogSubscriber.unsubscribe!(:action_view, ::ActionView::LogSubscriber)
|
||||
TimberLogSubscriber.attach_to(:action_view)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
module Timber
|
||||
module Integrations
|
||||
module ActionView
|
||||
class LogSubscriber < Integrator
|
||||
|
||||
# The log subscriber that replaces the default `ActionView::LogSubscriber`.
|
||||
# The intent of this subscriber is to, as transparently as possible, properly
|
||||
# track events that are being logged here.
|
||||
#
|
||||
# @private
|
||||
class TimberLogSubscriber < ::ActionView::LogSubscriber
|
||||
def render_template(event)
|
||||
return true if silence?
|
||||
|
||||
info do
|
||||
full_name = from_rails_root(event.payload[:identifier])
|
||||
message = " Rendered #{full_name}"
|
||||
message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
|
||||
message << " (#{event.duration.round(1)}ms)"
|
||||
|
||||
Events::TemplateRender.new(
|
||||
name: full_name,
|
||||
duration_ms: event.duration,
|
||||
message: message
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def render_partial(event)
|
||||
return true if silence?
|
||||
|
||||
info do
|
||||
full_name = from_rails_root(event.payload[:identifier])
|
||||
message = " Rendered #{full_name}"
|
||||
message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
|
||||
message << " (#{event.duration.round(1)}ms)"
|
||||
message << " #{cache_message(event.payload)}" if event.payload.key?(:cache_hit)
|
||||
|
||||
Events::TemplateRender.new(
|
||||
name: full_name,
|
||||
duration_ms: event.duration,
|
||||
message: message
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def render_collection(event)
|
||||
return true if silence?
|
||||
|
||||
if respond_to?(:render_count, true)
|
||||
info do
|
||||
identifier = event.payload[:identifier] || "templates"
|
||||
full_name = from_rails_root(identifier)
|
||||
message = " Rendered collection of #{full_name}" \
|
||||
" #{render_count(event.payload)} (#{event.duration.round(1)}ms)"
|
||||
|
||||
Events::TemplateRender.new(
|
||||
name: full_name,
|
||||
duration_ms: event.duration,
|
||||
message: message
|
||||
)
|
||||
end
|
||||
else
|
||||
# Older versions of rails delegate this method to #render_template
|
||||
render_template(event)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def log_rendering_start(payload)
|
||||
# Consolidates 2 template rendering events into 1. We don't need 2 events for
|
||||
# rendering a template. If you disagree, please feel free to open a PR and we
|
||||
# can make this an option.
|
||||
end
|
||||
|
||||
def silence?
|
||||
ActionView.silence?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
require "timber-rails/active_record/log_subscriber"
|
||||
|
||||
module Timber
|
||||
module Integrations
|
||||
# Module for holding *all* ActiveRecord integrations. See {Integration} for
|
||||
# configuration details for all integrations.
|
||||
module ActiveRecord
|
||||
extend Integration
|
||||
|
||||
def self.integrate!
|
||||
return false if !enabled?
|
||||
|
||||
LogSubscriber.integrate!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
require "timber-rails/active_record/log_subscriber/timber_log_subscriber"
|
||||
|
||||
module Timber
|
||||
module Integrations
|
||||
module ActiveRecord
|
||||
# Reponsible for uninstalling the default `ActiveRecord::LogSubscriber` and replacing it
|
||||
# with the `TimberLogSubscriber`.
|
||||
#
|
||||
# @private
|
||||
class LogSubscriber < Integrator
|
||||
def integrate!
|
||||
return true if Timber::Integrations::Rails::ActiveSupportLogSubscriber.subscribed?(:active_record, TimberLogSubscriber)
|
||||
|
||||
Timber::Integrations::Rails::ActiveSupportLogSubscriber.unsubscribe!(:active_record, ::ActiveRecord::LogSubscriber)
|
||||
TimberLogSubscriber.attach_to(:active_record)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
# We require all of ActiveRecord because the #logger method in ::ActiveRecord::LogSubscriber
|
||||
# uses ActiveRecord::Base. We can't require active_record/base directly because ActiveRecord
|
||||
# does not require files properly and we receive unintialized constant errors.
|
||||
require "active_record"
|
||||
require "active_record/log_subscriber"
|
||||
|
||||
module Timber
|
||||
module Integrations
|
||||
module ActiveRecord
|
||||
class LogSubscriber < Integrator
|
||||
# The log subscriber that replaces the default `ActiveRecord::LogSubscriber`.
|
||||
# The intent of this subscriber is to, as transparently as possible, properly
|
||||
# track events that are being logged here. This LogSubscriber will never change
|
||||
# default behavior / log messages.
|
||||
#
|
||||
# @private
|
||||
class TimberLogSubscriber < ::ActiveRecord::LogSubscriber
|
||||
def sql(event)
|
||||
return true if silence?
|
||||
|
||||
r = super(event)
|
||||
|
||||
if @message
|
||||
payload = event.payload
|
||||
|
||||
sql_event = Events::SQLQuery.new(
|
||||
sql: payload[:sql],
|
||||
duration_ms: event.duration,
|
||||
message: @message,
|
||||
)
|
||||
|
||||
logger.debug sql_event
|
||||
|
||||
@message = nil
|
||||
end
|
||||
|
||||
r
|
||||
end
|
||||
|
||||
private
|
||||
def debug(message)
|
||||
@message = message
|
||||
end
|
||||
|
||||
def silence?
|
||||
ActiveRecord.silence?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
module Timber
|
||||
module Integrations
|
||||
module Rails
|
||||
# @private
|
||||
module ActiveSupportLogSubscriber
|
||||
extend self
|
||||
|
||||
def find(component, type)
|
||||
::ActiveSupport::LogSubscriber.log_subscribers.find do |subscriber|
|
||||
subscriber.class == type
|
||||
end
|
||||
end
|
||||
|
||||
def subscribed?(component, type)
|
||||
!find(component, type).nil?
|
||||
end
|
||||
|
||||
# I don't know why this has to be so complicated, but it is. This code was taken from
|
||||
# lograge :/
|
||||
def unsubscribe!(component, type)
|
||||
subscriber = find(component, type)
|
||||
|
||||
if !subscriber
|
||||
raise "We could not find a log subscriber for #{component.inspect} of type #{type.inspect}"
|
||||
end
|
||||
|
||||
events = subscriber.public_methods(false).reject { |method| method.to_s == 'call' }
|
||||
events.each do |event|
|
||||
::ActiveSupport::Notifications.notifier.listeners_for("#{event}.#{component}").each do |listener|
|
||||
if listener.instance_variable_get('@delegate') == subscriber
|
||||
::ActiveSupport::Notifications.unsubscribe listener
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
require 'timber/config'
|
||||
require 'timber-rack/config'
|
||||
require 'timber-rails/config/action_view'
|
||||
require 'timber-rails/config/active_record'
|
||||
require 'timber-rails/config/action_controller'
|
||||
|
||||
Timber::Config.instance.define_singleton_method(:logrageify!) do
|
||||
integrations.action_controller.silence = true
|
||||
integrations.action_view.silence = true
|
||||
integrations.active_record.silence = true
|
||||
integrations.rack.http_events.collapse_into_single_event = true
|
||||
end
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
require "timber-rails/action_controller"
|
||||
|
||||
module Timber
|
||||
class Config
|
||||
# Convenience module for accessing the various `Timber::Integrations::*` classes
|
||||
# through the {Timber::Config} object. Timber couples configuration with the class
|
||||
# responsible for implementing it. This provides for a tighter design, but also
|
||||
# requires the user to understand and access the various classes. This module aims
|
||||
# to provide a simple ruby-like configuration interface for internal Timber classes.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# config = Timber::Config.instance
|
||||
# config.integrations.active_record.silence = true
|
||||
module Integrations
|
||||
extend self
|
||||
|
||||
# Convenience method for accessing the {Timber::Integrations::ActionController} class
|
||||
# specific configuration.
|
||||
#
|
||||
# @example
|
||||
# config = Timber::Config.instance
|
||||
# config.integrations.action_controller.silence = true
|
||||
def action_controller
|
||||
Timber::Integrations::ActionController
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
require "timber-rails/action_view"
|
||||
|
||||
module Timber
|
||||
class Config
|
||||
# Convenience module for accessing the various `Timber::Integrations::*` classes
|
||||
# through the {Timber::Config} object. Timber couples configuration with the class
|
||||
# responsible for implementing it. This provides for a tighter design, but also
|
||||
# requires the user to understand and access the various classes. This module aims
|
||||
# to provide a simple ruby-like configuration interface for internal Timber classes.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# config = Timber::Config.instance
|
||||
# config.integrations.active_record.silence = true
|
||||
module Integrations
|
||||
extend self
|
||||
|
||||
# Convenience method for accessing the {Timber::Integrations::ActionView} class
|
||||
# specific configuration.
|
||||
#
|
||||
# @example
|
||||
# config = Timber::Config.instance
|
||||
# config.integrations.action_view.silence = true
|
||||
def action_view
|
||||
Timber::Integrations::ActionView
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
require "timber-rails/active_record"
|
||||
|
||||
module Timber
|
||||
class Config
|
||||
# Convenience module for accessing the various `Timber::Integrations::*` classes
|
||||
# through the {Timber::Config} object. Timber couples configuration with the class
|
||||
# responsible for implementing it. This provides for a tighter design, but also
|
||||
# requires the user to understand and access the various classes. This module aims
|
||||
# to provide a simple ruby-like configuration interface for internal Timber classes.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# config = Timber::Config.instance
|
||||
# config.integrations.active_record.silence = true
|
||||
module Integrations
|
||||
extend self
|
||||
|
||||
# Convenience method for accessing the {Timber::Integrations::ActiveRecord} class
|
||||
# specific configuration.
|
||||
#
|
||||
# @example
|
||||
# config = Timber::Config.instance
|
||||
# config.integrations.active_record.silence = true
|
||||
def active_record
|
||||
Timber::Integrations::ActiveRecord
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
begin
|
||||
# Rails 3.2 requires you to require all of Rails before requiring
|
||||
# the exception wrapper.
|
||||
require "action_dispatch/middleware/exception_wrapper"
|
||||
rescue Exception
|
||||
end
|
||||
|
||||
require "timber/events/error"
|
||||
require "timber-rack/middleware"
|
||||
require "timber/util"
|
||||
|
||||
module Timber
|
||||
module Integrations
|
||||
module Rails
|
||||
# A Rack middleware that is reponsible for capturing exception and error events
|
||||
# {Timber::Events::Error}.
|
||||
class ErrorEvent < Timber::Integrations::Rack::Middleware
|
||||
# We determine this when the app loads to avoid the overhead on a per request basis.
|
||||
EXCEPTION_WRAPPER_TAKES_CLEANER = defined?(::ActionDispatch::ExceptionWrapper) &&
|
||||
!::ActionDispatch::ExceptionWrapper.instance_methods.include?(:env)
|
||||
|
||||
def call(env)
|
||||
begin
|
||||
status, headers, body = @app.call(env)
|
||||
rescue Exception => exception
|
||||
Config.instance.logger.fatal do
|
||||
backtrace = extract_backtrace(env, exception)
|
||||
Events::Error.new(
|
||||
name: exception.class.name,
|
||||
error_message: exception.message,
|
||||
backtrace: backtrace
|
||||
)
|
||||
end
|
||||
|
||||
raise exception
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
# Rails provides a backtrace cleaner, so we use it here.
|
||||
def extract_backtrace(env, exception)
|
||||
if defined?(::ActionDispatch::ExceptionWrapper)
|
||||
wrapper = if EXCEPTION_WRAPPER_TAKES_CLEANER
|
||||
request = Util::Request.new(env)
|
||||
backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
|
||||
::ActionDispatch::ExceptionWrapper.new(backtrace_cleaner, exception)
|
||||
else
|
||||
::ActionDispatch::ExceptionWrapper.new(env, exception)
|
||||
end
|
||||
|
||||
trace = wrapper.application_trace
|
||||
trace = wrapper.framework_trace if trace.empty?
|
||||
trace
|
||||
else
|
||||
exception.backtrace
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
module Timber
|
||||
# The Timber Logger behaves exactly like the standard Ruby `::Logger`, except that it supports a
|
||||
# transparent API for logging structured data and events.
|
||||
#
|
||||
# @example Basic logging
|
||||
# logger.info "Payment rejected for customer #{customer_id}"
|
||||
#
|
||||
# @example Logging an event
|
||||
# logger.info "Payment rejected", payment_rejected: {customer_id: customer_id, amount: 100}
|
||||
class Logger < ::Logger
|
||||
include ::ActiveSupport::LoggerThreadSafeLevel if defined?(::ActiveSupport::LoggerThreadSafeLevel)
|
||||
|
||||
if defined?(::ActiveSupport::LoggerSilence)
|
||||
include ::ActiveSupport::LoggerSilence
|
||||
elsif defined?(::LoggerSilence)
|
||||
include ::LoggerSilence
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
# The order is relevant
|
||||
require "timber-rails/overrides/active_support_3_tagged_logging"
|
||||
require "timber-rails/overrides/active_support_tagged_logging"
|
||||
require "timber-rails/overrides/active_support_buffered_logger"
|
||||
require "timber-rails/overrides/lograge"
|
||||
require "timber-rails/overrides/rails_stdout_logging"
|
||||
|
||||
module Timber
|
||||
# @private
|
||||
module Overrides
|
||||
end
|
||||
end
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
# Please note, this patch is merely an upgrade, backporting improved tagged logging code
|
||||
# from newer versions of Rails:
|
||||
# https://github.com/rails/rails/blob/5-1-stable/activesupport/lib/active_support/tagged_logging.rb
|
||||
# The behavior of tagged logging will not change in any way.
|
||||
#
|
||||
# This patch is specifically for Rails 3. The legacy approach to wrapping the logger in
|
||||
# ActiveSupport::TaggedLogging is rather poor, hence the reason it was changed entirely
|
||||
# for Rails 4 and 5. The problem is that ActiveSupport::TaggedLogging is a wrapping
|
||||
# class that entirely redefines the public API for the logger. As a result, any deviations
|
||||
# from this API in the logger are not exposed (such as accepting event data as a second argument).
|
||||
# This is assuming, so we're fixing it here.
|
||||
|
||||
begin
|
||||
require "active_support/tagged_logging"
|
||||
|
||||
# Instead of patching the class we're pulling the code from Rails master. This brings in
|
||||
# a number of improvements while also addressing the issue above.
|
||||
if ActiveSupport::TaggedLogging.instance_of?(Class)
|
||||
ActiveSupport.send(:remove_const, :TaggedLogging)
|
||||
|
||||
require "active_support/core_ext/module/delegation"
|
||||
require "active_support/core_ext/object/blank"
|
||||
require "logger"
|
||||
|
||||
module ActiveSupport
|
||||
# Wraps any standard Logger object to provide tagging capabilities.
|
||||
#
|
||||
# logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
|
||||
# logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
|
||||
# logger.tagged('BCX', "Jason") { logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
|
||||
# logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
|
||||
#
|
||||
# This is used by the default Rails.logger as configured by Railties to make
|
||||
# it easy to stamp log lines with subdomains, request ids, and anything else
|
||||
# to aid debugging of multi-user production applications.
|
||||
module TaggedLogging
|
||||
module Formatter # :nodoc:
|
||||
# This method is invoked when a log event occurs.
|
||||
def call(severity, timestamp, progname, msg)
|
||||
super(severity, timestamp, progname, "#{tags_text}#{msg}")
|
||||
end
|
||||
|
||||
def tagged(*tags)
|
||||
new_tags = push_tags(*tags)
|
||||
yield self
|
||||
ensure
|
||||
pop_tags(new_tags.size)
|
||||
end
|
||||
|
||||
def push_tags(*tags)
|
||||
tags.flatten.reject(&:blank?).tap do |new_tags|
|
||||
current_tags.concat new_tags
|
||||
end
|
||||
end
|
||||
|
||||
def pop_tags(size = 1)
|
||||
current_tags.pop size
|
||||
end
|
||||
|
||||
def clear_tags!
|
||||
current_tags.clear
|
||||
end
|
||||
|
||||
def current_tags
|
||||
# We use our object ID here to avoid conflicting with other instances
|
||||
thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}".freeze
|
||||
Thread.current[thread_key] ||= []
|
||||
end
|
||||
|
||||
def tags_text
|
||||
tags = current_tags
|
||||
if tags.any?
|
||||
tags.collect { |tag| "[#{tag}] " }.join
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Simple formatter which only displays the message.
|
||||
class SimpleFormatter < ::Logger::Formatter
|
||||
# This method is invoked when a log event occurs
|
||||
def call(severity, timestamp, progname, msg)
|
||||
"#{String === msg ? msg : msg.inspect}\n"
|
||||
end
|
||||
end
|
||||
|
||||
def self.new(logger)
|
||||
if logger.respond_to?(:formatter=) && logger.respond_to?(:formatter)
|
||||
# Ensure we set a default formatter so we aren't extending nil!
|
||||
logger.formatter ||= SimpleFormatter.new
|
||||
logger.formatter.extend Formatter
|
||||
end
|
||||
|
||||
logger.extend(self)
|
||||
end
|
||||
|
||||
delegate :push_tags, :pop_tags, :clear_tags!, to: :formatter
|
||||
|
||||
def tagged(*tags)
|
||||
formatter.tagged(*tags) { yield self }
|
||||
end
|
||||
|
||||
def flush
|
||||
clear_tags!
|
||||
super if defined?(super)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
rescue Exception
|
||||
end
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
# This adds a #formatter and #formatter= method to the legacy ActiveSupport::BufferedLogger
|
||||
# class. This bug was never resolved due to it being phased out past Rails >= 4.
|
||||
|
||||
begin
|
||||
require "active_support/buffered_logger"
|
||||
|
||||
class ActiveSupport::BufferedLogger
|
||||
def formatter
|
||||
if @log.respond_to?(:formatter)
|
||||
@log.formatter
|
||||
end
|
||||
end
|
||||
|
||||
def formatter=(value)
|
||||
if @log.respond_to?(:formatter=)
|
||||
@log.formatter = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
rescue Exception
|
||||
end
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
# This is an override instead of an integration because without this Timber would not
|
||||
# work properly if ActiveSupport::TaggedLogging is used.
|
||||
#
|
||||
# This is called after 'active_support_3_tagged_logging' where the constant is loaded and
|
||||
# replaced. I want to make sure we don't attempt to load it again undoing the patches
|
||||
# applied there.
|
||||
if defined?(ActiveSupport::TaggedLogging)
|
||||
module Timber
|
||||
module Overrides
|
||||
# @private
|
||||
module ActiveSupportTaggedLogging
|
||||
# @private
|
||||
module FormatterMethods
|
||||
def self.included(mod)
|
||||
mod.module_eval do
|
||||
alias_method :_timber_original_push_tags, :push_tags
|
||||
alias_method :_timber_original_pop_tags, :pop_tags
|
||||
|
||||
def call(severity, timestamp, progname, msg)
|
||||
if is_a?(Timber::Logger::Formatter)
|
||||
# Don't convert the message into a string
|
||||
super(severity, timestamp, progname, msg)
|
||||
else
|
||||
super(severity, timestamp, progname, "#{tags_text}#{msg}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @private
|
||||
module LoggerMethods
|
||||
def self.included(klass)
|
||||
klass.class_eval do
|
||||
def add(severity, message = nil, progname = nil, &block)
|
||||
if message.nil?
|
||||
if block_given?
|
||||
message = block.call
|
||||
else
|
||||
message = progname
|
||||
progname = nil #No instance variable for this like Logger
|
||||
end
|
||||
end
|
||||
if @logger.is_a?(Timber::Logger)
|
||||
@logger.add(severity, message, progname)
|
||||
else
|
||||
@logger.add(severity, "#{tags_text}#{message}", progname)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if defined?(::ActiveSupport::TaggedLogging::Formatter)
|
||||
if !::ActiveSupport::TaggedLogging::Formatter.include?(FormatterMethods)
|
||||
::ActiveSupport::TaggedLogging::Formatter.send(:include, FormatterMethods)
|
||||
end
|
||||
else
|
||||
if !::ActiveSupport::TaggedLogging.include?(LoggerMethods)
|
||||
::ActiveSupport::TaggedLogging.send(:include, LoggerMethods)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
# Timber and lograge are not compatible installed together. Using lograge
|
||||
# with the Timber.io *service* is perfectly fine, but not with the Timber *gem*.
|
||||
#
|
||||
# Timber does ship with a {Timber::Config#logrageify!} option that configures
|
||||
# Timber to behave similarly to Lograge (silencing various logs). Check out
|
||||
# the aforementioned method or the README for info.
|
||||
begin
|
||||
require "lograge"
|
||||
|
||||
module Lograge
|
||||
module_function
|
||||
|
||||
def setup(app)
|
||||
return true
|
||||
end
|
||||
end
|
||||
rescue Exception
|
||||
end
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
# See https://github.com/heroku/rails_stdout_logging
|
||||
# I have no idea why this library was created, but most Heroku / Rails apps use it.
|
||||
# This library completely obliterates any logger configuration you set.
|
||||
# So this patch fixes that.
|
||||
|
||||
begin
|
||||
require "rails_stdout_logging"
|
||||
|
||||
module RailsStdoutLogging
|
||||
class Rails2 < Rails
|
||||
def self.set_logger
|
||||
end
|
||||
end
|
||||
|
||||
class Rails3 < Rails
|
||||
def self.set_logger(config)
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue Exception
|
||||
end
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
module Timber
|
||||
module Integrations
|
||||
module Rails
|
||||
# Disables the default rail's rack logging. Note, we cannot simply uninstall this rack
|
||||
# middleware because rails couples this with ActiveSupport instrumentation. As such,
|
||||
# we simply disable the logger and let our Rack middleware handle the logging.
|
||||
#
|
||||
# See: https://github.com/rails/rails/blob/80e66cc4d90bf8c15d1a5f6e3152e90147f00772/railties/lib/rails/rack/logger.rb#L34
|
||||
#
|
||||
# @private
|
||||
class RackLogger < Integrator
|
||||
|
||||
# @private
|
||||
module InstanceMethods
|
||||
LOGGER = ::Logger.new(nil)
|
||||
|
||||
def self.included(klass)
|
||||
klass.class_eval do
|
||||
private
|
||||
if ::Rails::VERSION::MAJOR == 3
|
||||
# Rails 3.2 calls Rails.logger directly in call_app, so we
|
||||
# will just replace it with a version that doesn't
|
||||
def call_app(_, env)
|
||||
# Put some space between requests in development logs.
|
||||
if ::Rails.env.development?
|
||||
::Rails.logger.info ''
|
||||
::Rails.logger.info ''
|
||||
end
|
||||
@app.call(env)
|
||||
ensure
|
||||
ActiveSupport::LogSubscriber.flush_all!
|
||||
end
|
||||
end
|
||||
|
||||
# Rails > 3.2 uses a logger method. Muting logs is accomplished by
|
||||
# passing a dummy logger instance with a nil log device.
|
||||
def logger
|
||||
LOGGER
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def initialize
|
||||
require "rails/rack/logger"
|
||||
rescue LoadError => e
|
||||
raise RequirementNotMetError.new(e.message)
|
||||
end
|
||||
|
||||
def integrate!
|
||||
return true if ::Rails::Rack::Logger.include?(InstanceMethods)
|
||||
|
||||
::Rails::Rack::Logger.send(:include, InstanceMethods)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
module Timber
|
||||
module Frameworks
|
||||
# Module for Rails specific code, such as the Railtie and any methods that assist
|
||||
# with Rails setup.
|
||||
module Rails
|
||||
# Installs Timber into your Rails app automatically.
|
||||
class Railtie < ::Rails::Railtie
|
||||
config.timber = Config.instance
|
||||
|
||||
config.before_initialize do
|
||||
Timber::Config.instance.logger = Proc.new { ::Rails.logger }
|
||||
end
|
||||
|
||||
# Must be loaded after initializers so that we respect any Timber configuration set
|
||||
initializer(:timber, before: :build_middleware_stack, after: :load_config_initializers) do
|
||||
Integrations::Rails.integrate!
|
||||
|
||||
# Install the Rack middlewares so that we capture structured data instead of
|
||||
# raw text logs.
|
||||
Integrations::Rails.middlewares.collect do |middleware_class|
|
||||
config.app_middleware.use middleware_class
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
require "timber/contexts/session"
|
||||
require "timber-rack/middleware"
|
||||
|
||||
module Timber
|
||||
module Integrations
|
||||
module Rails
|
||||
# A Rack middleware that is responsible for adding the Session context
|
||||
# {Timber::Contexts::Session}.
|
||||
class SessionContext < Timber::Integrations::Rack::Middleware
|
||||
def call(env)
|
||||
id = get_session_id(env)
|
||||
if id
|
||||
context = Contexts::Session.new(id: id)
|
||||
CurrentContext.add(context.to_hash)
|
||||
end
|
||||
@app.call(env)
|
||||
end
|
||||
|
||||
private
|
||||
def get_session_id(env)
|
||||
session_key = ::Rails.application.config.session_options[:key]
|
||||
request = ::ActionDispatch::Request.new(env)
|
||||
extract_from_cookie(request, session_key)
|
||||
rescue Exception => e
|
||||
nil
|
||||
end
|
||||
|
||||
def extract_from_cookie(request, session_key)
|
||||
data = request
|
||||
.cookie_jar
|
||||
.signed_or_encrypted[session_key] || {}
|
||||
data["session_id"]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
module Timber
|
||||
module Integrations
|
||||
module Rails
|
||||
VERSION = "1.0.2"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
# Testing
|
||||
|
||||
To get started:
|
||||
|
||||
```shell
|
||||
bundle install
|
||||
```
|
||||
|
||||
Be sure to install specific Gemfile dependencies:
|
||||
|
||||
```
|
||||
BUNDLE_GEMFILE=gemfiles/rails-4.2.gemfile bundle install
|
||||
```
|
||||
|
||||
You can run tests like this:
|
||||
|
||||
```shell
|
||||
BUNDLE_GEMFILE=gemfiles/rails-4.2.gemfile bundle exec rspec
|
||||
```
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
# Base
|
||||
# require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
# Testing
|
||||
require 'rspec'
|
||||
require 'rspec/its'
|
||||
require 'rspec/mocks'
|
||||
|
||||
# Support files, order is relevant
|
||||
require File.join(File.dirname(__FILE__), 'support', 'socket_hostname')
|
||||
require File.join(File.dirname(__FILE__), 'support', 'timecop')
|
||||
require File.join(File.dirname(__FILE__), 'support', 'webmock')
|
||||
require File.join(File.dirname(__FILE__), 'support', 'timber')
|
||||
|
||||
# Load framework files after we've setup everything
|
||||
if !ENV["RAILS_23"]
|
||||
require File.join(File.dirname(__FILE__), 'support', 'rails')
|
||||
require File.join(File.dirname(__FILE__), 'support', 'action_controller')
|
||||
require File.join(File.dirname(__FILE__), 'support', 'active_record')
|
||||
end
|
||||
|
||||
RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = 5_000
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.color = true
|
||||
config.order = :random
|
||||
config.warnings = false
|
||||
|
||||
# Enable flags like --only-failures and --next-failure
|
||||
config.example_status_persistence_file_path = ".rspec_status"
|
||||
|
||||
# Disable RSpec exposing methods globally on `Module` and `main`
|
||||
config.disable_monkey_patching!
|
||||
|
||||
config.expect_with :rspec do |c|
|
||||
c.syntax = :expect
|
||||
end
|
||||
end
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
require "action_controller"
|
||||
::ActionController::Base.prepend_view_path("#{File.dirname(__FILE__)}/rails/templates")
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
require 'active_record'
|
||||
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
||||
ActiveRecord::Schema.define do
|
||||
self.verbose = false
|
||||
|
||||
create_table :organizations, :force => true do |t|
|
||||
t.string :name
|
||||
|
||||
t.timestamps :null => false
|
||||
end
|
||||
|
||||
create_table :users, :force => true do |t|
|
||||
t.integer :age
|
||||
t.string :email
|
||||
t.string :first_name
|
||||
|
||||
t.timestamps :null => false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Organization < ::ActiveRecord::Base
|
||||
end
|
||||
|
||||
class User < ::ActiveRecord::Base
|
||||
end
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
require "rails"
|
||||
require "timber-rails/railtie"
|
||||
|
||||
# Defualt the rails logger to nothing, each test shoould be
|
||||
# responsible for setting up the logger
|
||||
logger = Timber::Logger.new(nil) # change to STDOUT to see rails logs
|
||||
Rails.logger = logger
|
||||
|
||||
class RailsApp < Rails::Application
|
||||
if ::Rails.version =~ /^3\./
|
||||
config.secret_token = '1e05af2b349457936a41427e63450937'
|
||||
else
|
||||
config.secret_key_base = '1e05af2b349457936a41427e63450937'
|
||||
end
|
||||
|
||||
# This ensures our tests fail, otherwise exceptions get swallowed by ActionDispatch::DebugExceptions
|
||||
config.action_dispatch.show_exceptions = false
|
||||
config.active_support.deprecation = :stderr
|
||||
config.eager_load = false
|
||||
end
|
||||
|
||||
RailsApp.initialize!
|
||||
|
||||
module Support
|
||||
module Rails
|
||||
def dispatch_rails_request(path, additional_env_options = {})
|
||||
application = ::Rails.application
|
||||
env = application.respond_to?(:env_config) ? application.env_config.clone : application.env_defaults.clone
|
||||
env["rack.request.cookie_hash"] = {}.with_indifferent_access
|
||||
env["CONTENT_LENGTH"] = 100
|
||||
env["REMOTE_ADDR"] = "123.456.789.10"
|
||||
env["HTTP_X_REQUEST_ID"] = "unique-request-id-1234"
|
||||
env["action_dispatch.request_id"] = env["HTTP_X_REQUEST_ID"]
|
||||
env = env.merge(additional_env_options)
|
||||
::Rack::MockRequest.new(application).get(path, env)
|
||||
end
|
||||
|
||||
def with_rails_logger(logger)
|
||||
old_logger = ::Rails.logger
|
||||
|
||||
# We have to set these again because rails set's these after initialization.
|
||||
# Since we've already booted the rails app we need to update them all as we
|
||||
# change the logger.
|
||||
#
|
||||
# You can see here that they use simple class attribute, hence the reason we need
|
||||
# to update all of them: https://github.com/rails/rails/blob/700ec897f97c60016ad748236bf3a49ef15a20de/actionview/lib/action_view/base.rb#L157
|
||||
::ActionCable::Server::Base.logger = logger if defined?(::ActionCable::Server::Base) && ::ActionCable::Server::Base.respond_to?(:logger=)
|
||||
::ActionController::Base.logger = logger if defined?(::ActionController::Base) && ::ActionController::Base.respond_to?(:logger=)
|
||||
::ActionMailer::Base.logger = logger if defined?(::ActionMailer::Base) && ::ActionMailer::Base.respond_to?(:logger=)
|
||||
::ActionView::Base.logger = logger if defined?(::ActionView::Base) && ::ActionView::Base.respond_to?(:logger=)
|
||||
::ActiveRecord::Base.logger = logger if defined?(::ActiveRecord::Base) && ::ActiveRecord::Base.respond_to?(:logger=)
|
||||
::Rails.logger = logger
|
||||
|
||||
yield
|
||||
|
||||
::Rails.logger = old_logger
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# This is necessary as tests use Timber::Config.send(:new) to create
|
||||
# an instance of the Config class instead of the Timber::Config
|
||||
# singleton.
|
||||
module Timber
|
||||
class Config
|
||||
def logrageify!
|
||||
integrations.action_controller.silence = true
|
||||
integrations.action_view.silence = true
|
||||
integrations.active_record.silence = true
|
||||
integrations.rack.http_events.collapse_into_single_event = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.include Support::Rails
|
||||
end
|
||||
|
|
@ -1 +0,0 @@
|
|||
I am a partial
|
||||
|
|
@ -1 +0,0 @@
|
|||
I am a template
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
require "socket"
|
||||
|
||||
# Stub out the hostname for tests only. This can't use a normal stub in the
|
||||
# test life cycle since our test rails app is loaded once upon initialization.
|
||||
# In other words, the rails app gets loaded with the server context inserted
|
||||
# before any tests are run.
|
||||
|
||||
class ::Socket
|
||||
def self.gethostname
|
||||
"computer-name.domain.com"
|
||||
end
|
||||
end
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
require "timber-rails"
|
||||
require "timber"
|
||||
require "timber/config"
|
||||
|
||||
config = Timber::Config.instance
|
||||
config.environment = "production"
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
require 'timecop'
|
||||
|
||||
Timecop.safe_mode = true
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
require 'webmock/rspec'
|
||||
|
||||
WebMock.disable_net_connect!
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
require "spec_helper"
|
||||
|
||||
RSpec.describe Timber::Integrations::ActionController::LogSubscriber do
|
||||
let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
|
||||
let(:io) { StringIO.new }
|
||||
let(:logger) do
|
||||
logger = Timber::Logger.new(io)
|
||||
logger.level = ::Logger::INFO
|
||||
logger
|
||||
end
|
||||
|
||||
describe "#insert!" do
|
||||
around(:each) do |example|
|
||||
class LogSubscriberController < ActionController::Base
|
||||
layout nil
|
||||
|
||||
def index
|
||||
render json: {}
|
||||
end
|
||||
|
||||
def method_for_action(action_name)
|
||||
action_name
|
||||
end
|
||||
end
|
||||
|
||||
::RailsApp.routes.draw do
|
||||
get 'log_subscriber' => 'log_subscriber#index'
|
||||
end
|
||||
|
||||
with_rails_logger(logger) do
|
||||
Timecop.freeze(time) { example.run }
|
||||
end
|
||||
|
||||
Object.send(:remove_const, :LogSubscriberController)
|
||||
end
|
||||
|
||||
it "should log a controller_call event once" do
|
||||
# Rails uses this to calculate the view runtime below
|
||||
allow(Benchmark).to receive(:ms).and_return(1).and_yield
|
||||
|
||||
dispatch_rails_request("/log_subscriber?query=value")
|
||||
lines = clean_lines(io.string.split("\n"))
|
||||
expect(lines.length).to eq(3)
|
||||
expect(lines[1]).to include("Processing by LogSubscriberController#index as HTML")
|
||||
expect(lines[1]).to include('"controller_called":{"controller":"LogSubscriberController","action":"index","params_json"')
|
||||
end
|
||||
|
||||
# Remove blank lines since Rails does this to space out requests in the logs
|
||||
def clean_lines(lines)
|
||||
lines.select { |line| !line.start_with?(" @metadat") }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
require "spec_helper"
|
||||
|
||||
RSpec.describe Timber::Integrations::ActionDispatch::DebugExceptions do
|
||||
let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
|
||||
let(:io) { StringIO.new }
|
||||
let(:logger) do
|
||||
logger = Timber::Logger.new(io)
|
||||
logger.level = ::Logger::DEBUG
|
||||
logger
|
||||
end
|
||||
|
||||
describe "#insert!" do
|
||||
around(:each) do |example|
|
||||
class ExceptionController < ActionController::Base
|
||||
layout nil
|
||||
|
||||
def index
|
||||
raise "boom"
|
||||
end
|
||||
|
||||
def method_for_action(action_name)
|
||||
action_name
|
||||
end
|
||||
end
|
||||
|
||||
::RailsApp.routes.draw do
|
||||
get 'exception' => 'exception#index'
|
||||
end
|
||||
|
||||
with_rails_logger(logger) do
|
||||
Timecop.freeze(time) { example.run }
|
||||
end
|
||||
|
||||
Object.send(:remove_const, :ExceptionController)
|
||||
end
|
||||
|
||||
it "should log an exception event once" do
|
||||
expect { dispatch_rails_request("/exception") }.to raise_error(RuntimeError)
|
||||
|
||||
lines = clean_lines(io.string.split("\n"))
|
||||
expect(lines.length).to eq(3)
|
||||
expect(lines[2]).to include('RuntimeError (boom)')
|
||||
expect(lines[2]).to include('fatal')
|
||||
expect(lines[2]).to include("\"error\":{\"name\":\"RuntimeError\",\"message\":\"boom\",\"backtrace_json\":\"[")
|
||||
end
|
||||
|
||||
# Remove blank lines since Rails does this to space out requests in the logs
|
||||
def clean_lines(lines)
|
||||
lines.select { |line| !line.start_with?(" @metadat") }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
require "spec_helper"
|
||||
|
||||
RSpec.describe Timber::Integrations::ActionView::LogSubscriber do
|
||||
let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
|
||||
let(:io) { StringIO.new }
|
||||
let(:logger) do
|
||||
logger = Timber::Logger.new(io)
|
||||
logger.level = ::Logger::WARN
|
||||
logger
|
||||
end
|
||||
|
||||
describe "insert!" do
|
||||
around(:each) do |example|
|
||||
class ActionViewLogSubscriberController < ActionController::Base
|
||||
layout nil
|
||||
|
||||
def index
|
||||
render template: "template"
|
||||
end
|
||||
|
||||
def method_for_action(action_name)
|
||||
action_name
|
||||
end
|
||||
end
|
||||
|
||||
::RailsApp.routes.draw do
|
||||
get 'action_view_log_subscriber' => 'action_view_log_subscriber#index'
|
||||
end
|
||||
|
||||
with_rails_logger(logger) do
|
||||
Timecop.freeze(time) { example.run }
|
||||
end
|
||||
|
||||
Object.send(:remove_const, :ActionViewLogSubscriberController)
|
||||
end
|
||||
|
||||
describe "#render_template" do
|
||||
it "should not log if the level is not sufficient" do
|
||||
dispatch_rails_request("/action_view_log_subscriber")
|
||||
expect(io.string).to eq("")
|
||||
end
|
||||
|
||||
context "with an info level" do
|
||||
around(:each) do |example|
|
||||
old_level = logger.level
|
||||
logger.level = ::Logger::INFO
|
||||
example.run
|
||||
logger.level = old_level
|
||||
end
|
||||
|
||||
it "should log a template render event once" do
|
||||
dispatch_rails_request("/action_view_log_subscriber")
|
||||
lines = clean_lines(io.string.split("\n"))
|
||||
expect(lines[2].strip).to match(/Rendered spec\/support\/rails\/templates\/template.html \(\d+\.\d+ms\)/)
|
||||
expect(lines[2]).to include("\"template_rendered\":{\"name\":\"spec/support/rails/templates/template.html\"")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if defined?(described_class::TimberLogSubscriber)
|
||||
describe described_class::TimberLogSubscriber do
|
||||
let(:event) do
|
||||
event = Struct.new(:duration, :payload)
|
||||
event.new(2.0, identifier: "path/to/template.html")
|
||||
end
|
||||
|
||||
around(:each) do |example|
|
||||
old_level = logger.level
|
||||
logger.level = ::Logger::INFO
|
||||
example.run
|
||||
logger.level = old_level
|
||||
end
|
||||
|
||||
describe "#render_template" do
|
||||
it "should render the collection" do
|
||||
log_subscriber = described_class.new
|
||||
allow(log_subscriber).to receive(:logger).and_return(logger)
|
||||
log_subscriber.render_template(event)
|
||||
expect(io.string.strip).to include("Rendered path/to/template.html (2.0ms)")
|
||||
end
|
||||
end
|
||||
|
||||
describe "#render_partial" do
|
||||
it "should render the collection" do
|
||||
log_subscriber = described_class.new
|
||||
allow(log_subscriber).to receive(:logger).and_return(logger)
|
||||
log_subscriber.render_partial(event)
|
||||
expect(io.string.strip).to include("Rendered path/to/template.html (2.0ms)")
|
||||
end
|
||||
end
|
||||
|
||||
describe "#render_collection" do
|
||||
it "should render the collection" do
|
||||
log_subscriber = described_class.new
|
||||
allow(log_subscriber).to receive(:logger).and_return(logger)
|
||||
log_subscriber.render_collection(event)
|
||||
|
||||
if log_subscriber.respond_to?(:render_count, true)
|
||||
expect(io.string.strip).to include("Rendered collection of path/to/template.html [ times] (2.0ms)")
|
||||
else
|
||||
expect(io.string.strip).to include("Rendered path/to/template.html (2.0ms)")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Remove blank lines since Rails does this to space out requests in the logs
|
||||
def clean_lines(lines)
|
||||
lines.select { |line| !line.start_with?(" @metadata") }
|
||||
end
|
||||
end
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
require "spec_helper"
|
||||
|
||||
RSpec.describe Timber::Integrations::ActiveRecord::LogSubscriber do
|
||||
let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
|
||||
let(:io) { StringIO.new }
|
||||
let(:logger) do
|
||||
logger = Timber::Logger.new(io)
|
||||
logger.level = ::Logger::INFO
|
||||
logger
|
||||
end
|
||||
|
||||
describe "#insert!" do
|
||||
around(:each) do |example|
|
||||
with_rails_logger(logger) do
|
||||
Timecop.freeze(time) { example.run }
|
||||
end
|
||||
end
|
||||
|
||||
it "should not log if the level is not sufficient" do
|
||||
ActiveRecord::Base.connection.execute("select * from users")
|
||||
expect(io.string).to eq("")
|
||||
end
|
||||
|
||||
context "with an info level" do
|
||||
around(:each) do |example|
|
||||
old_level = logger.level
|
||||
logger.level = ::Logger::DEBUG
|
||||
example.run
|
||||
logger.level = old_level
|
||||
end
|
||||
|
||||
it "should log the sql query" do
|
||||
ActiveRecord::Base.connection.execute("select * from users")
|
||||
# Rails 4.X adds random spaces :/
|
||||
string = io.string.gsub(" ORDER BY", " ORDER BY")
|
||||
string = string.gsub(" ORDER BY", " ORDER BY")
|
||||
expect(string).to include("select * from users")
|
||||
expect(string).to include("duration_ms")
|
||||
expect(string).to include("\"level\":\"debug\"")
|
||||
expect(string).to include("\"sql_query_executed\":")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
require "singleton"
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe Timber::Config, :rails_23 => true do
|
||||
let(:config) { Timber::Config.send(:new) }
|
||||
|
||||
describe ".logrageify!" do
|
||||
it "should logrageify!" do
|
||||
expect(Timber::Integrations::ActionController.silence?).to eq(false)
|
||||
expect(Timber::Integrations::ActionView.silence?).to eq(false)
|
||||
expect(Timber::Integrations::ActiveRecord.silence?).to eq(false)
|
||||
expect(Timber::Integrations::Rack::HTTPEvents.collapse_into_single_event?).to eq(false)
|
||||
|
||||
|
||||
config.logrageify!
|
||||
|
||||
expect(Timber::Integrations::ActionController.silence?).to eq(true)
|
||||
expect(Timber::Integrations::ActionView.silence?).to eq(true)
|
||||
expect(Timber::Integrations::ActiveRecord.silence?).to eq(true)
|
||||
expect(Timber::Integrations::Rack::HTTPEvents.collapse_into_single_event?).to eq(true)
|
||||
|
||||
|
||||
# Reset
|
||||
Timber::Integrations::ActionController.silence = false
|
||||
Timber::Integrations::ActionView.silence = false
|
||||
Timber::Integrations::ActiveRecord.silence = false
|
||||
Timber::Integrations::Rack::HTTPEvents.collapse_into_single_event = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
require "spec_helper"
|
||||
|
||||
RSpec.describe Timber::Integrations::Rails::ErrorEvent do
|
||||
let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
|
||||
let(:io) { StringIO.new }
|
||||
let(:logger) do
|
||||
logger = Timber::Logger.new(io)
|
||||
logger.level = ::Logger::INFO
|
||||
logger
|
||||
end
|
||||
|
||||
around(:each) do |example|
|
||||
class RackErrorController < ActionController::Base
|
||||
layout nil
|
||||
|
||||
hook_name = respond_to?(:before_action) ? "before_action" : "before_filter"
|
||||
send(hook_name) do
|
||||
raise "Boom!"
|
||||
end
|
||||
|
||||
def index
|
||||
Thread.current[:_timber_context_snapshot] = Timber::CurrentContext.instance.snapshot
|
||||
render json: {}
|
||||
end
|
||||
|
||||
def method_for_action(action_name)
|
||||
action_name
|
||||
end
|
||||
end
|
||||
|
||||
::RailsApp.routes.draw do
|
||||
get '/rack_error' => 'rack_error#index'
|
||||
end
|
||||
|
||||
with_rails_logger(logger) do
|
||||
Timecop.freeze(time) { example.run }
|
||||
end
|
||||
|
||||
Object.send(:remove_const, :RackErrorController)
|
||||
end
|
||||
|
||||
describe "#process" do
|
||||
it "should log the exception" do
|
||||
allow(Benchmark).to receive(:ms).and_return(1).and_yield
|
||||
|
||||
expect { dispatch_rails_request("/rack_error") }.to raise_error(RuntimeError)
|
||||
|
||||
lines = clean_lines(io.string.split("\n"))
|
||||
|
||||
expect(lines.length).to eq(3)
|
||||
|
||||
expect(lines[0]).to include("Started GET \\\"/rack_error\\\"")
|
||||
expect(lines[1]).to include("Processing by RackErrorController#index as HTML")
|
||||
expect(lines[2]).to include("RuntimeError (Boom!)")
|
||||
end
|
||||
end
|
||||
|
||||
# Remove blank lines since Rails does this to space out requests in the logs
|
||||
def clean_lines(lines)
|
||||
lines.select { |line| !line.start_with?(" @metadat") }
|
||||
end
|
||||
end
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
require "spec_helper"
|
||||
|
||||
RSpec.describe Timber::Integrations::Rack::HTTPContext do
|
||||
let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
|
||||
let(:io) { StringIO.new }
|
||||
let(:logger) do
|
||||
logger = Timber::Logger.new(io)
|
||||
logger.level = ::Logger::INFO
|
||||
logger
|
||||
end
|
||||
|
||||
around(:each) do |example|
|
||||
class RackHttpController < ActionController::Base
|
||||
layout nil
|
||||
|
||||
def index
|
||||
Thread.current[:_timber_context_snapshot] = Timber::CurrentContext.instance.snapshot
|
||||
render json: {}
|
||||
end
|
||||
|
||||
def method_for_action(action_name)
|
||||
action_name
|
||||
end
|
||||
end
|
||||
|
||||
::RailsApp.routes.draw do
|
||||
get '/rack_http' => 'rack_http#index'
|
||||
end
|
||||
|
||||
with_rails_logger(logger) do
|
||||
Timecop.freeze(time) { example.run }
|
||||
end
|
||||
|
||||
Object.send(:remove_const, :RackHttpController)
|
||||
end
|
||||
|
||||
describe "#process" do
|
||||
it "should set the context" do
|
||||
allow(Benchmark).to receive(:ms).and_return(1).and_yield
|
||||
|
||||
dispatch_rails_request("/rack_http")
|
||||
http_context = Thread.current[:_timber_context_snapshot][:http]
|
||||
|
||||
expect(http_context).to eq({:host => "example.org", :method=>"GET", :path=>"/rack_http", :remote_addr=>"123.456.789.10", :request_id=>"unique-request-id-1234"})
|
||||
|
||||
lines = clean_lines(io.string.split("\n"))
|
||||
expect(lines.length).to eq(3)
|
||||
lines.each do |line|
|
||||
expect(line).to include("\"http\":{\"host\":\"example.org\",\"method\":\"GET\",\"path\":\"/rack_http\",\"remote_addr\":\"123.456.789.10\",\"request_id\":\"unique-request-id-1234\"}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Remove blank lines since Rails does this to space out requests in the logs
|
||||
def clean_lines(lines)
|
||||
lines.select { |line| !line.start_with?(" @metadat") }
|
||||
end
|
||||
end
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
require "spec_helper"
|
||||
|
||||
RSpec.describe Timber::Integrations::Rack::HTTPEvents do
|
||||
let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
|
||||
let(:io) { StringIO.new }
|
||||
let(:logger) do
|
||||
logger = Timber::Logger.new(io)
|
||||
logger.level = ::Logger::INFO
|
||||
logger
|
||||
end
|
||||
|
||||
around(:each) do |example|
|
||||
class RackHttpController < ActionController::Base
|
||||
layout nil
|
||||
|
||||
def index
|
||||
Thread.current[:_timber_context_snapshot] = Timber::CurrentContext.instance.snapshot
|
||||
render json: {}
|
||||
end
|
||||
|
||||
def method_for_action(action_name)
|
||||
action_name
|
||||
end
|
||||
end
|
||||
|
||||
::RailsApp.routes.draw do
|
||||
get '/rack_http' => 'rack_http#index'
|
||||
end
|
||||
|
||||
with_rails_logger(logger) do
|
||||
Timecop.freeze(time) { example.run }
|
||||
end
|
||||
|
||||
Object.send(:remove_const, :RackHttpController)
|
||||
end
|
||||
|
||||
describe "#process" do
|
||||
it "should log the events" do
|
||||
allow(Benchmark).to receive(:ms).and_return(1).and_yield
|
||||
|
||||
dispatch_rails_request("/rack_http")
|
||||
|
||||
lines = clean_lines(io.string.split("\n"))
|
||||
expect(lines.length).to eq(3)
|
||||
|
||||
expect(lines[0]).to include("Started GET \\\"/rack_http\\\"")
|
||||
expect(lines[1]).to include("Processing by RackHttpController#index as HTML")
|
||||
expect(lines[2]).to include("Completed 200 OK in 0.0ms")
|
||||
end
|
||||
|
||||
context "with the route silenced" do
|
||||
around(:each) do |example|
|
||||
described_class.silence_request = lambda do |rack_env, rack_request|
|
||||
rack_request.path == "/rack_http"
|
||||
end
|
||||
|
||||
example.run
|
||||
|
||||
described_class.silence_request = nil
|
||||
end
|
||||
|
||||
it "should silence the logs" do
|
||||
allow(Benchmark).to receive(:ms).and_return(1).and_yield
|
||||
|
||||
dispatch_rails_request("/rack_http")
|
||||
|
||||
lines = clean_lines(io.string.split("\n"))
|
||||
expect(lines.length).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "collapsed into a single event" do
|
||||
around(:each) do |example|
|
||||
described_class.collapse_into_single_event = true
|
||||
|
||||
example.run
|
||||
|
||||
described_class.collapse_into_single_event = nil
|
||||
end
|
||||
|
||||
it "should silence the logs" do
|
||||
allow(Benchmark).to receive(:ms).and_return(1).and_yield
|
||||
|
||||
dispatch_rails_request("/rack_http")
|
||||
|
||||
lines = clean_lines(io.string.split("\n"))
|
||||
expect(lines.length).to eq(2)
|
||||
|
||||
expect(lines[0]).to include("Processing by RackHttpController#index as HTML")
|
||||
expect(lines[1]).to include("GET /rack_http completed with 200 OK in 0.0ms")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Remove blank lines since Rails does this to space out requests in the logs
|
||||
def clean_lines(lines)
|
||||
lines.select { |line| !line.start_with?(" @metadat") }
|
||||
end
|
||||
end
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
require "spec_helper"
|
||||
|
||||
RSpec.describe Timber::Logger, :rails_23 => true do
|
||||
describe "#silence" do
|
||||
let(:io) { StringIO.new }
|
||||
let(:logger) { Timber::Logger.new(io) }
|
||||
|
||||
it "should silence the logs" do
|
||||
logger.silence do
|
||||
logger.info("test")
|
||||
end
|
||||
|
||||
expect(io.string).to eq("")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
require "spec_helper"
|
||||
|
||||
RSpec.describe Timber::Integrations::Rails::RackLogger do
|
||||
describe described_class::InstanceMethods do
|
||||
let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
|
||||
let(:io) { StringIO.new }
|
||||
let(:logger) do
|
||||
logger = Timber::Logger.new(io)
|
||||
logger.level = ::Logger::INFO
|
||||
logger
|
||||
end
|
||||
|
||||
around(:each) do |example|
|
||||
class RailsRackLoggerController < ActionController::Base
|
||||
layout nil
|
||||
|
||||
def index
|
||||
render json: {}
|
||||
end
|
||||
|
||||
def method_for_action(action_name)
|
||||
action_name
|
||||
end
|
||||
end
|
||||
|
||||
::RailsApp.routes.draw do
|
||||
get '/rails_rack_logger' => 'rails_rack_logger#index'
|
||||
end
|
||||
|
||||
with_rails_logger(logger) do
|
||||
Timecop.freeze(time) { example.run }
|
||||
end
|
||||
|
||||
Object.send(:remove_const, :RailsRackLoggerController)
|
||||
end
|
||||
|
||||
describe "#started_request_message" do
|
||||
it "should mute the default rails logs" do
|
||||
allow(::Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new("production")) # Rails 3.2.X
|
||||
|
||||
dispatch_rails_request("/rails_rack_logger")
|
||||
|
||||
lines = clean_lines(io.string.split("\n"))
|
||||
expect(lines.length).to eq(3)
|
||||
expect(lines[0]).to include("Started GET \\\"/rails_rack_logger\\\"")
|
||||
expect(lines[1]).to include("Processing by RailsRackLoggerController#index as HTML")
|
||||
expect(lines[2]).to include("Completed 200 OK in 0.0ms")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Remove blank lines since Rails does this to space out requests in the logs
|
||||
def clean_lines(lines)
|
||||
lines.select { |line| !line.start_with?(" @metadat") }
|
||||
end
|
||||
end
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
require "spec_helper"
|
||||
|
||||
RSpec.describe Timber::Integrations::Rails::SessionContext do
|
||||
let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
|
||||
let(:io) { StringIO.new }
|
||||
let(:logger) do
|
||||
logger = Timber::Logger.new(io)
|
||||
logger.level = ::Logger::INFO
|
||||
logger
|
||||
end
|
||||
end
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
require "spec_helper"
|
||||
|
||||
RSpec.describe ActiveSupport::TaggedLogging, :rails_23 => true do
|
||||
describe "#new" do
|
||||
let(:io) { StringIO.new }
|
||||
|
||||
it "should instantiate for Timber::Logger object" do
|
||||
ActiveSupport::TaggedLogging.new(Timber::Logger.new(io))
|
||||
end
|
||||
|
||||
if defined?(ActiveSupport::BufferedLogger)
|
||||
it "should instantiate for a ActiveSupport::BufferedLogger object" do
|
||||
ActiveSupport::TaggedLogging.new(ActiveSupport::BufferedLogger.new(io))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#info" do
|
||||
let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
|
||||
let(:io) { StringIO.new }
|
||||
let(:logger) { ActiveSupport::TaggedLogging.new(Timber::Logger.new(io)) }
|
||||
|
||||
it "should accept events as the second argument" do
|
||||
logger.info("SQL query", payment_rejected: {customer_id: "abcd1234", amount: 100, reason: "Card expired"})
|
||||
expect(io.string).to include("SQL query")
|
||||
expect(io.string).to include("\"payment_rejected\":")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
# stub: timber-rails 1.0.2 ruby lib
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = "timber-rails".freeze
|
||||
s.version = "1.0.2"
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
||||
s.metadata = { "changelog_uri" => "https://github.com/timberio/timber-ruby-rails/blob/master/README.md", "homepage_uri" => "https://docs.timber.io/languages/ruby/", "source_code_uri" => "https://github.com/timberio/timber-ruby-rails" } if s.respond_to? :metadata=
|
||||
s.require_paths = ["lib".freeze]
|
||||
s.authors = ["Timber Technologies, Inc.".freeze]
|
||||
s.bindir = "exe".freeze
|
||||
s.date = "2020-06-01"
|
||||
s.email = ["hi@timber.io".freeze]
|
||||
s.files = [".gitignore".freeze, ".rspec".freeze, ".travis.yml".freeze, "Gemfile".freeze, "LICENSE.md".freeze, "README.md".freeze, "Rakefile".freeze, "bin/console".freeze, "bin/setup".freeze, "gemfiles/rails-3.0.gemfile".freeze, "gemfiles/rails-3.1.gemfile".freeze, "gemfiles/rails-3.2.gemfile".freeze, "gemfiles/rails-4.0.gemfile".freeze, "gemfiles/rails-4.1.gemfile".freeze, "gemfiles/rails-4.2.gemfile".freeze, "gemfiles/rails-5.0.gemfile".freeze, "gemfiles/rails-5.1.gemfile".freeze, "gemfiles/rails-5.2.gemfile".freeze, "gemfiles/rails-6.0.gemfile".freeze, "gemfiles/rails-edge.gemfile".freeze, "lib/timber-rails.rb".freeze, "lib/timber-rails/action_controller.rb".freeze, "lib/timber-rails/action_controller/log_subscriber.rb".freeze, "lib/timber-rails/action_controller/log_subscriber/timber_log_subscriber.rb".freeze, "lib/timber-rails/action_dispatch.rb".freeze, "lib/timber-rails/action_dispatch/debug_exceptions.rb".freeze, "lib/timber-rails/action_view.rb".freeze, "lib/timber-rails/action_view/log_subscriber.rb".freeze, "lib/timber-rails/action_view/log_subscriber/timber_log_subscriber.rb".freeze, "lib/timber-rails/active_record.rb".freeze, "lib/timber-rails/active_record/log_subscriber.rb".freeze, "lib/timber-rails/active_record/log_subscriber/timber_log_subscriber.rb".freeze, "lib/timber-rails/active_support_log_subscriber.rb".freeze, "lib/timber-rails/config.rb".freeze, "lib/timber-rails/config/action_controller.rb".freeze, "lib/timber-rails/config/action_view.rb".freeze, "lib/timber-rails/config/active_record.rb".freeze, "lib/timber-rails/error_event.rb".freeze, "lib/timber-rails/logger.rb".freeze, "lib/timber-rails/overrides.rb".freeze, "lib/timber-rails/overrides/active_support_3_tagged_logging.rb".freeze, "lib/timber-rails/overrides/active_support_buffered_logger.rb".freeze, "lib/timber-rails/overrides/active_support_tagged_logging.rb".freeze, "lib/timber-rails/overrides/lograge.rb".freeze, "lib/timber-rails/overrides/rails_stdout_logging.rb".freeze, "lib/timber-rails/rack_logger.rb".freeze, "lib/timber-rails/railtie.rb".freeze, "lib/timber-rails/session_context.rb".freeze, "lib/timber-rails/version.rb".freeze, "timber-rails.gemspec".freeze]
|
||||
s.homepage = "https://docs.timber.io/languages/ruby/".freeze
|
||||
s.licenses = ["ISC".freeze]
|
||||
s.required_ruby_version = Gem::Requirement.new(">= 1.9.0".freeze)
|
||||
s.rubygems_version = "3.1.2".freeze
|
||||
s.summary = "Timber.io Rails integration".freeze
|
||||
|
||||
s.installed_by_version = "3.1.2" if s.respond_to? :installed_by_version
|
||||
|
||||
if s.respond_to? :specification_version then
|
||||
s.specification_version = 4
|
||||
end
|
||||
|
||||
if s.respond_to? :add_runtime_dependency then
|
||||
s.add_runtime_dependency(%q<rails>.freeze, [">= 3.0.0"])
|
||||
s.add_runtime_dependency(%q<timber>.freeze, ["~> 3.0"])
|
||||
s.add_runtime_dependency(%q<timber-rack>.freeze, ["~> 1.0"])
|
||||
s.add_development_dependency(%q<bundler>.freeze, [">= 0.0"])
|
||||
s.add_development_dependency(%q<rake>.freeze, [">= 0.8"])
|
||||
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.0"])
|
||||
s.add_development_dependency(%q<bundler-audit>.freeze, [">= 0"])
|
||||
s.add_development_dependency(%q<rails_stdout_logging>.freeze, [">= 0"])
|
||||
s.add_development_dependency(%q<rspec-its>.freeze, [">= 0"])
|
||||
s.add_development_dependency(%q<timecop>.freeze, [">= 0"])
|
||||
s.add_development_dependency(%q<sqlite3>.freeze, ["= 1.3.13"])
|
||||
s.add_development_dependency(%q<webmock>.freeze, ["~> 2.3"])
|
||||
else
|
||||
s.add_dependency(%q<rails>.freeze, [">= 3.0.0"])
|
||||
s.add_dependency(%q<timber>.freeze, ["~> 3.0"])
|
||||
s.add_dependency(%q<timber-rack>.freeze, ["~> 1.0"])
|
||||
s.add_dependency(%q<bundler>.freeze, [">= 0.0"])
|
||||
s.add_dependency(%q<rake>.freeze, [">= 0.8"])
|
||||
s.add_dependency(%q<rspec>.freeze, ["~> 3.0"])
|
||||
s.add_dependency(%q<bundler-audit>.freeze, [">= 0"])
|
||||
s.add_dependency(%q<rails_stdout_logging>.freeze, [">= 0"])
|
||||
s.add_dependency(%q<rspec-its>.freeze, [">= 0"])
|
||||
s.add_dependency(%q<timecop>.freeze, [">= 0"])
|
||||
s.add_dependency(%q<sqlite3>.freeze, ["= 1.3.13"])
|
||||
s.add_dependency(%q<webmock>.freeze, ["~> 2.3"])
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue