timber 2.0.24 → 2.1.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -2
  3. data/CHANGELOG +3 -0
  4. data/README.md +314 -59
  5. data/bin/timber +11 -2
  6. data/lib/timber.rb +2 -7
  7. data/lib/timber/cli.rb +16 -28
  8. data/lib/timber/cli/api.rb +80 -14
  9. data/lib/timber/cli/api/application.rb +30 -0
  10. data/lib/timber/cli/config_file.rb +66 -0
  11. data/lib/timber/cli/file_helper.rb +43 -0
  12. data/lib/timber/cli/installer.rb +58 -0
  13. data/lib/timber/cli/installers.rb +37 -0
  14. data/lib/timber/cli/installers/other.rb +47 -0
  15. data/lib/timber/cli/installers/rails.rb +255 -0
  16. data/lib/timber/cli/installers/root.rb +189 -0
  17. data/lib/timber/cli/io.rb +97 -0
  18. data/lib/timber/cli/io/ansi.rb +22 -0
  19. data/lib/timber/cli/io/messages.rb +213 -0
  20. data/lib/timber/cli/os_helper.rb +53 -0
  21. data/lib/timber/config.rb +97 -43
  22. data/lib/timber/config/integrations.rb +63 -0
  23. data/lib/timber/config/integrations/rack.rb +74 -0
  24. data/lib/timber/context.rb +13 -10
  25. data/lib/timber/contexts.rb +1 -0
  26. data/lib/timber/contexts/custom.rb +16 -3
  27. data/lib/timber/contexts/http.rb +10 -3
  28. data/lib/timber/contexts/organization.rb +4 -0
  29. data/lib/timber/contexts/release.rb +46 -0
  30. data/lib/timber/contexts/runtime.rb +7 -1
  31. data/lib/timber/contexts/session.rb +8 -1
  32. data/lib/timber/contexts/system.rb +5 -1
  33. data/lib/timber/contexts/user.rb +9 -2
  34. data/lib/timber/current_context.rb +43 -11
  35. data/lib/timber/events/controller_call.rb +4 -0
  36. data/lib/timber/events/custom.rb +13 -5
  37. data/lib/timber/events/exception.rb +4 -0
  38. data/lib/timber/events/http_client_request.rb +4 -0
  39. data/lib/timber/events/http_client_response.rb +4 -0
  40. data/lib/timber/events/http_server_request.rb +5 -0
  41. data/lib/timber/events/http_server_response.rb +15 -3
  42. data/lib/timber/events/sql_query.rb +3 -0
  43. data/lib/timber/events/template_render.rb +3 -0
  44. data/lib/timber/integration.rb +40 -0
  45. data/lib/timber/integrations.rb +21 -14
  46. data/lib/timber/integrations/action_controller.rb +18 -0
  47. data/lib/timber/integrations/action_controller/log_subscriber.rb +2 -0
  48. data/lib/timber/integrations/action_controller/log_subscriber/timber_log_subscriber.rb +6 -0
  49. data/lib/timber/integrations/action_dispatch.rb +23 -0
  50. data/lib/timber/integrations/action_dispatch/debug_exceptions.rb +2 -0
  51. data/lib/timber/integrations/action_view.rb +18 -0
  52. data/lib/timber/integrations/action_view/log_subscriber.rb +2 -0
  53. data/lib/timber/integrations/action_view/log_subscriber/timber_log_subscriber.rb +10 -0
  54. data/lib/timber/integrations/active_record.rb +18 -0
  55. data/lib/timber/integrations/active_record/log_subscriber.rb +2 -0
  56. data/lib/timber/integrations/active_record/log_subscriber/timber_log_subscriber.rb +8 -0
  57. data/lib/timber/integrations/rack.rb +12 -2
  58. data/lib/timber/integrations/rack/exception_event.rb +38 -5
  59. data/lib/timber/integrations/rack/http_context.rb +4 -6
  60. data/lib/timber/integrations/rack/http_events.rb +177 -27
  61. data/lib/timber/integrations/rack/middleware.rb +28 -0
  62. data/lib/timber/integrations/rack/session_context.rb +5 -6
  63. data/lib/timber/integrations/rack/user_context.rb +90 -43
  64. data/lib/timber/integrations/rails.rb +22 -0
  65. data/lib/timber/integrations/rails/rack_logger.rb +2 -0
  66. data/lib/timber/integrator.rb +18 -3
  67. data/lib/timber/log_devices/http.rb +107 -99
  68. data/lib/timber/log_devices/http/dropping_sized_queue.rb +26 -0
  69. data/lib/timber/log_devices/http/flushable_sized_queue.rb +42 -0
  70. data/lib/timber/log_entry.rb +14 -2
  71. data/lib/timber/logger.rb +51 -36
  72. data/lib/timber/overrides.rb +2 -0
  73. data/lib/timber/overrides/active_support_3_tagged_logging.rb +103 -0
  74. data/lib/timber/overrides/active_support_tagged_logging.rb +53 -90
  75. data/lib/timber/timer.rb +21 -0
  76. data/lib/timber/util/hash.rb +1 -1
  77. data/lib/timber/util/http_event.rb +16 -3
  78. data/lib/timber/version.rb +1 -1
  79. data/spec/support/timber.rb +2 -3
  80. data/spec/timber/cli/installers/rails_spec.rb +160 -0
  81. data/spec/timber/cli/installers/root_spec.rb +100 -0
  82. data/spec/timber/config_spec.rb +28 -0
  83. data/spec/timber/current_context_spec.rb +61 -12
  84. data/spec/timber/events/custom_spec.rb +13 -2
  85. data/spec/timber/events/exception_spec.rb +15 -0
  86. data/spec/timber/events/http_server_request_spec.rb +3 -3
  87. data/spec/timber/integrations/rack/http_events_spec.rb +101 -0
  88. data/spec/timber/log_devices/http_spec.rb +20 -4
  89. data/spec/timber/log_entry_spec.rb +2 -1
  90. data/spec/timber/logger_spec.rb +8 -8
  91. metadata +40 -9
  92. data/benchmarks/rails.rb +0 -122
  93. data/lib/timber/cli/application.rb +0 -28
  94. data/lib/timber/cli/install.rb +0 -196
  95. data/lib/timber/cli/io_helper.rb +0 -65
  96. data/lib/timber/cli/messages.rb +0 -180
  97. data/lib/timber/integrations/active_support/tagged_logging.rb +0 -71
@@ -1,28 +0,0 @@
1
- require "json"
2
-
3
- module Timber
4
- class CLI
5
- class Application
6
-
7
- attr_reader :api_key, :environment, :framework_type, :heroku_drain_url, :language_type,
8
- :name, :platform_type
9
-
10
- def initialize(api)
11
- res = api.application!
12
- parsed_body = JSON.parse(res.body)
13
- application_data = parsed_body.fetch("data")
14
- @api_key = application_data.fetch("api_key")
15
- @environment = application_data.fetch("environment")
16
- @framework_type = application_data.fetch("framework_type")
17
- @heroku_drain_url = application_data.fetch("heroku_drain_url")
18
- @language_type = application_data.fetch("language_type")
19
- @name = application_data.fetch("name")
20
- @platform_type = application_data.fetch("platform_type")
21
- end
22
-
23
- def heroku?
24
- platform_type == "heroku"
25
- end
26
- end
27
- end
28
- end
@@ -1,196 +0,0 @@
1
- require "fileutils"
2
-
3
- module Timber
4
- class CLI
5
- class Install
6
- EXCLUDED_ENVIRONMENTS = ["test"].freeze
7
-
8
- class << self
9
- include IOHelper
10
-
11
- def run(api_key)
12
- puts colorize(Messages.header, :green)
13
- puts colorize(Messages.separator, :green)
14
- puts colorize(Messages.contact, :green)
15
- puts colorize(Messages.separator, :green)
16
- puts ""
17
-
18
- if !api_key
19
- puts Messages.no_api_key_provided
20
- return
21
- end
22
-
23
- api = API.new(api_key)
24
-
25
- api.event!(:started)
26
-
27
- app = Application.new(api)
28
-
29
- puts Messages.application_details(app)
30
- puts ""
31
-
32
- case ask_yes_no("Are the above details correct?", api)
33
- when :yes
34
- if app.heroku?
35
- update_environment_config("production", :stdout, api)
36
-
37
- puts ""
38
- puts Messages.separator
39
- puts ""
40
- puts Messages.heroku_install(app)
41
- puts ""
42
-
43
- ask_yes_no("Ready to proceed?", api)
44
- puts ""
45
-
46
- else
47
- puts ""
48
- puts Messages.separator
49
- puts ""
50
- puts "How would you like configure Timber?"
51
- puts ""
52
- puts "1) Using environment variables"
53
- puts "2) Configuring in my app"
54
- puts ""
55
-
56
- case ask("Enter your choice: (1/2) ", api)
57
- when "1"
58
- update_environment_config("production", :http, api, :api_key_code => "ENV['TIMBER_API_KEY']")
59
-
60
- puts ""
61
- puts Messages.http_environment_variables(app.api_key)
62
- puts ""
63
-
64
- ask_yes_no("Ready to proceed?", api)
65
- puts ""
66
-
67
- when "2"
68
- update_environment_config("production", :http, api, :api_key_code => "'#{app.api_key}'")
69
-
70
- end
71
-
72
- send_test_messages(api_key)
73
- end
74
-
75
-
76
- api.wait_for_logs do |iteration|
77
- write Messages.task_start("Waiting for logs")
78
- write Messages.spinner(iteration)
79
- end
80
-
81
- puts colorize(Messages.task_complete("Waiting for logs"), :green)
82
-
83
- puts ""
84
- puts Messages.separator
85
- puts ""
86
- puts Messages.commit_and_deploy_reminder
87
-
88
- api.event!(:success)
89
-
90
- collect_feedback(api)
91
-
92
- puts ""
93
- puts Messages.separator
94
- puts ""
95
- puts Messages.free_data
96
- puts ""
97
-
98
- when :no
99
- puts ""
100
- puts "Bummer. Head to this URL to update the details:"
101
- puts ""
102
- puts " #{Messages.edit_app_url(app)}"
103
- puts ""
104
- puts "exiting..."
105
- return false
106
- end
107
- end
108
-
109
- private
110
- def update_environment_config(name, log_device_type, api, options = {})
111
- path = File.join("config", "environments", "#{name}.rb")
112
-
113
- puts ""
114
- task_message = "Configuring Timber in #{path}"
115
- write Messages.task_start(task_message)
116
-
117
- init_logger_code = defined?(::ActiveSupport::TaggedLogging) ? "ActiveSupport::TaggedLogging.new(logger)" : "logger"
118
-
119
- logger_code = \
120
- case log_device_type
121
- when :http
122
- api_key_code = options[:api_key_code] || raise(ArgumentError.new("the :api_key_code option is required"))
123
-
124
- code = <<-CODE
125
- # Install the Timber.io logger, send logs over HTTP
126
- log_device = Timber::LogDevices::HTTP.new(#{api_key_code})
127
- logger = Timber::Logger.new(log_device)
128
- logger.level = config.log_level
129
- config.logger = #{init_logger_code}
130
- CODE
131
- code.rstrip
132
-
133
- when :stdout
134
- code = <<-CODE
135
- # Install the Timber.io logger, send logs to STDOUT
136
- logger = Timber::Logger.new(STDOUT)
137
- logger.level = config.log_level
138
- config.logger = #{init_logger_code}
139
- CODE
140
- code.rstrip
141
- end
142
-
143
-
144
- current_contents = File.read(path)
145
-
146
- if !current_contents.include?("Timber::Logger.new")
147
- new_contents = current_contents.sub(/\nend/, "\n\n#{logger_code}\nend")
148
- File.write(path, new_contents)
149
- api.event!(:file_written, path: path)
150
- end
151
-
152
- puts colorize(Messages.task_complete(task_message), :green)
153
- end
154
-
155
- def send_test_messages(api_key)
156
- write Messages.task_start("Sending test logs")
157
-
158
- http_device = LogDevices::HTTP.new(api_key)
159
- logger = Logger.new(http_device)
160
- logger.info("Welcome to Timber!")
161
- logger.info("This is a test log to ensure the pipes are working")
162
- logger.info("Be sure to commit and deploy your app to start seeing real logs")
163
-
164
- puts colorize(Messages.task_complete("Sending test logs"), :green)
165
- end
166
-
167
- def collect_feedback(api)
168
- puts ""
169
- puts Messages.separator
170
- puts ""
171
-
172
- rating = ask("How would rate this install experience? 1 (bad) - 5 (perfect)", api)
173
-
174
- case rating
175
- when "4", "5"
176
- api.event!(:feedback, rating: rating.to_i)
177
- puts ""
178
- puts Messages.we_love_you_too
179
-
180
- when "1", "2", "3"
181
- puts ""
182
- puts Messages.bad_experience_message
183
- puts ""
184
-
185
- comments = ask("Type your comments (enter sends)", api)
186
-
187
- api.event!(:feedback, rating: rating.to_i, comments: comments)
188
-
189
- puts ""
190
- puts "Thank you! We take feedback seriously and will work to improve this."
191
- end
192
- end
193
- end
194
- end
195
- end
196
- end
@@ -1,65 +0,0 @@
1
- module Timber
2
- class CLI
3
- module IOHelper
4
- def ask(message, api)
5
- api.event!(:waiting_for_input, prompt: message)
6
-
7
- write message + " "
8
- input = gets
9
-
10
- api.event!(:received_input, prompt: message, value: input)
11
-
12
- input
13
- end
14
-
15
- def ask_yes_no(message, api)
16
- case ask(message + " (y/n)", api)
17
- when "y", "Y"
18
- :yes
19
- when "n", "N"
20
- :no
21
- else
22
- puts "Woops! That's not a valid input. Please try again."
23
- ask_yes_no(message, api)
24
- end
25
- end
26
-
27
- def colorize(text, color)
28
- return text if Gem.win_platform?
29
-
30
- code =
31
- case color
32
- when :blue then 34
33
- when :red then 31
34
- when :green then 32
35
- when :yellow then 33
36
- else 0
37
- end
38
-
39
- "\e[#{code}m#{text}\e[0m"
40
- end
41
-
42
- def gets
43
- value = stdin.gets
44
- value ? value.chomp.downcase : ""
45
- end
46
-
47
- def puts(message)
48
- stdout.puts(message)
49
- end
50
-
51
- def write(message)
52
- stdout.write(message)
53
- end
54
-
55
- private
56
- def stdout
57
- $stdout
58
- end
59
-
60
- def stdin
61
- $stdin
62
- end
63
- end
64
- end
65
- end
@@ -1,180 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Timber
4
- class CLI
5
- module Messages
6
- include IOHelper
7
-
8
- extend self
9
-
10
- APP_URL = "https://app.timber.io"
11
- DOCS_URL = "https://timber.io/docs"
12
- REPO_URL = "https://github.com/timberio/timber-ruby"
13
- SUPPORT_EMAIL = "support@timber.io"
14
- TWITTER_HANDLE = "@timberdotio"
15
- WEBSITE_URL = "https://timber.io"
16
- MAX_LENGTH = 80.freeze
17
-
18
- def application_details(app)
19
- message = <<-MESSAGE
20
- Woot! Your API 🔑 is valid:
21
-
22
- Name: #{app.name} (#{app.environment})
23
- Framework: #{app.framework_type}
24
- Platform: #{app.platform_type}
25
- MESSAGE
26
- message.rstrip
27
- end
28
-
29
- def edit_app_url(app)
30
- "#{APP_URL}"
31
- end
32
-
33
- def bad_experience_message
34
- message = <<-MESSAGE
35
- Bummer! That is certainly not the experience we were going for.
36
-
37
- Could you tell us why you a bad experience?
38
-
39
- (this will be sent directly to the Timber engineering team)
40
- MESSAGE
41
- message.rstrip
42
- end
43
-
44
- def commit_and_deploy_reminder
45
- message = <<-MESSAGE
46
- Last step! Commit and deploy:
47
-
48
- #{colorize("git commit -m 'Install Timber' config/environments/production.rb", :blue)}
49
-
50
- #{colorize("push and deploy", :blue)} 🚀
51
- MESSAGE
52
- message.rstrip
53
- end
54
-
55
- def console_url(app)
56
- message = <<-MESSAGE
57
- Your console URL: https://app.timber.io/organizations/timber/apps/#{app.slug}/console
58
- MESSAGE
59
- end
60
-
61
- def contact
62
- message = <<-MESSAGE
63
- Website: #{WEBSITE_URL}
64
- Documentation: #{DOCS_URL}
65
- Support: #{SUPPORT_EMAIL}
66
- MESSAGE
67
- message.rstrip
68
- end
69
-
70
- def http_environment_variables(api_key)
71
- message = <<-MESSAGE
72
- Great! Add this variable to your environment:
73
-
74
- #{colorize("export TIMBER_API_KEY=\"#{api_key}\"", :blue)}
75
-
76
- MESSAGE
77
- message.rstrip
78
- end
79
-
80
- def free_data
81
- message = <<-MESSAGE
82
- As a welcome gift, we've credited your account with ✨ 50mb✨. Get more:
83
-
84
- * Get ✨ 250mb✨ for tweeting your experience to #{TWITTER_HANDLE}
85
- * Get ✨ 100mb✨ for starring our repo: #{REPO_URL}
86
- * Get ✨ 100mb✨ for following #{TWITTER_HANDLE} on twitter
87
- MESSAGE
88
- message.rstrip
89
- end
90
-
91
- def header
92
- message = <<-MESSAGE
93
- 🌲 Timber.io Ruby Installer
94
-
95
- ^ ^ ^ ^ ___I_ ^ ^ ^ ^ ^ ^ ^
96
- /|\\/|\\/|\\ /|\\ /\\-_--\\ /|\\/|\\ /|\\/|\\/|\\ /|\\/|\\
97
- /|\\/|\\/|\\ /|\\ / \\_-__\\ /|\\/|\\ /|\\/|\\/|\\ /|\\/|\\
98
- /|\\/|\\/|\\ /|\\ |[]| [] | /|\\/|\\ /|\\/|\\/|\\ /|\\/|\\
99
- MESSAGE
100
- message.rstrip
101
- end
102
-
103
- def heroku_install(app)
104
- message = <<-MESSAGE
105
- To send logs from Heroku please run this command in a separate window:
106
-
107
- #{colorize("heroku drains:add #{app.heroku_drain_url}", :blue)}
108
-
109
- MESSAGE
110
- message.rstrip
111
- end
112
-
113
- def no_api_key_provided
114
- message = <<-MESSAGE
115
- Hey there! Welcome to Timber. In order to proceed, you'll need an API key.
116
- If you already have one, you can run this installer like:
117
-
118
- #{colorize("bundle exec timber install my-api-key", :blue)}
119
-
120
- #{obtain_key_instructions}
121
- MESSAGE
122
- message.rstrip
123
- end
124
-
125
- def obtain_key_instructions
126
- message = <<-MESSAGE
127
- Don't have a key? Head over to:
128
-
129
- #{colorize("https://app.timber.io", :blue)}
130
-
131
- Once there, create an application. Your API key will be displayed afterwards.
132
- For more detailed instructions, checkout our docs page:
133
-
134
- https://timber.io/docs/app/obtain-api-key/
135
-
136
- If you're confused, don't hesitate to contact us: #{SUPPORT_EMAIL}
137
-
138
- MESSAGE
139
- message.rstrip
140
- end
141
-
142
- def separator
143
- "--------------------------------------------------------------------------------"
144
- end
145
-
146
- def spinner(iteration)
147
- rem = iteration % 3
148
- case rem
149
- when 0
150
- "/"
151
- when 1
152
- "-"
153
- when 2
154
- "\\"
155
- end
156
- end
157
-
158
- def success
159
- "✓ Success!"
160
- end
161
-
162
- def task_complete(message)
163
- remainder = MAX_LENGTH - message.length - success.length
164
-
165
- dots = "." * remainder
166
- "\r#{message}#{dots}#{success}"
167
- end
168
-
169
- def task_start(message)
170
- remainder = MAX_LENGTH - message.length - success.length
171
-
172
- "\r#{message}" + ("." * remainder)
173
- end
174
-
175
- def we_love_you_too
176
- "Thanks! We 💖 you too!"
177
- end
178
- end
179
- end
180
- end