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.
@@ -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 ✨ 50mb✨. Get more:
95
+ Because you're awesome, we've credited your account with ✨ 100mb✨.
96
96
 
97
- * Get ✨ 250mb✨ for tweeting your experience to #{TWITTER_HANDLE}
98
- * Get ✨ 100mb for starring our repo: #{REPO_URL}
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
@@ -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
@@ -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 << logged_obj.delete(:tag) if logged_obj.key?(:tag)
96
- tags += logged_obj.delete(:tags) if logged_obj.key?(: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["activesupport_tagged_logging_tags:#{object_id}"] ||
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
@@ -3,7 +3,6 @@ require "timber/util/hash"
3
3
  require "timber/util/http_event"
4
4
  require "timber/util/object"
5
5
  require "timber/util/request"
6
- require "timber/util/string"
7
6
  require "timber/util/struct"
8
7
 
9
8
  module Timber
@@ -33,28 +33,16 @@ module Timber
33
33
 
34
34
  # Normalizes headers to:
35
35
  #
36
- # 1. Ensure the value is UTF8, this will otherwise throw errors upon capturing.
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
- # Force the header into a valid UTF-8 string, otherwise we will encounter
42
- # encoding issues when we serialize this data. Moreoever, if the
43
- # data is already valid UTF-8 we don't pay a penalty.
44
- #
45
- # Note: we compare the class name because...
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
 
@@ -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 ||= ::Hash[
23
- *@env.select { |k,v| k.is_a?(String) && k.start_with?(HTTP_PREFIX) }
24
- .collect { |k,v| [k.sub(/^#{HTTP_PREFIX}/, ''), v] }
25
- .collect { |k,v| [k.split('_').collect(&:capitalize).join('-'), v] }
26
- .sort
27
- .flatten
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["action_dispatch.remote_ip"]
33
- @env["action_dispatch.remote_ip"].to_s || super
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["action_dispatch.request_id"] || @env["X-Request-ID"] ||
46
- @env["X-Request-Id"]
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
@@ -1,3 +1,3 @@
1
1
  module Timber
2
- VERSION = "2.1.0.rc3"
2
+ VERSION = "2.1.0.rc4"
3
3
  end
@@ -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(: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" }
21
+ let(:logger_code) { defined?(ActiveSupport::TaggedLogging) ? "ActiveSupport::TaggedLogging.new(logger)" : "logger" }
22
22
 
23
23
  describe ".run" do
24
- it "should execute properly" do
25
- expect(installer).to receive(:get_development_preference).exactly(1).times.and_return(:send)
26
- expect(installer).to receive(:get_api_key_storage_preference).exactly(1).times.and_return(:environment)
27
- expect(installer).to receive(:logrageify?).exactly(1).times.and_return(true)
28
- expect(installer).to receive(:initializer).exactly(1).times.and_return(true)
29
- expect(installer).to receive(:logrageify!).exactly(1).times.and_return(true)
30
- expect(installer).to receive(:environment_file_paths).exactly(1).times.and_return(["config/environments/development.rb", "config/environments/production.rb", "config/environments/test.rb"])
31
- expect(installer).to receive(:setup_development_environment).with("config/environments/development.rb", :send).and_return(true)
32
- expect(installer).to receive(:setup_other_environment).with(app, "config/environments/production.rb", :environment).and_return(true)
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
- expect(Timber::CLI::FileHelper).to receive(:read_or_create).
44
- with(config_file_path, initial_config_contents).
45
- and_return(initial_config_contents)
35
+ context "staging" do
36
+ before(:each) do
37
+ app.environment = "staging"
38
+ end
46
39
 
47
- config_file = installer.send(:initializer)
48
- expect(config_file.path).to eq(config_file_path)
49
- end
50
- end
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
- describe ".logrageify?" do
53
- it "should do nothing if Lograge is not detected" do
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 "with a Lograge constant" do
59
- around(:each) do |example|
60
- Lograge = 1
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 prompt for Lograge configuration and return true for y" do
66
- input.string = "y\n"
67
- expect(installer.send(:logrageify?)).to eq(true)
68
- 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
+ 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 ".logrageify!" do
74
- it "should set the option in the config file" do
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
- expect(Timber::CLI::FileHelper).to receive(:read_or_create).
78
- with(config_file_path, initial_config_contents).
79
- and_return(initial_config_contents)
71
+ installer.send(:install_initializer, app)
72
+ end
73
+ end
80
74
 
81
- expect(Timber::CLI::FileHelper).to receive(:read).
82
- with(config_file_path).
83
- and_return(initial_config_contents)
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
- new_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\nconfig.logrageify!\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"
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
- expect(Timber::CLI::FileHelper).to receive(:write).
88
- with(config_file_path, new_config_contents).
89
- and_return(true)
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
- expect(installer.send(:logrageify!)).to eq(true)
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 ".setup_development_environment" do
96
- it "should setup properly" do
97
- env_file_path = "config/environments/development.rb"
206
+ describe ".install_app_environment" do
207
+ context "production" do
208
+ before(:each) do
209
+ app.environment = "production"
210
+ end
98
211
 
99
- expect(Timber::CLI::FileHelper).to receive(:read).
100
- with(env_file_path).
101
- exactly(2).times.
102
- and_return("\nend")
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
- logger_code = defined?(ActiveSupport::TaggedLogging) ? "ActiveSupport::TaggedLogging.new(logger)" : "logger"
105
- new_contents = "\n\n # Install the Timber.io logger, send logs over HTTP.\n # Note: When you are done testing, simply instantiate the logger like this:\n #\n # logger = Timber::Logger.new(STDOUT)\n #\n # Be sure to remove the \"log_device =\" and \"logger =\" lines below.\n log_device = Timber::LogDevices::HTTP.new('abcd1234')\n logger = Timber::Logger.new(log_device)\n logger.level = config.log_level\n config.logger = #{logger_code}\n\nend"
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
- expect(Timber::CLI::FileHelper).to receive(:write).
108
- with(env_file_path, new_contents).
109
- and_return(true)
298
+ result = installer.send(:get_environment_file_path, "development")
299
+ expect(result).to eq(env_file_path)
300
+ end
110
301
 
111
- expect(api).to receive(:event).with(:file_written, path: env_file_path)
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
- expect(installer.send(:setup_development_environment, env_file_path, :send)).to eq(true)
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 ".setup_test_environment" do
118
- it "should setup properly" do
119
- env_file_path = "config/environments/test.rb"
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
- expect(Timber::CLI::FileHelper).to receive(:write).
130
- with(env_file_path, new_contents).
131
- and_return(true)
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(api).to receive(:event).with(:file_written, path: env_file_path)
322
+ expect(installer).to receive(:install_logger).
323
+ with(env_file_path, expected_code).
324
+ exactly(1).times
134
325
 
135
- expect(installer.send(:setup_test_environment, env_file_path)).to eq(true)
326
+ installer.send(:install_nil, env_file_path)
136
327
  end
137
328
  end
138
329
 
139
- describe ".setup_other_environment" do
140
- it "should setup properly" do
141
- env_file_path = "config/environments/production.rb"
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
- expect(Timber::CLI::FileHelper).to receive(:read).
144
- with(env_file_path).
145
- exactly(2).times.
146
- and_return("\nend")
335
+ logger_code = "my code"
147
336
 
148
- logger_code = defined?(ActiveSupport::TaggedLogging) ? "ActiveSupport::TaggedLogging.new(logger)" : "logger"
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
- expect(Timber::CLI::FileHelper).to receive(:write).
152
- with(env_file_path, new_contents).
153
- and_return(true)
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
- expect(api).to receive(:event).with(:file_written, path: env_file_path).exactly(1).times
344
+ new_contents = "\n\nmy code\nend"
156
345
 
157
- expect(installer.send(:setup_other_environment, app, env_file_path, :environment)).to eq(true)
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