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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5f1b00e64f1666ef47d33c347cea42bcc4d7b262
4
- data.tar.gz: cbde1d3d51a40c4e08eb3357f8d1fa72beae5d19
3
+ metadata.gz: 6c4de508448203aa02a9dba6eec487ed04d0ffcf
4
+ data.tar.gz: 8c7e69aad8ab879841ca7d31910e09e86e5c7658
5
5
  SHA512:
6
- metadata.gz: 374705c1b1a8f0e0091d92a4ee0186246af3126a8c4e5e5358591deac6a1f2174052347350d42d1c8d1e79548a9a159438e39bdcbc95a2753182d5b52f18b921
7
- data.tar.gz: baa0ba4b26cc7157710213635f12750da54ee3bde50e7b1fdac74a06da5ba2b1314c66db5aa258cfd8a170d4299b4f866520ba9a63a31a6ee39f200f95c9331e
6
+ metadata.gz: e91f93d4548d7459c5ecdda73917a1cf188301feaab95de3bcd319e8b779a9f250507046010688c459bbfc1a06de058df9caf3329e834d0f6e49d31fe9099c22
7
+ data.tar.gz: d944798f07d4b1bb0ee0d07b34ce321b75918aa5c5b23107ca6e6f62ba532837d474f2f625092f513c977fe7362fbfd4831506383945e28419c68c8fe44950a1
data/README.md CHANGED
@@ -26,8 +26,9 @@ focusing on logging.
26
26
  3. **Seamlessly integrates with popular libraries and frameworks.** - Rails, Rack, Devise,
27
27
  Omniauth, etc. [Automatically captures user context, HTTP context, and event data.](#third-party-integrations)
28
28
 
29
- 4. **Pairs with a modern console.** - Designed specifically for this librariy, hosted, instantly
30
- usable, zero configuration. [Checkout the docs](https://timber.io/docs/app/overview/).
29
+ 4. **Pairs with a modern structured-logging console.** - Designed specifically for structured data,
30
+ hosted, instantly usable, tail users, trace requests.
31
+ [Checkout the docs](https://timber.io/docs/app/tutorials/).
31
32
 
32
33
 
33
34
  ## Installation
@@ -45,16 +46,16 @@ focusing on logging.
45
46
 
46
47
  ## How it works
47
48
 
48
- Let's start with an example. Timber turns this:
49
+ Let's start with an example. Timber turns this production log line:
49
50
 
50
51
  ```
51
- Sent 200 in 45.2ms
52
+ I, [2017-06-04T18:04:53.653812 #42348] INFO -- : [my.host.com] [df88dbaa-50fd-4178-85d7-d66279ea33b6] [192.32.23.12] [bfa8242cd9733bf0211e334be203f0d0] Sent 200 in 45.2ms
52
53
  ```
53
54
 
54
- Into a rich [`http_server_response` event](https://timber.io/docs/ruby/events-and-context/http-server-response-event/).
55
+ Into a structured [`http_server_response` event](https://timber.io/docs/ruby/events-and-context/http-server-response-event/).
55
56
 
56
57
  ```
57
- Sent 200 in 45.2ms @metadata {"dt": "2017-02-02T01:33:21.154345Z", "level": "info", "context": {"http": {"method": "GET", "path": "/path", "remote_addr": "192.32.23.12", "request_id": "abcd1234"}, "system": {"hostname": "1.server.com", "pid": "254354"}, "user": {"id": 1, "name": "Ben Johnson", "email": "bens@email.com"}}, "event": {"http_server_response": {"status": 200, "time_ms": 45.2}}}
58
+ Sent 200 in 45.2ms @metadata {"dt": "2017-02-02T01:33:21.154345Z", "level": "info", "context": {"http": {"method": "GET", "path": "/path", "remote_addr": "192.32.23.12", "request_id": "df88dbaa-50fd-4178-85d7-d66279ea33b6"}, "session": {"id": "bfa8242cd9733bf0211e334be203f0d0"}, "system": {"hostname": "my.host.com", "pid": "254354"}, "user": {"id": 1, "name": "Ben Johnson", "email": "bens@email.com"}}, "event": {"http_server_response": {"status": 200, "time_ms": 45.2}}}
58
59
  ```
59
60
 
60
61
  Notice that instead of completely replacing your log messages,
@@ -72,7 +73,7 @@ logger.info("Sent 200 in 45.2ms")
72
73
 
73
74
  Here's a better look at the metadata:
74
75
 
75
- ```json
76
+ ```js
76
77
  {
77
78
  "dt": "2017-02-02T01:33:21.154345Z",
78
79
  "level": "info",
@@ -83,11 +84,14 @@ Here's a better look at the metadata:
83
84
  "remote_addr": "192.32.23.12",
84
85
  "request_id": "abcd1234"
85
86
  },
87
+ "session": {
88
+ "id": "bfa8242cd9733bf0211e334be203f0d0"
89
+ },
86
90
  "system": {
87
91
  "hostname": "1.server.com",
88
92
  "pid": "254354"
89
93
  },
90
- "user": {
94
+ "user": { // user identifiable logs :O
91
95
  "id": 1,
92
96
  "name": "Ben Johnson",
93
97
  "email": "bens@email.com"
@@ -418,15 +422,18 @@ Lastly, you can checkout how we capture these events in
418
422
 
419
423
  <details><summary><strong>Won't this increase the size of my log data?</strong></summary><p>
420
424
 
421
- Yes. In terms of size, it's no different than adding tags to your logs or any other useful
422
- data. A few things to point out though:
423
-
424
- 1. Timber generally _reduces_ the amount of logs your app generates by providing options to
425
- consolidate request / response logs, template logs, and even silence logs that are not
426
- of value to you. (see [configuration](#configuration) for examples).
427
- 2. Your log provider should be compressing your data and charging you accordingly. Log data
428
- is notoriously repetitive, and the context Timber generates is repetitive as well.
429
- Because of compression we've seen somes apps only incur a 10% increase in data size.
425
+ Yes, but it's no different than adding any other useful data to your logs, such as
426
+ [tags](http://api.rubyonrails.org/classes/ActiveSupport/TaggedLogging.html). A few
427
+ of things to note:
428
+
429
+ 1. Timber generally _reduces_ the amount of logs your app generates, trading quality for quantity.
430
+ It does so by providing options to consolidate request / response logs, template logs, and
431
+ even silence logs that are not of value to you. (see [configuration](#configuration) for examples).
432
+ 2. Timber lets you pick exactly which events and contexts you want.
433
+ (see [configuration](#configuration) for examples)
434
+ 3. Your logging provider should be compressing your data and charging you accordingly. Log data
435
+ is notoriously repetitive, and the context Timber generates is repetitive.
436
+ Because of compression we've seen somes apps only incur a ~15% increase in data size.
430
437
 
431
438
  Finally, log what is useful to you. Quality over quantity certainly applies to logging.
432
439
 
@@ -64,7 +64,7 @@ module Timber
64
64
  HAS_LOGS_PATH = "/installer/has_logs".freeze
65
65
  USER_AGENT = "Timber Ruby/#{Timber::VERSION} (HTTP)".freeze
66
66
 
67
- attr_reader :api_key
67
+ attr_accessor :api_key
68
68
 
69
69
  def initialize(api_key)
70
70
  @api_key = api_key
@@ -103,7 +103,7 @@ module Timber
103
103
  when 0
104
104
  event(:waiting_for_logs)
105
105
  when 20
106
- event(:excessively_waiting_for_logs)
106
+ event(:excessive_log_waiting)
107
107
  when 60
108
108
  raise LogsNotReceivedError.new
109
109
  end
@@ -142,7 +142,10 @@ module Timber
142
142
  end
143
143
 
144
144
  def issue!(req)
145
- req['Authorization'] = "Basic #{encoded_api_key}"
145
+ if api_key
146
+ req['Authorization'] = "Basic #{encoded_api_key}"
147
+ end
148
+
146
149
  req['User-Agent'] = USER_AGENT
147
150
  req['X-Installer-Session-Id'] = @session_id
148
151
  res = http.start do |http|
@@ -2,7 +2,8 @@ module Timber
2
2
  class CLI
3
3
  class API
4
4
  class Application
5
- DEVELOPMENT = "development".freeze
5
+ DEVELOPMENT_ENVIRONMENT = "development".freeze
6
+ TEST_ENVIRONMENT = "test".freeze
6
7
  HEROKU = "heroku".freeze
7
8
 
8
9
  attr_accessor :api_key, :environment, :framework_type, :heroku_drain_url,
@@ -18,7 +19,11 @@ module Timber
18
19
  end
19
20
 
20
21
  def development?
21
- environment == DEVELOPMENT
22
+ environment == DEVELOPMENT_ENVIRONMENT
23
+ end
24
+
25
+ def test?
26
+ environment == TEST_ENVIRONMENT
22
27
  end
23
28
 
24
29
  def heroku?
@@ -7,27 +7,24 @@ module Timber
7
7
 
8
8
  def initialize(path)
9
9
  @path = path
10
- FileHelper.read_or_create(path, initial_content)
10
+ end
11
+
12
+ def create!
13
+ FileHelper.write(path, content)
14
+ end
15
+
16
+ def exists?
17
+ File.exists?(path)
11
18
  end
12
19
 
13
20
  def logrageify!
14
- append("config.logrageify!")
21
+ append!("config.logrageify!")
15
22
  end
16
23
 
17
24
  private
18
- def get_content
19
- FileHelper.read(path)
20
- end
21
-
22
- def append(code)
23
- current_content = get_content
24
- if !current_content.include?(code)
25
- if current_content.include?(insert_hook)
26
- new_content = current_content.gsub(insert_hook, "#{code}\n\n#{insert_hook}")
27
- FileHelper.write(path, new_content)
28
- else
29
- FileHelper.append(path, new_content)
30
- end
25
+ def append!(code)
26
+ if !content.include?(code)
27
+ content.gsub!(insert_hook, "#{code}\n\n#{insert_hook}")
31
28
  end
32
29
 
33
30
  true
@@ -39,8 +36,8 @@ module Timber
39
36
 
40
37
  # We provide this as an instance method so that the string is only defined when needed.
41
38
  # This avoids allocating this string during normal app runtime.
42
- def initial_content
43
- <<-CONTENT
39
+ def content
40
+ @content ||= <<-CONTENT
44
41
  # Timber.io Ruby Configuration - Simple Structured Logging
45
42
  #
46
43
  # ^ ^ ^ ^ ___I_ ^ ^ ^ ^ ^ ^ ^
@@ -1,32 +1,44 @@
1
1
  module Timber
2
2
  class CLI
3
- module FileHelper
4
- def self.append(path, contents)
3
+ class FileHelper
4
+ attr_reader :api
5
+
6
+ def initialize(api)
7
+ @api = api
8
+ end
9
+
10
+ def append(path, contents)
5
11
  File.open(path, "a") do |f|
6
12
  f.write(contents)
7
13
  end
8
14
  end
9
15
 
10
- def self.read_or_create(path, contents)
11
- if !File.exists?(path)
16
+ def exists?(path)
17
+ File.exists?(path)
18
+ end
19
+
20
+ def read_or_create(path, contents)
21
+ if !exists?(path)
12
22
  write(path, contents)
13
23
  end
14
24
 
15
- File.read(path)
25
+ read(path)
16
26
  end
17
27
 
18
- def self.read(path)
28
+ def read(path)
19
29
  File.read(path)
20
30
  end
21
31
 
22
- def self.write(path, contents)
32
+ def write(path, contents)
23
33
  File.open(path, "w") do |f|
24
34
  f.write(contents)
25
35
  end
36
+
37
+ api.event(:file_written, path: path)
26
38
  end
27
39
 
28
- def self.verify(path, io)
29
- if !File.exists?(path)
40
+ def verify(path, io)
41
+ if !exists?(path)
30
42
  io.puts ""
31
43
  io.puts "Uh oh! It looks like we couldn't locate the #{path} file. "
32
44
  io.puts "Please enter the correct path:"
@@ -1,13 +1,15 @@
1
+ require "timber/cli/file_helper"
1
2
  require "timber/cli/io/messages"
2
3
 
3
4
  module Timber
4
5
  class CLI
5
6
  class Installer
6
- attr_reader :io, :api
7
+ attr_reader :io, :api, :file_helper
7
8
 
8
9
  def initialize(io, api)
9
10
  @io = io
10
11
  @api = api
12
+ @file_helper = FileHelper.new(api)
11
13
  end
12
14
 
13
15
  def run(app)
@@ -9,57 +9,65 @@ module Timber
9
9
  class CLI
10
10
  module Installers
11
11
  def self.run(api_key, io)
12
- io.puts IO::Messages.header, :green
13
- io.puts IO::Messages.separator, :green
14
- io.puts IO::Messages.contact, :green
15
- io.puts IO::Messages.separator, :green
16
- io.puts ""
12
+ api = API.new(api_key)
13
+ api.event(:started)
17
14
 
18
- if !api_key
19
- app_url = IO::Messages::APP_URL
20
-
21
- io.puts "Hey there! Welcome to Timber. In order to proceed, you'll need an API key."
22
- io.puts "You can grab one by registering at #{IO::ANSI.colorize(app_url, :blue)}."
23
- io.puts ""
24
- io.puts "It takes less than a minute, with one click Google and Github registration."
15
+ begin
16
+ io.puts IO::Messages.header, :green
17
+ io.puts IO::Messages.separator, :green
18
+ io.puts IO::Messages.contact, :green
19
+ io.puts IO::Messages.separator, :green
25
20
  io.puts ""
26
21
 
27
- if OSHelper.can_open?
28
- case io.ask_yes_no("Open #{app_url}?")
29
- when :yes
30
- puts ""
31
- io.task("Opening #{app_url}") do
32
- OSHelper.open(app_url)
22
+ if !api_key
23
+ api.event(:no_api_key)
24
+
25
+ app_url = IO::Messages::APP_URL
26
+
27
+ io.puts "Hey there! Welcome to Timber. In order to proceed, you'll need an API key."
28
+ io.puts "You can grab one by registering at #{IO::ANSI.colorize(app_url, :blue)}."
29
+ io.puts ""
30
+ io.puts "It takes less than a minute, with one click Google and Github registration."
31
+ io.puts ""
32
+
33
+ if OSHelper.can_open?
34
+ case io.ask_yes_no("Open #{app_url}?")
35
+ when :yes
36
+ puts ""
37
+ io.task("Opening #{app_url}") do
38
+ OSHelper.open(app_url)
39
+ end
40
+ when :no
41
+ io.puts ""
42
+ io.puts "No problem, navigate to the following URL:"
43
+ io.puts ""
44
+ io.puts " #{IO::ANSI.colorize(app_url, :blue)}"
33
45
  end
34
- when :no
46
+ else
35
47
  io.puts ""
36
- io.puts "No problem, navigate to the following URL:"
48
+ io.puts "Please navigate to:"
37
49
  io.puts ""
38
50
  io.puts " #{IO::ANSI.colorize(app_url, :blue)}"
39
51
  end
40
- else
52
+
41
53
  io.puts ""
42
- io.puts "Please navigate to:"
54
+ io.puts "Once you obtain your API key, you can run the installer like"
43
55
  io.puts ""
44
- io.puts " #{IO::ANSI.colorize(app_url, :blue)}"
45
- end
46
-
47
- io.puts ""
48
- io.puts "Once you obtain your API key, you can run the installer like"
49
- io.puts ""
50
- io.puts " #{IO::ANSI.colorize("bundle exec timber my-api-key", :blue)}"
51
- io.puts ""
52
- io.puts "See you soon! 🎈"
53
- io.puts ""
54
- else
55
- api = API.new(api_key)
56
- api.event(:started)
57
-
58
- io.api = api
56
+ io.puts " #{IO::ANSI.colorize("bundle exec timber my-api-key", :blue)}"
57
+ io.puts ""
58
+ io.puts "See you soon! 🎈"
59
+ io.puts ""
60
+ else
61
+ api.event(:api_key_provided)
62
+ io.api = api
59
63
 
60
- app = api.application!
64
+ app = api.application!
61
65
 
62
- Root.new(io, api).run(app)
66
+ Root.new(io, api).run(app)
67
+ end
68
+ rescue Exception => e
69
+ api.event(:exception, message: e.message, stacktrace: e.backtrace)
70
+ raise e
63
71
  end
64
72
  end
65
73
  end
@@ -0,0 +1,60 @@
1
+ begin
2
+ require "lograge"
3
+ rescue Exception
4
+ end
5
+
6
+ require "timber/cli/config_file"
7
+ require "timber/cli/installer"
8
+ require "timber/cli/io/messages"
9
+
10
+ module Timber
11
+ class CLI
12
+ module Installers
13
+ class ConfigFile < Installer
14
+ def run(app, path)
15
+ config_file = Timber::CLI::ConfigFile.new(path)
16
+
17
+ if config_file.exists?
18
+ io.puts ""
19
+ io.task_complete("#{config_file.path} already created")
20
+ return true
21
+ end
22
+
23
+ if logrageify?
24
+ config_file.logrageify!
25
+ end
26
+
27
+ io.puts ""
28
+ task_message = "Creating #{config_file.path}"
29
+ io.task(task_message) { config_file.create! }
30
+ end
31
+
32
+ private
33
+ def logrageify?
34
+ if defined?(::Lograge)
35
+ io.puts ""
36
+ io.puts IO::Messages.separator
37
+ io.puts ""
38
+ io.puts "We noticed you have lograge installed. Would you like to configure "
39
+ io.puts "Timber to function similarly?"
40
+ io.puts "(This silences template renders, sql queries, and controller calls."
41
+ io.puts "You can always do this later in config/initialzers/timber.rb)"
42
+ io.puts ""
43
+ io.puts "y) Yes, configure Timber like lograge", :blue
44
+ io.puts "n) No, use the Rails logging defaults", :blue
45
+ io.puts ""
46
+
47
+ case io.ask_yes_no("Enter your choice:", event_prompt: "Logrageify?")
48
+ when :yes
49
+ true
50
+ when :no
51
+ false
52
+ end
53
+ else
54
+ false
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -14,13 +14,7 @@ module Timber
14
14
  install_http(api_key_code)
15
15
  end
16
16
 
17
- io.puts ""
18
- io.puts IO::Messages.separator
19
- io.puts ""
20
- io.puts "We're going to send a few test messages to ensure communication is working."
21
- io.puts ""
22
- io.ask_to_proceed
23
- io.puts ""
17
+ ask_to_proceed
24
18
  end
25
19
 
26
20
  private
@@ -48,6 +42,16 @@ module Timber
48
42
  io.puts ""
49
43
  io.ask_to_proceed
50
44
  end
45
+
46
+ def ask_to_proceed
47
+ io.puts ""
48
+ io.puts IO::Messages.separator
49
+ io.puts ""
50
+ io.puts "We're going to send a few test messages to ensure communication is working."
51
+ io.puts ""
52
+ io.ask_to_proceed
53
+ io.puts ""
54
+ end
51
55
  end
52
56
  end
53
57
  end