timber 2.1.0.rc3 → 2.1.0.rc4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -17
- data/lib/timber/cli/api.rb +6 -3
- data/lib/timber/cli/api/application.rb +7 -2
- data/lib/timber/cli/config_file.rb +14 -17
- data/lib/timber/cli/file_helper.rb +21 -9
- data/lib/timber/cli/installer.rb +3 -1
- data/lib/timber/cli/installers.rb +47 -39
- data/lib/timber/cli/installers/config_file.rb +60 -0
- data/lib/timber/cli/installers/other.rb +11 -7
- data/lib/timber/cli/installers/rails.rb +93 -146
- data/lib/timber/cli/installers/root.rb +43 -27
- data/lib/timber/cli/io.rb +15 -3
- data/lib/timber/cli/io/messages.rb +3 -4
- data/lib/timber/current_context.rb +15 -3
- data/lib/timber/log_entry.rb +0 -10
- data/lib/timber/logger.rb +7 -3
- data/lib/timber/util.rb +0 -1
- data/lib/timber/util/http_event.rb +6 -18
- data/lib/timber/util/request.rb +32 -11
- data/lib/timber/version.rb +1 -1
- data/spec/timber/cli/config_file_spec.rb +23 -0
- data/spec/timber/cli/installers/config_file_spec.rb +58 -0
- data/spec/timber/cli/installers/other_spec.rb +50 -0
- data/spec/timber/cli/installers/rails_spec.rb +290 -95
- data/spec/timber/cli/installers/root_spec.rb +8 -7
- data/spec/timber/current_context_spec.rb +15 -15
- data/spec/timber/events/http_server_request_spec.rb +1 -1
- data/spec/timber/log_devices/http_spec.rb +2 -2
- data/spec/timber/logger_spec.rb +5 -5
- data/spec/timber/util/http_event_spec.rb +2 -2
- metadata +9 -3
- data/lib/timber/util/string.rb +0 -21
@@ -92,11 +92,10 @@ MESSAGE
|
|
92
92
|
|
93
93
|
def free_data
|
94
94
|
message = <<-MESSAGE
|
95
|
-
Because you're awesome, we've credited your account with ✨
|
95
|
+
Because you're awesome, we've credited your account with ✨ 100mb✨.
|
96
96
|
|
97
|
-
* Get ✨ 250mb✨
|
98
|
-
* Get ✨
|
99
|
-
* Get ✨ 100mb✨ for following #{TWITTER_HANDLE} on twitter
|
97
|
+
* Get ✨ 250mb✨ for starring our repo: #{IO::ANSI.colorize(REPO_URL, :blue)}
|
98
|
+
* Get ✨ 250mb✨ for tweeting your experience to #{IO::ANSI.colorize(TWITTER_HANDLE, :blue)}
|
100
99
|
MESSAGE
|
101
100
|
message.rstrip
|
102
101
|
end
|
@@ -1,5 +1,8 @@
|
|
1
|
+
require "socket"
|
2
|
+
|
1
3
|
require "timber/config"
|
2
4
|
require "timber/contexts/release"
|
5
|
+
require "timber/contexts/system"
|
3
6
|
|
4
7
|
module Timber
|
5
8
|
# Holds the current context in a thread safe memory storage. This context is
|
@@ -81,7 +84,7 @@ module Timber
|
|
81
84
|
# to only neccessary data.
|
82
85
|
def add(*objects)
|
83
86
|
objects.each do |object|
|
84
|
-
add_to(hash, object)
|
87
|
+
add_to!(hash, object)
|
85
88
|
end
|
86
89
|
expire_cache!
|
87
90
|
self
|
@@ -142,14 +145,23 @@ module Timber
|
|
142
145
|
# it's hash properly.
|
143
146
|
def build_initial_hash
|
144
147
|
new_hash = {}
|
148
|
+
|
149
|
+
# Release context
|
145
150
|
release_context = Contexts::Release.from_env
|
146
151
|
if release_context
|
147
|
-
add_to(new_hash, release_context)
|
152
|
+
add_to!(new_hash, release_context)
|
148
153
|
end
|
154
|
+
|
155
|
+
# System context
|
156
|
+
hostname = Socket.gethostname
|
157
|
+
pid = Process.pid
|
158
|
+
system_context = Contexts::System.new(hostname: hostname, pid: pid)
|
159
|
+
add_to!(new_hash, system_context)
|
160
|
+
|
149
161
|
new_hash
|
150
162
|
end
|
151
163
|
|
152
|
-
def add_to(hash, object)
|
164
|
+
def add_to!(hash, object)
|
153
165
|
context = Contexts.build(object) # Normalizes objects into a Timber::Context descendant.
|
154
166
|
key = context.keyspace
|
155
167
|
json = context.as_json # Convert to json now so that we aren't doing it for every line
|
data/lib/timber/log_entry.rb
CHANGED
@@ -33,16 +33,6 @@ module Timber
|
|
33
33
|
@message = message.is_a?(String) ? message : message.inspect
|
34
34
|
@tags = options[:tags]
|
35
35
|
@time_ms = options[:time_ms]
|
36
|
-
|
37
|
-
context_snapshot = {} if context_snapshot.nil?
|
38
|
-
|
39
|
-
# Set the system context for each log entry since processes can be forked
|
40
|
-
# and the process ID could change.
|
41
|
-
hostname = Socket.gethostname
|
42
|
-
pid = Process.pid
|
43
|
-
system_context = Contexts::System.new(hostname: hostname, pid: pid)
|
44
|
-
context_snapshot[system_context.keyspace] = system_context.as_json
|
45
|
-
|
46
36
|
@context_snapshot = context_snapshot
|
47
37
|
@event = event
|
48
38
|
end
|
data/lib/timber/logger.rb
CHANGED
@@ -92,8 +92,8 @@ module Timber
|
|
92
92
|
elsif logged_obj.is_a?(Hash)
|
93
93
|
# Extract the tags
|
94
94
|
tags = tags.clone
|
95
|
-
tags
|
96
|
-
tags
|
95
|
+
tags.push(logged_obj.delete(:tag)) if logged_obj.key?(:tag)
|
96
|
+
tags.concat(logged_obj.delete(:tags)) if logged_obj.key?(:tags)
|
97
97
|
tags.uniq!
|
98
98
|
|
99
99
|
# Extract the time_ms
|
@@ -113,9 +113,13 @@ module Timber
|
|
113
113
|
# Because of all the crazy ways Rails has attempted tags, we need this crazy method.
|
114
114
|
def extract_active_support_tagged_logging_tags
|
115
115
|
Thread.current[:activesupport_tagged_logging_tags] ||
|
116
|
-
Thread.current[
|
116
|
+
Thread.current[tagged_logging_object_key_name] ||
|
117
117
|
EMPTY_ARRAY
|
118
118
|
end
|
119
|
+
|
120
|
+
def tagged_logging_object_key_name
|
121
|
+
@tagged_logging_object_key_name ||= "activesupport_tagged_logging_tags:#{object_id}"
|
122
|
+
end
|
119
123
|
end
|
120
124
|
|
121
125
|
# For use in development and test environments where you do not want metadata
|
data/lib/timber/util.rb
CHANGED
@@ -33,28 +33,16 @@ module Timber
|
|
33
33
|
|
34
34
|
# Normalizes headers to:
|
35
35
|
#
|
36
|
-
# 1.
|
36
|
+
# 1. Only select values that are UTF8, otherwise they will throw errors when serializing.
|
37
37
|
# 2. Sanitize sensitive headers such as `Authorization` or custom headers specified in
|
38
38
|
def normalize_headers(headers)
|
39
39
|
if headers.is_a?(::Hash)
|
40
40
|
h = headers.each_with_object({}) do |(k, v), h|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
#
|
47
|
-
# string = 'my string'.force_encoding('ASCII-8BIT')
|
48
|
-
# string.is_a?(String) => false
|
49
|
-
# string.class => String
|
50
|
-
# string.class == String => false
|
51
|
-
# string.class.name == "String" => true
|
52
|
-
#
|
53
|
-
# ¯\_(ツ)_/¯
|
54
|
-
if v.class.name == STRING_CLASS_NAME
|
55
|
-
h[k] = Timber::Util::String.normalize_to_utf8(v)
|
56
|
-
else
|
57
|
-
h[k] = v
|
41
|
+
if v
|
42
|
+
v = v.to_s
|
43
|
+
if [Encoding::UTF_8, Encoding::US_ASCII].include?(v.encoding)
|
44
|
+
h[k] = v
|
45
|
+
end
|
58
46
|
end
|
59
47
|
end
|
60
48
|
|
data/lib/timber/util/request.rb
CHANGED
@@ -8,8 +8,17 @@ if defined?(::Rack::Request)
|
|
8
8
|
module Util
|
9
9
|
# @private
|
10
10
|
class Request < ::Rack::Request
|
11
|
+
# We store strings as constants since they are reused on a per request basis.
|
12
|
+
# This avoids string allocations.
|
13
|
+
HTTP_HEADER_ORIGINAL_DELIMITER = '_'.freeze
|
14
|
+
HTTP_HEADER_NEW_DELIMITER = '_'.freeze
|
11
15
|
HTTP_PREFIX = 'HTTP_'.freeze
|
12
16
|
|
17
|
+
REMOTE_IP_KEY_NAME = 'action_dispatch.remote_ip'.freeze
|
18
|
+
REQUEST_ID_KEY_NAME1 = 'action_dispatch.request_id'.freeze
|
19
|
+
REQUEST_ID_KEY_NAME2 = 'X-Request-ID'.freeze
|
20
|
+
REQUEST_ID_KEY_NAME3 = 'X-Request-Id'.freeze
|
21
|
+
|
13
22
|
def body_content
|
14
23
|
content = body.read
|
15
24
|
body.rewind
|
@@ -18,19 +27,30 @@ if defined?(::Rack::Request)
|
|
18
27
|
|
19
28
|
# Returns a list of request headers. The rack env contains a lot of data, this function
|
20
29
|
# identifies those that were the actual request headers.
|
30
|
+
#
|
31
|
+
# This was extracted from: https://github.com/ruby-grape/grape/blob/91c6c78ae3d3f3ffabaf57ffc4dc35ab7cfc7b5f/lib/grape/request.rb#L30
|
21
32
|
def headers
|
22
|
-
@headers ||=
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
.
|
27
|
-
|
28
|
-
|
33
|
+
@headers ||= begin
|
34
|
+
headers = {}
|
35
|
+
|
36
|
+
@env.each_pair do |k, v|
|
37
|
+
next unless k.is_a?(String) && k.to_s.start_with?(HTTP_PREFIX)
|
38
|
+
|
39
|
+
k = k[5..-1].
|
40
|
+
split(HTTP_HEADER_ORIGINAL_DELIMITER).
|
41
|
+
each(&:capitalize!).
|
42
|
+
join(HTTP_HEADER_NEW_DELIMITER)
|
43
|
+
|
44
|
+
headers[k] = v
|
45
|
+
end
|
46
|
+
|
47
|
+
headers
|
48
|
+
end
|
29
49
|
end
|
30
50
|
|
31
51
|
def ip
|
32
|
-
@ip ||= if @env[
|
33
|
-
@env[
|
52
|
+
@ip ||= if @env[REMOTE_IP_KEY_NAME]
|
53
|
+
@env[REMOTE_IP_KEY_NAME].to_s || super
|
34
54
|
else
|
35
55
|
super
|
36
56
|
end
|
@@ -42,8 +62,9 @@ if defined?(::Rack::Request)
|
|
42
62
|
end
|
43
63
|
|
44
64
|
def request_id
|
45
|
-
@request_id ||= @env[
|
46
|
-
@env[
|
65
|
+
@request_id ||= @env[REQUEST_ID_KEY_NAME1] ||
|
66
|
+
@env[REQUEST_ID_KEY_NAME12] ||
|
67
|
+
@env[REQUEST_ID_KEY_NAME3]
|
47
68
|
end
|
48
69
|
end
|
49
70
|
end
|
data/lib/timber/version.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Timber::CLI::ConfigFile, :rails_23 => true do
|
4
|
+
let(:path) { "config/initializers/timber.rb" }
|
5
|
+
let(:config_file) { described_class.new(path) }
|
6
|
+
let(:initial_contents) { "# Timber.io Ruby Configuration - Simple Structured Logging\n#\n# ^ ^ ^ ^ ___I_ ^ ^ ^ ^ ^ ^ ^\n# /|\\/|\\/|\\ /|\\ /\\-_--\\ /|\\/|\\ /|\\/|\\/|\\ /|\\/|\\\n# /|\\/|\\/|\\ /|\\ / \\_-__\\ /|\\/|\\ /|\\/|\\/|\\ /|\\/|\\\n# /|\\/|\\/|\\ /|\\ |[]| [] | /|\\/|\\ /|\\/|\\/|\\ /|\\/|\\\n# -------------------------------------------------------------------\n# Website: https://timber.io\n# Documentation: https://timber.io/docs\n# Support: support@timber.io\n# -------------------------------------------------------------------\n\nconfig = Timber::Config.instance\n\n# Add additional configuration here.\n# For a full list of configuration options and their explanations see:\n# http://www.rubydoc.info/github/timberio/timber-ruby/Timber/Config\n\n" }
|
7
|
+
let(:contents_hook) { "# Add additional configuration here." }
|
8
|
+
|
9
|
+
describe ".create!" do
|
10
|
+
it "should create" do
|
11
|
+
expect(Timber::CLI::FileHelper).to receive(:write).with(path, initial_contents).exactly(1).times
|
12
|
+
config_file.create!
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ".logrageify!" do
|
17
|
+
it "should set the option in the config file" do
|
18
|
+
config_file.logrageify!
|
19
|
+
new_contents = initial_contents.gsub(contents_hook, "config.logrageify!\n\n#{contents_hook}")
|
20
|
+
expect(config_file.send(:content)).to eq(new_contents)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Timber::CLI::Installers::ConfigFile, :rails_23 => true do
|
4
|
+
let(:api_key) { "abcd1234" }
|
5
|
+
let(:app) do
|
6
|
+
attributes = {
|
7
|
+
"api_key" => api_key,
|
8
|
+
"environment" => "development",
|
9
|
+
"framework_type" => "rails",
|
10
|
+
"heroku_drain_url" => "http://drain.heroku.com",
|
11
|
+
"name" => "My Rails App",
|
12
|
+
"platform_type" => "other"
|
13
|
+
}
|
14
|
+
Timber::CLI::API::Application.new(attributes)
|
15
|
+
end
|
16
|
+
let(:api) { Timber::CLI::API.new(api_key) }
|
17
|
+
let(:input) { StringIO.new }
|
18
|
+
let(:output) { StringIO.new }
|
19
|
+
let(:io) { Timber::CLI::IO.new(io_out: output, io_in: input) }
|
20
|
+
let(:installer) { described_class.new(io, api) }
|
21
|
+
let(:initial_config_contents) { "# Timber.io Ruby Configuration - Simple Structured Logging\n#\n# ^ ^ ^ ^ ___I_ ^ ^ ^ ^ ^ ^ ^\n# /|\\/|\\/|\\ /|\\ /\\-_--\\ /|\\/|\\ /|\\/|\\/|\\ /|\\/|\\\n# /|\\/|\\/|\\ /|\\ / \\_-__\\ /|\\/|\\ /|\\/|\\/|\\ /|\\/|\\\n# /|\\/|\\/|\\ /|\\ |[]| [] | /|\\/|\\ /|\\/|\\/|\\ /|\\/|\\\n# -------------------------------------------------------------------\n# Website: https://timber.io\n# Documentation: https://timber.io/docs\n# Support: support@timber.io\n# -------------------------------------------------------------------\n\nconfig = Timber::Config.instance\n\n# Add additional configuration here.\n# For a full list of configuration options and their explanations see:\n# http://www.rubydoc.info/github/timberio/timber-ruby/Timber/Config\n\n" }
|
22
|
+
|
23
|
+
describe ".run" do
|
24
|
+
it "should run properly" do
|
25
|
+
path = "/path/to/file"
|
26
|
+
config_file = Timber::CLI::ConfigFile.new(path)
|
27
|
+
|
28
|
+
expect(Timber::CLI::ConfigFile).to receive(:new).with(path).and_return(config_file)
|
29
|
+
expect(config_file).to receive(:exists?).exactly(1).times.and_return(false)
|
30
|
+
expect(installer).to receive(:logrageify?).exactly(1).times.and_return(true)
|
31
|
+
expect(config_file).to receive(:logrageify!).exactly(1).times
|
32
|
+
expect(config_file).to receive(:create!).exactly(1).times
|
33
|
+
|
34
|
+
installer.run(app, path)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ".logrageify?" do
|
39
|
+
it "should do nothing if Lograge is not detected" do
|
40
|
+
expect(installer.send(:logrageify?)).to eq(false)
|
41
|
+
expect(output.string).to eq("")
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with a Lograge constant" do
|
45
|
+
around(:each) do |example|
|
46
|
+
Lograge = 1
|
47
|
+
example.run
|
48
|
+
Object.send(:remove_const, :Lograge)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should prompt for Lograge configuration and return true for y" do
|
52
|
+
input.string = "y\n"
|
53
|
+
expect(installer.send(:logrageify?)).to eq(true)
|
54
|
+
expect(output.string).to eq("\n--------------------------------------------------------------------------------\n\nWe noticed you have lograge installed. Would you like to configure \nTimber to function similarly?\n(This silences template renders, sql queries, and controller calls.\nYou can always do this later in config/initialzers/timber.rb)\n\n\e[34my) Yes, configure Timber like lograge\e[0m\n\e[34mn) No, use the Rails logging defaults\e[0m\n\nEnter your choice: (y/n) ")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Timber::CLI::Installers::Other, :rails_23 => true do
|
6
|
+
let(:api_key) { "abcd1234" }
|
7
|
+
let(:app) do
|
8
|
+
attributes = {
|
9
|
+
"api_key" => api_key,
|
10
|
+
"environment" => "development",
|
11
|
+
"framework_type" => "rails",
|
12
|
+
"heroku_drain_url" => "http://drain.heroku.com",
|
13
|
+
"name" => "My Rails App",
|
14
|
+
"platform_type" => "other"
|
15
|
+
}
|
16
|
+
Timber::CLI::API::Application.new(attributes)
|
17
|
+
end
|
18
|
+
let(:api) { Timber::CLI::API.new(api_key) }
|
19
|
+
let(:input) { StringIO.new }
|
20
|
+
let(:output) { StringIO.new }
|
21
|
+
let(:io) { Timber::CLI::IO.new(io_out: output, io_in: input) }
|
22
|
+
let(:installer) { described_class.new(io, api) }
|
23
|
+
|
24
|
+
describe ".run" do
|
25
|
+
context "heroku" do
|
26
|
+
before(:each) do
|
27
|
+
app.platform_type = "heroku"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should run properly" do
|
31
|
+
expect(installer).to receive(:install_stdout).exactly(1).times
|
32
|
+
expect(installer).to receive(:ask_to_proceed).exactly(1).times
|
33
|
+
|
34
|
+
installer.run(app)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "non-heroku" do
|
39
|
+
it "should run properly" do
|
40
|
+
api_key_code = "'#{api_key}'"
|
41
|
+
expect(installer).to receive(:get_api_key_storage_preference).exactly(1).times.and_return(:inline)
|
42
|
+
expect(installer).to receive(:get_api_key_code).with(:inline).exactly(1).times.and_return(api_key_code)
|
43
|
+
expect(installer).to receive(:install_http).with(api_key_code).exactly(1).times
|
44
|
+
expect(installer).to receive(:ask_to_proceed).exactly(1).times
|
45
|
+
|
46
|
+
installer.run(app)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -18,143 +18,338 @@ describe Timber::CLI::Installers::Rails, :rails_23 => true do
|
|
18
18
|
let(:output) { StringIO.new }
|
19
19
|
let(:io) { Timber::CLI::IO.new(io_out: output, io_in: input) }
|
20
20
|
let(:installer) { described_class.new(io, api) }
|
21
|
-
let(:
|
21
|
+
let(:logger_code) { defined?(ActiveSupport::TaggedLogging) ? "ActiveSupport::TaggedLogging.new(logger)" : "logger" }
|
22
22
|
|
23
23
|
describe ".run" do
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
expect(installer).to receive(:setup_test_environment).with("config/environments/test.rb").and_return(true)
|
34
|
-
|
35
|
-
installer.run(app)
|
24
|
+
context "development" do
|
25
|
+
it "should execute properly" do
|
26
|
+
expect(installer).to receive(:install_initializer).with(app).exactly(1).times
|
27
|
+
expect(installer).to receive(:install_development_environment).with(app).exactly(1).times
|
28
|
+
expect(installer).to receive(:install_test_environment).with(app).exactly(1).times
|
29
|
+
expect(installer).to_not receive(:install_app_environment)
|
30
|
+
|
31
|
+
installer.run(app)
|
32
|
+
end
|
36
33
|
end
|
37
|
-
end
|
38
|
-
|
39
|
-
describe ".initializer" do
|
40
|
-
it "should create a config file" do
|
41
|
-
config_file_path = "config/initializers/timber.rb"
|
42
34
|
|
43
|
-
|
44
|
-
|
45
|
-
|
35
|
+
context "staging" do
|
36
|
+
before(:each) do
|
37
|
+
app.environment = "staging"
|
38
|
+
end
|
46
39
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
40
|
+
it "should execute properly" do
|
41
|
+
expect(installer).to receive(:install_initializer).with(app).exactly(1).times
|
42
|
+
expect(installer).to receive(:install_development_environment).with(app).exactly(1).times
|
43
|
+
expect(installer).to receive(:install_test_environment).with(app).exactly(1).times
|
44
|
+
expect(installer).to receive(:install_app_environment).with(app).exactly(1).times
|
51
45
|
|
52
|
-
|
53
|
-
|
54
|
-
expect(installer.send(:logrageify?)).to eq(false)
|
55
|
-
expect(output.string).to eq("")
|
46
|
+
installer.run(app)
|
47
|
+
end
|
56
48
|
end
|
57
49
|
|
58
|
-
context "
|
59
|
-
|
60
|
-
|
61
|
-
example.run
|
62
|
-
Object.send(:remove_const, :Lograge)
|
50
|
+
context "production" do
|
51
|
+
before(:each) do
|
52
|
+
app.environment = "production"
|
63
53
|
end
|
64
54
|
|
65
|
-
it "should
|
66
|
-
|
67
|
-
expect(installer.
|
68
|
-
expect(
|
55
|
+
it "should execute properly" do
|
56
|
+
expect(installer).to receive(:install_initializer).with(app).exactly(1).times
|
57
|
+
expect(installer).to receive(:install_development_environment).with(app).exactly(1).times
|
58
|
+
expect(installer).to receive(:install_test_environment).with(app).exactly(1).times
|
59
|
+
expect(installer).to receive(:install_app_environment).with(app).exactly(1).times
|
60
|
+
|
61
|
+
installer.run(app)
|
69
62
|
end
|
70
63
|
end
|
71
64
|
end
|
72
65
|
|
73
|
-
describe ".
|
74
|
-
it "should
|
66
|
+
describe ".install_initializer" do
|
67
|
+
it "should create a config file" do
|
75
68
|
config_file_path = "config/initializers/timber.rb"
|
69
|
+
expect_any_instance_of(Timber::CLI::Installers::ConfigFile).to receive(:run).with(app, config_file_path).exactly(1).times
|
76
70
|
|
77
|
-
|
78
|
-
|
79
|
-
|
71
|
+
installer.send(:install_initializer, app)
|
72
|
+
end
|
73
|
+
end
|
80
74
|
|
81
|
-
|
82
|
-
|
83
|
-
|
75
|
+
describe ".install_development_environment" do
|
76
|
+
let(:env_file_path) { "config/environments/development.rb" }
|
77
|
+
|
78
|
+
context "env file exists" do
|
79
|
+
context "not installed" do
|
80
|
+
context "send logs" do
|
81
|
+
it "should setup properly" do
|
82
|
+
expect(installer).to receive(:get_environment_file_path).
|
83
|
+
with("development").
|
84
|
+
exactly(1).times.
|
85
|
+
and_return(env_file_path)
|
86
|
+
|
87
|
+
expect(installer).to receive(:already_installed?).
|
88
|
+
with(env_file_path).
|
89
|
+
exactly(1).times.
|
90
|
+
and_return(false)
|
91
|
+
|
92
|
+
expect(installer).to receive(:get_development_preference).
|
93
|
+
with(app).
|
94
|
+
exactly(1).times.
|
95
|
+
and_return(:send)
|
96
|
+
|
97
|
+
expected_code = <<-CODE
|
98
|
+
# Install the Timber.io logger
|
99
|
+
send_logs_to_timber = true # <---- set to false to stop sending dev logs to Timber.io
|
100
|
+
|
101
|
+
log_device = send_logs_to_timber ? Timber::LogDevices::HTTP.new('#{app.api_key}') : STDOUT
|
102
|
+
logger = Timber::Logger.new(log_device)
|
103
|
+
logger.level = config.log_level
|
104
|
+
config.logger = #{logger_code}
|
105
|
+
CODE
|
106
|
+
|
107
|
+
expect(installer).to receive(:install_logger).
|
108
|
+
with(env_file_path, expected_code).
|
109
|
+
exactly(1).times
|
110
|
+
|
111
|
+
result = installer.send(:install_development_environment, app)
|
112
|
+
expect(result).to eq(:http)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "dont send" do
|
117
|
+
it "should setup properly" do
|
118
|
+
expect(installer).to receive(:get_environment_file_path).
|
119
|
+
with("development").
|
120
|
+
exactly(1).times.
|
121
|
+
and_return(env_file_path)
|
122
|
+
|
123
|
+
expect(installer).to receive(:already_installed?).
|
124
|
+
with(env_file_path).
|
125
|
+
exactly(1).times.
|
126
|
+
and_return(false)
|
127
|
+
|
128
|
+
expect(installer).to receive(:get_development_preference).
|
129
|
+
with(app).
|
130
|
+
exactly(1).times.
|
131
|
+
and_return(:dont_send)
|
132
|
+
|
133
|
+
expect(installer).to receive(:install_stdout).
|
134
|
+
with(env_file_path).
|
135
|
+
exactly(1).times
|
136
|
+
|
137
|
+
result = installer.send(:install_development_environment, app)
|
138
|
+
expect(result).to eq(:stdout)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
84
142
|
|
85
|
-
|
143
|
+
context "installed" do
|
144
|
+
it "should skip" do
|
145
|
+
expect(installer).to receive(:get_environment_file_path).
|
146
|
+
with("development").
|
147
|
+
exactly(1).times.
|
148
|
+
and_return(env_file_path)
|
149
|
+
|
150
|
+
expect(installer).to receive(:already_installed?).
|
151
|
+
with(env_file_path).
|
152
|
+
exactly(1).times.
|
153
|
+
and_return(true)
|
154
|
+
|
155
|
+
result = installer.send(:install_development_environment, app)
|
156
|
+
expect(result).to eq(:already_installed)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
86
161
|
|
87
|
-
|
88
|
-
|
89
|
-
|
162
|
+
describe ".install_test_environment" do
|
163
|
+
let(:env_file_path) { "config/environments/test.rb" }
|
164
|
+
|
165
|
+
context "env file exists" do
|
166
|
+
context "not installed" do
|
167
|
+
it "should setup properly" do
|
168
|
+
expect(installer).to receive(:get_environment_file_path).
|
169
|
+
with("test").
|
170
|
+
exactly(1).times.
|
171
|
+
and_return(env_file_path)
|
172
|
+
|
173
|
+
expect(installer).to receive(:already_installed?).
|
174
|
+
with(env_file_path).
|
175
|
+
exactly(1).times.
|
176
|
+
and_return(false)
|
177
|
+
|
178
|
+
expect(installer).to receive(:install_nil).
|
179
|
+
with(env_file_path).
|
180
|
+
exactly(1).times
|
181
|
+
|
182
|
+
result = installer.send(:install_test_environment, app)
|
183
|
+
expect(result).to eq(:nil)
|
184
|
+
end
|
185
|
+
end
|
90
186
|
|
91
|
-
|
187
|
+
context "installed" do
|
188
|
+
it "should skip" do
|
189
|
+
expect(installer).to receive(:get_environment_file_path).
|
190
|
+
with("test").
|
191
|
+
exactly(1).times.
|
192
|
+
and_return(env_file_path)
|
193
|
+
|
194
|
+
expect(installer).to receive(:already_installed?).
|
195
|
+
with(env_file_path).
|
196
|
+
exactly(1).times.
|
197
|
+
and_return(true)
|
198
|
+
|
199
|
+
result = installer.send(:install_test_environment, app)
|
200
|
+
expect(result).to eq(:already_installed)
|
201
|
+
end
|
202
|
+
end
|
92
203
|
end
|
93
204
|
end
|
94
205
|
|
95
|
-
describe ".
|
96
|
-
|
97
|
-
|
206
|
+
describe ".install_app_environment" do
|
207
|
+
context "production" do
|
208
|
+
before(:each) do
|
209
|
+
app.environment = "production"
|
210
|
+
end
|
98
211
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
212
|
+
let(:env_file_path) { "config/environments/production.rb" }
|
213
|
+
|
214
|
+
context "env file exists" do
|
215
|
+
context "not installed" do
|
216
|
+
context "http" do
|
217
|
+
it "should setup properly" do
|
218
|
+
expect(installer).to receive(:get_environment_file_path).
|
219
|
+
with("production").
|
220
|
+
exactly(1).times.
|
221
|
+
and_return(env_file_path)
|
222
|
+
|
223
|
+
expect(installer).to receive(:already_installed?).
|
224
|
+
with(env_file_path).
|
225
|
+
exactly(1).times.
|
226
|
+
and_return(false)
|
227
|
+
|
228
|
+
expect(installer).to receive(:get_delivery_strategy).
|
229
|
+
with(app).
|
230
|
+
exactly(1).times.
|
231
|
+
and_return(:http)
|
232
|
+
|
233
|
+
expect(installer).to receive(:get_api_key_storage_preference).
|
234
|
+
exactly(1).times.
|
235
|
+
and_return(:inline)
|
236
|
+
|
237
|
+
expect(installer).to receive(:install_http).
|
238
|
+
with(env_file_path, :inline).
|
239
|
+
exactly(1).times
|
240
|
+
|
241
|
+
result = installer.send(:install_app_environment, app)
|
242
|
+
expect(result).to eq(:http)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
context "stdout" do
|
247
|
+
it "should setup properly" do
|
248
|
+
expect(installer).to receive(:get_environment_file_path).
|
249
|
+
with("production").
|
250
|
+
exactly(1).times.
|
251
|
+
and_return(env_file_path)
|
252
|
+
|
253
|
+
expect(installer).to receive(:already_installed?).
|
254
|
+
with(env_file_path).
|
255
|
+
exactly(1).times.
|
256
|
+
and_return(false)
|
257
|
+
|
258
|
+
expect(installer).to receive(:get_delivery_strategy).
|
259
|
+
with(app).
|
260
|
+
exactly(1).times.
|
261
|
+
and_return(:stdout)
|
262
|
+
|
263
|
+
expect(installer).to receive(:install_stdout).
|
264
|
+
with(env_file_path).
|
265
|
+
exactly(1).times
|
266
|
+
|
267
|
+
result = installer.send(:install_app_environment, app)
|
268
|
+
expect(result).to eq(:stdout)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
context "installed" do
|
274
|
+
it "should skip" do
|
275
|
+
expect(installer).to receive(:get_environment_file_path).
|
276
|
+
with("production").
|
277
|
+
exactly(1).times.
|
278
|
+
and_return(env_file_path)
|
279
|
+
|
280
|
+
expect(installer).to receive(:already_installed?).
|
281
|
+
with(env_file_path).
|
282
|
+
exactly(1).times.
|
283
|
+
and_return(true)
|
284
|
+
|
285
|
+
result = installer.send(:install_app_environment, app)
|
286
|
+
expect(result).to eq(:already_installed)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
103
292
|
|
104
|
-
|
105
|
-
|
293
|
+
describe ".get_environment_file_path" do
|
294
|
+
it "should return the file if it exists" do
|
295
|
+
env_file_path = "config/environments/development.rb"
|
296
|
+
expect(installer.file_helper).to receive(:exists?).with(env_file_path).exactly(1).times.and_return(true)
|
106
297
|
|
107
|
-
|
108
|
-
|
109
|
-
|
298
|
+
result = installer.send(:get_environment_file_path, "development")
|
299
|
+
expect(result).to eq(env_file_path)
|
300
|
+
end
|
110
301
|
|
111
|
-
|
302
|
+
it "should return nil if it does not exist" do
|
303
|
+
env_file_path = "config/environments/production.rb"
|
304
|
+
expect(installer.file_helper).to receive(:exists?).with(env_file_path).exactly(1).times.and_return(false)
|
112
305
|
|
113
|
-
|
306
|
+
result = installer.send(:get_environment_file_path, "production")
|
307
|
+
expect(result).to eq(nil)
|
114
308
|
end
|
115
309
|
end
|
116
310
|
|
117
|
-
describe ".
|
118
|
-
it "should
|
119
|
-
env_file_path = "config/environments/
|
120
|
-
|
121
|
-
expect(Timber::CLI::FileHelper).to receive(:read).
|
122
|
-
with(env_file_path).
|
123
|
-
exactly(2).times.
|
124
|
-
and_return("\nend")
|
125
|
-
|
126
|
-
logger_code = defined?(ActiveSupport::TaggedLogging) ? "ActiveSupport::TaggedLogging.new(logger)" : "logger"
|
127
|
-
new_contents = "\n\n # Install the Timber.io logger but silence all logs (log to nil). We install the\n # logger to ensure the Rails.logger object exposes the proper API.\n logger = Timber::Logger.new(nil)\n logger.level = config.log_level\n config.logger = #{logger_code}\n\nend"
|
311
|
+
describe ".install_nil" do
|
312
|
+
it "should pass the proper code" do
|
313
|
+
env_file_path = "config/environments/development.rb"
|
128
314
|
|
129
|
-
|
130
|
-
|
131
|
-
|
315
|
+
expected_code = <<-CODE
|
316
|
+
# Install the Timber.io logger, but do not send logs.
|
317
|
+
logger = Timber::Logger.new(nil)
|
318
|
+
logger.level = config.log_level
|
319
|
+
config.logger = #{logger_code}
|
320
|
+
CODE
|
132
321
|
|
133
|
-
expect(
|
322
|
+
expect(installer).to receive(:install_logger).
|
323
|
+
with(env_file_path, expected_code).
|
324
|
+
exactly(1).times
|
134
325
|
|
135
|
-
|
326
|
+
installer.send(:install_nil, env_file_path)
|
136
327
|
end
|
137
328
|
end
|
138
329
|
|
139
|
-
describe ".
|
140
|
-
|
141
|
-
|
330
|
+
describe ".install_logger" do
|
331
|
+
context "not installed" do
|
332
|
+
it "should pass the proper code" do
|
333
|
+
env_file_path = "config/environments/development.rb"
|
142
334
|
|
143
|
-
|
144
|
-
with(env_file_path).
|
145
|
-
exactly(2).times.
|
146
|
-
and_return("\nend")
|
335
|
+
logger_code = "my code"
|
147
336
|
|
148
|
-
|
149
|
-
new_contents = "\n\n # Install the Timber.io logger, send logs over HTTP.\n log_device = Timber::LogDevices::HTTP.new(ENV['TIMBER_API_KEY'])\n logger = Timber::Logger.new(log_device)\n logger.level = config.log_level\n config.logger = #{logger_code}\n\nend"
|
337
|
+
current_contents = "\nend"
|
150
338
|
|
151
|
-
|
152
|
-
|
153
|
-
|
339
|
+
expect(installer.file_helper).to receive(:read).
|
340
|
+
with(env_file_path).
|
341
|
+
exactly(1).times.
|
342
|
+
and_return(current_contents)
|
154
343
|
|
155
|
-
|
344
|
+
new_contents = "\n\nmy code\nend"
|
156
345
|
|
157
|
-
|
346
|
+
expect(installer.file_helper).to receive(:write).
|
347
|
+
with(env_file_path, new_contents).
|
348
|
+
exactly(1).times.
|
349
|
+
and_return("\nend")
|
350
|
+
|
351
|
+
installer.send(:install_logger, env_file_path, logger_code)
|
352
|
+
end
|
158
353
|
end
|
159
354
|
end
|
160
355
|
end
|