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