heavylog 0.0.16 → 0.0.21

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
  SHA256:
3
- metadata.gz: 14234701b389d0f983d0195b56bff88b36bd5b20303dde3831e24c09c1413857
4
- data.tar.gz: d64b00d6db92f63d676c245259dd40bf32e0aa86a4390d5603eacd66d06ac31c
3
+ metadata.gz: 1e5698a7bfa3d9476d9b35f0a0da99a7faeeb230df8889599cf343b017745488
4
+ data.tar.gz: 74d24b9be2f75463929bc5de1cb076fca87cb7b707a7123474a95682b3899e4a
5
5
  SHA512:
6
- metadata.gz: '08f1ce54b82fa3e501535b1d78725f81ae4f2e6a004bba8b75e1b10f954e93473eb25aa3f5a740dd88543438b10b051cafa1c1742e5ee47432a6778d40a3fbc8'
7
- data.tar.gz: 95f42f4607951a35b499e022028a0f9e4d4d3de063ffe8a9c88d74852827c0b3a3751b3a82affed322d252c193a6a957aee57bc4cc317166e9f4261a49c3047f
6
+ metadata.gz: 1dde2fc6a5912a2345729bd7150d1a6c39b55ab4f90800ee2cbe61acb3f351c978ecadea820981ba1cc94180140d8ddbab0f0f6890901c6251a906b2be9343a7
7
+ data.tar.gz: b7a5930b2cba4fa6501798ac200978a5c172cda4af2b0d1dd55dc23bf0373edde9c722b1b3cbf658f68163d03adee190814f3d342bf621bf5d11c7eeab03dbaa
data/.editorconfig ADDED
@@ -0,0 +1,14 @@
1
+ # This file is for unifying the coding style for different editors and IDEs
2
+ # editorconfig.org
3
+
4
+ root = true
5
+
6
+ [*]
7
+ charset = utf-8
8
+ trim_trailing_whitespace = false
9
+ insert_final_newline = true
10
+ indent_style = space
11
+ indent_size = 2
12
+
13
+ [*.md]
14
+ trim_trailing_whitespace = true
@@ -0,0 +1,33 @@
1
+ name: Test
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ test:
7
+ name: Build
8
+ runs-on: ubuntu-latest
9
+
10
+ steps:
11
+ - uses: actions/checkout@v1
12
+ - name: Set up Ruby
13
+ uses: ruby/setup-ruby@v1
14
+ with:
15
+ ruby-version: 3.0.1
16
+
17
+ - uses: actions/cache@v1
18
+ with:
19
+ path: vendor/bundle
20
+ key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }}
21
+ restore-keys: |
22
+ ${{ runner.os }}-gem-
23
+
24
+ - name: Install dependencies
25
+ run: |
26
+ gem install bundler
27
+ bundle config path vendor/bundle
28
+ bundle install --jobs 4 --retry 3
29
+
30
+ - name: Run tests
31
+ env:
32
+ CI: true
33
+ run: bundle exec rspec
data/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /log/
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
data/.rubocop.yml CHANGED
@@ -2,46 +2,42 @@ require:
2
2
  - rubocop-performance
3
3
 
4
4
  AllCops:
5
- TargetRubyVersion: 2.5
5
+ TargetRubyVersion: 3.0
6
6
 
7
7
  # # Commonly used screens these days easily fit more than 80 characters.
8
- Metrics/LineLength:
8
+ Layout/LineLength:
9
9
  Max: 120
10
10
 
11
11
  # Too short methods lead to extraction of single-use methods, which can make
12
12
  # the code easier to read (by naming things), but can also clutter the class
13
13
  Metrics/MethodLength:
14
- Max: 125
14
+ Enabled: false
15
15
 
16
16
  # The guiding principle of classes is SRP, SRP can't be accurately measured by LoC
17
17
  Metrics/ClassLength:
18
- Max: 1500
18
+ Enabled: false
19
19
 
20
20
  Metrics/AbcSize:
21
- Max: 160
21
+ Enabled: false
22
22
 
23
23
  Metrics/CyclomaticComplexity:
24
- Max: 45
24
+ Enabled: false
25
25
 
26
26
  Metrics/PerceivedComplexity:
27
- Max: 45
27
+ Enabled: false
28
28
 
29
29
  Metrics/ParameterLists:
30
- Max: 6
30
+ Enabled: false
31
31
 
32
32
  Metrics/ModuleLength:
33
- Max: 125
33
+ Enabled: false
34
34
 
35
35
  Metrics/BlockLength:
36
- Max: 45
37
- Exclude:
38
- - 'spec/**/*'
36
+ Enabled: false
39
37
 
40
38
  # Mixing the styles looks just silly.
41
39
  Style/HashSyntax:
42
40
  EnforcedStyle: ruby19_no_mixed_keys
43
- Exclude:
44
- - 'config/routes.rb'
45
41
 
46
42
  # Single quotes being faster is hardly measurable and only affects parse time.
47
43
  # Enforcing double quotes reduces the times where you need to change them
@@ -103,8 +99,11 @@ Style/ClassAndModuleChildren:
103
99
  Style/DoubleNegation:
104
100
  Enabled: false
105
101
 
102
+ Style/AsciiComments:
103
+ Enabled: false
104
+
106
105
  # Most readable form.
107
- Layout/AlignHash:
106
+ Layout/HashAlignment:
108
107
  EnforcedHashRocketStyle: table
109
108
  EnforcedColonStyle: table
110
109
 
@@ -125,14 +124,14 @@ Layout/MultilineMethodCallIndentation:
125
124
  # Suppressing exceptions can be perfectly fine, and be it to avoid to
126
125
  # explicitly type nil into the rescue since that's what you want to return,
127
126
  # or suppressing LoadError for optional dependencies
128
- Lint/HandleExceptions:
127
+ Lint/SuppressedException:
129
128
  Enabled: false
130
129
 
131
130
  # This is just silly. Calling the argument `other` in all cases makes no sense.
132
131
  Naming/BinaryOperatorParameterName:
133
132
  Enabled: false
134
133
 
135
- Naming/UncommunicativeMethodParamName:
134
+ Naming/MethodParameterName:
136
135
  AllowedNames:
137
136
  - io
138
137
  - id
@@ -148,3 +147,6 @@ Naming/UncommunicativeMethodParamName:
148
147
 
149
148
  Bundler/OrderedGems:
150
149
  Enabled: false
150
+
151
+ Gemspec/OrderedDependencies:
152
+ Enabled: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- heavylog (0.0.16)
4
+ heavylog (0.0.21)
5
5
  actionpack (>= 5)
6
6
  activesupport (>= 5)
7
7
  railties (>= 5)
@@ -10,90 +10,137 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- actionpack (6.0.0)
14
- actionview (= 6.0.0)
15
- activesupport (= 6.0.0)
16
- rack (~> 2.0)
13
+ actionpack (6.1.3.2)
14
+ actionview (= 6.1.3.2)
15
+ activesupport (= 6.1.3.2)
16
+ rack (~> 2.0, >= 2.0.9)
17
17
  rack-test (>= 0.6.3)
18
18
  rails-dom-testing (~> 2.0)
19
19
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
20
- actionview (6.0.0)
21
- activesupport (= 6.0.0)
20
+ actionview (6.1.3.2)
21
+ activesupport (= 6.1.3.2)
22
22
  builder (~> 3.1)
23
23
  erubi (~> 1.4)
24
24
  rails-dom-testing (~> 2.0)
25
25
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
26
- activesupport (6.0.0)
26
+ activesupport (6.1.3.2)
27
27
  concurrent-ruby (~> 1.0, >= 1.0.2)
28
- i18n (>= 0.7, < 2)
29
- minitest (~> 5.1)
30
- tzinfo (~> 1.1)
31
- zeitwerk (~> 2.1, >= 2.1.8)
32
- ast (2.4.0)
33
- builder (3.2.3)
34
- concurrent-ruby (1.1.5)
35
- crass (1.0.4)
36
- diff-lcs (1.3)
37
- erubi (1.9.0)
38
- i18n (1.7.0)
28
+ i18n (>= 1.6, < 2)
29
+ minitest (>= 5.1)
30
+ tzinfo (~> 2.0)
31
+ zeitwerk (~> 2.3)
32
+ ast (2.4.2)
33
+ backport (1.1.2)
34
+ benchmark (0.1.1)
35
+ builder (3.2.4)
36
+ concurrent-ruby (1.1.8)
37
+ connection_pool (2.2.5)
38
+ crass (1.0.6)
39
+ diff-lcs (1.4.4)
40
+ docile (1.3.5)
41
+ e2mmap (0.1.0)
42
+ erubi (1.10.0)
43
+ i18n (1.8.10)
39
44
  concurrent-ruby (~> 1.0)
40
- jaro_winkler (1.5.2)
41
- loofah (2.3.0)
45
+ jaro_winkler (1.5.4)
46
+ json (2.5.1)
47
+ kramdown (2.3.1)
48
+ rexml
49
+ kramdown-parser-gfm (1.1.0)
50
+ kramdown (~> 2.0)
51
+ loofah (2.9.1)
42
52
  crass (~> 1.0.2)
43
53
  nokogiri (>= 1.5.9)
44
- method_source (0.9.2)
45
- mini_portile2 (2.4.0)
46
- minitest (5.12.2)
47
- nokogiri (1.10.4)
48
- mini_portile2 (~> 2.4.0)
49
- parallel (1.17.0)
50
- parser (2.6.3.0)
51
- ast (~> 2.4.0)
52
- rack (2.0.7)
54
+ method_source (1.0.0)
55
+ mini_portile2 (2.5.1)
56
+ minitest (5.14.4)
57
+ nokogiri (1.11.3)
58
+ mini_portile2 (~> 2.5.0)
59
+ racc (~> 1.4)
60
+ parallel (1.20.1)
61
+ parser (3.0.1.0)
62
+ ast (~> 2.4.1)
63
+ racc (1.5.2)
64
+ rack (2.2.3)
53
65
  rack-test (1.1.0)
54
66
  rack (>= 1.0, < 3)
55
67
  rails-dom-testing (2.0.3)
56
68
  activesupport (>= 4.2.0)
57
69
  nokogiri (>= 1.6)
58
- rails-html-sanitizer (1.2.0)
59
- loofah (~> 2.2, >= 2.2.2)
60
- railties (6.0.0)
61
- actionpack (= 6.0.0)
62
- activesupport (= 6.0.0)
70
+ rails-html-sanitizer (1.3.0)
71
+ loofah (~> 2.3)
72
+ railties (6.1.3.2)
73
+ actionpack (= 6.1.3.2)
74
+ activesupport (= 6.1.3.2)
63
75
  method_source
64
76
  rake (>= 0.8.7)
65
- thor (>= 0.20.3, < 2.0)
77
+ thor (~> 1.0)
66
78
  rainbow (3.0.0)
67
- rake (10.5.0)
68
- request_store (1.4.1)
79
+ rake (13.0.3)
80
+ redis (4.2.5)
81
+ regexp_parser (2.1.1)
82
+ request_store (1.5.0)
69
83
  rack (>= 1.4)
70
- rspec (3.7.0)
71
- rspec-core (~> 3.7.0)
72
- rspec-expectations (~> 3.7.0)
73
- rspec-mocks (~> 3.7.0)
74
- rspec-core (3.7.1)
75
- rspec-support (~> 3.7.0)
76
- rspec-expectations (3.7.0)
84
+ reverse_markdown (2.0.0)
85
+ nokogiri
86
+ rexml (3.2.5)
87
+ rspec (3.10.0)
88
+ rspec-core (~> 3.10.0)
89
+ rspec-expectations (~> 3.10.0)
90
+ rspec-mocks (~> 3.10.0)
91
+ rspec-core (3.10.1)
92
+ rspec-support (~> 3.10.0)
93
+ rspec-expectations (3.10.1)
77
94
  diff-lcs (>= 1.2.0, < 2.0)
78
- rspec-support (~> 3.7.0)
79
- rspec-mocks (3.7.0)
95
+ rspec-support (~> 3.10.0)
96
+ rspec-mocks (3.10.2)
80
97
  diff-lcs (>= 1.2.0, < 2.0)
81
- rspec-support (~> 3.7.0)
82
- rspec-support (3.7.1)
83
- rubocop (0.71.0)
84
- jaro_winkler (~> 1.5.1)
98
+ rspec-support (~> 3.10.0)
99
+ rspec-support (3.10.2)
100
+ rubocop (0.93.1)
85
101
  parallel (~> 1.10)
86
- parser (>= 2.6)
102
+ parser (>= 2.7.1.5)
87
103
  rainbow (>= 2.2.2, < 4.0)
104
+ regexp_parser (>= 1.8)
105
+ rexml
106
+ rubocop-ast (>= 0.6.0)
88
107
  ruby-progressbar (~> 1.7)
89
- unicode-display_width (>= 1.4.0, < 1.7)
90
- ruby-progressbar (1.10.1)
91
- thor (0.20.3)
92
- thread_safe (0.3.6)
93
- tzinfo (1.2.5)
94
- thread_safe (~> 0.1)
95
- unicode-display_width (1.6.0)
96
- zeitwerk (2.1.10)
108
+ unicode-display_width (>= 1.4.0, < 2.0)
109
+ rubocop-ast (1.4.1)
110
+ parser (>= 2.7.1.5)
111
+ rubocop-performance (1.5.2)
112
+ rubocop (>= 0.71.0)
113
+ ruby-progressbar (1.11.0)
114
+ sidekiq (6.2.1)
115
+ connection_pool (>= 2.2.2)
116
+ rack (~> 2.0)
117
+ redis (>= 4.2.0)
118
+ simplecov (0.17.1)
119
+ docile (~> 1.1)
120
+ json (>= 1.8, < 3)
121
+ simplecov-html (~> 0.10.0)
122
+ simplecov-html (0.10.2)
123
+ solargraph (0.40.4)
124
+ backport (~> 1.1)
125
+ benchmark
126
+ bundler (>= 1.17.2)
127
+ e2mmap
128
+ jaro_winkler (~> 1.5)
129
+ kramdown (~> 2.3)
130
+ kramdown-parser-gfm (~> 1.1)
131
+ parser (~> 3.0)
132
+ reverse_markdown (>= 1.0.5, < 3)
133
+ rubocop (>= 0.52)
134
+ thor (~> 1.0)
135
+ tilt (~> 2.0)
136
+ yard (~> 0.9, >= 0.9.24)
137
+ thor (1.1.0)
138
+ tilt (2.0.10)
139
+ tzinfo (2.0.4)
140
+ concurrent-ruby (~> 1.0)
141
+ unicode-display_width (1.7.0)
142
+ yard (0.9.26)
143
+ zeitwerk (2.4.2)
97
144
 
98
145
  PLATFORMS
99
146
  ruby
@@ -101,9 +148,13 @@ PLATFORMS
101
148
  DEPENDENCIES
102
149
  bundler (~> 2.0)
103
150
  heavylog!
104
- rake (~> 10.0)
151
+ rake (~> 13.0)
105
152
  rspec (~> 3.0)
106
153
  rubocop (~> 0.71)
154
+ rubocop-performance (~> 1.5.2)
155
+ sidekiq (>= 5.0)
156
+ simplecov (~> 0.17.1)
157
+ solargraph
107
158
 
108
159
  BUNDLED WITH
109
- 2.0.2
160
+ 2.2.15
data/README.md CHANGED
@@ -1,39 +1,102 @@
1
- # Heavylog [![Build Status](https://travis-ci.org/krisrang/heavylog.svg?branch=master)](https://travis-ci.org/krisrang/heavylog)
1
+ # Heavylog [![Test](https://github.com/krisrang/heavylog/actions/workflows/test.yml/badge.svg)](https://github.com/krisrang/heavylog/actions/workflows/test.yml) [![Gem Version](https://badge.fury.io/rb/heavylog.svg)](https://badge.fury.io/rb/heavylog)
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/heavylog`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Heavylog enables you to log all Rails requests to file as JSON or any other format you want.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ Aside from metadata about requests full output is also included like SQL/Rails logging and `puts` statements.
6
+ Example request using the JSON formatter:
7
+ ```
8
+ {"request_id":"e2cdef0a-9851-4aab-b58f-60e607b4d1a9","request_start":"2021-04-25T15:37:20+00:00","ip":"52.52.52.52","messages":"Started GET \"/admin/info/sidekiq\" for 52.52.52.52 at 2021-04-25 15:37:20 +0000\nProcessing by Admin::InfoController#sidekiq_stats as */*\nRequested via apphost.com as */*\n Snippet Load (1.8ms) SELECT \"snippets\".* FROM \"snippets\" WHERE (locale = 'sv-SE' AND tag = 'information_notice_contact') ORDER BY \"snippets\".\"id\" ASC LIMIT $1 [[\"LIMIT\", 1]]\n Snippet Load (1.5ms) SELECT \"snippets\".* FROM \"snippets\" WHERE (locale = 'sv-SE' AND tag = 'contact_us_frame') ORDER BY \"snippets\".\"id\" ASC LIMIT $1 [[\"LIMIT\", 1]]\n Rendering text template\n Rendered text template (Duration: 0.1ms | Allocations: 16)\nCompleted 200 OK in 41ms (Views: 0.6ms | ActiveRecord: 3.3ms | Allocations: 10734)\n","method":"GET","path":"/admin/info/sidekiq","format":"*/*","controller":"Admin::InfoController","action":"sidekiq_stats","status":200,"duration":40.74,"view_runtime":0.56,"db_runtime":3.28,"user_id":null,"admin_id":null,"request_host":"apphost.com","ua":"curl/7.58.0","operation":null}
9
+ ```
6
10
 
11
+ Example use case is collecting the JSON files and shipping them to an Elastic/Kibana cluster for centralized logging.
7
12
  ## Installation
8
13
 
9
14
  Add this line to your application's Gemfile:
10
15
 
11
16
  ```ruby
12
- gem 'heavylog'
17
+ gem "heavylog"
13
18
  ```
14
19
 
15
20
  And then execute:
16
21
 
17
- $ bundle
22
+ ```bash
23
+ $ bundle
24
+ ```
18
25
 
19
- Or install it yourself as:
26
+ ## Usage
20
27
 
21
- $ gem install heavylog
28
+ Enable and configure in a Rails initializer `config/initializers/logger.rb`:
22
29
 
23
- ## Usage
30
+ ```rb
31
+ Rails.application.configure do
32
+ config.heavylog.enabled = true
33
+ config.heavylog.path = Rails.root.join("log/heavylog.log")
34
+ # Default formatter is Heavylog::Formatters::Raw which simply outputs the ruby hash as a string
35
+ config.heavylog.formatter = Heavylog::Formatters::Json.new
36
+ config.heavylog.log_sidekiq = true # Default is `false`, set to `true` to automatically log sidekiq job runs too.
37
+ end
38
+ ```
24
39
 
25
- TODO: Write usage instructions here
40
+ ## Configuration
41
+
42
+ | Option | Type | Description |
43
+ | :-------- | :------- | :------------------------- |
44
+ | `enabled` | `boolean` | Set to `true` to enable logging. Default: `false`. |
45
+ | `path` | `string` | Path to output file. Default: `log/heavylog.log`. |
46
+ | `message_limit` | `integer` | Request output will be truncated if longer than this limit. Default: `52428800` (50MB). |
47
+ | `log_sidekiq` | `boolean` | Set to `true` to automatically log sidekiq jobs too. Default: `false`. |
48
+ | `error_handler` | `lambda/proc` | Code to execute when formatter throws exception. Default: `->(e) { p "HeavyLog: Error writing to log: #{e.class}: #{e.message}\n #{e.backtrace.join("\n ")}" }`
49
+ | `custom_payload` | `block` | Block executed for every request that should return hash with extra fields you want to log. Default: `nil`. |
50
+
51
+ ### Custom payload
52
+
53
+ `custom_payload` accepts a block with a single argument, `controller` you can use to access any methods you normally would in a controller action.
54
+ It should return a hash with the extra fields you want to log.
55
+
56
+ ```rb
57
+ Rails.application.configure do
58
+ config.heavylog.custom_payload do |controller|
59
+ user_id = controller.respond_to?(:current_user) ? controller.current_user&.id : nil
60
+
61
+ {
62
+ user_id: user_id,
63
+ request_host: controller.request.host,
64
+ ua: controller.request.user_agent,
65
+ operation: controller.request.params[:operationName],
66
+ }
67
+ end
68
+ end
69
+ ```
26
70
 
27
- ## Development
71
+ ### Sidekiq logging
28
72
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
73
+ Set `log_sidekiq` to `true` if you want to automatically log Sidekiq job runs to the same file. Example with JSON formatter:
74
+ ```
75
+ {"request_id":"fb2c3798e2634011d670f753","request_start":"2021-04-25T16:00:53+00:00","ip":"127.0.0.1","messages":" Order Load (1.8ms) SELECT \"orders\".* FROM \"orders\" WHERE \"orders\".\"id\" = $1 LIMIT $2 [[\"id\", 109987473], [\"LIMIT\", 1]]\n Customer Load (1.7ms) SELECT \"customers\".* FROM \"customers\" WHERE \"customers\".\"id\" = $1 LIMIT $2 [[\"id\", 1027337], [\"LIMIT\", 1]]\n","controller":"SidekiqLogger","action":"MailPrepaidCheckupsJob","args":"[109987473]"}
76
+ ```
77
+
78
+ Sidekiq job runs go into the same file as regular request logs but have controller set to `SidekiqLogger` and action to the name of the Job.
30
79
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
80
+ ### JSON formatter
32
81
 
33
- ## Contributing
82
+ Every request results in a hash containing all info about the request. The default `Heavylog::Formatters::Raw` formatter simply outputs the hash as a string to the output file.
83
+ Use the `Heavylog::Formatters::Json` formatter to convert the hash to JSON. The resulting file will contain one JSON object per line for every request.
34
84
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/krisrang/heavylog.
85
+ ### Custom formatter
36
86
 
87
+ The formatter interface is simply a class with a `call` method that accepts a single argument which is the hash containing info about the request.
88
+ The method should return the final result you want to write to file. Heavylog writes one line per request.
89
+
90
+ JSON formatter for example:
91
+ ```rb
92
+ class Json
93
+ def call(data)
94
+ ::JSON.dump(data)
95
+ end
96
+ end
97
+ ```
37
98
  ## License
38
99
 
39
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
100
+ [MIT](https://choosealicense.com/licenses/mit/)
101
+
102
+
data/heavylog.gemspec CHANGED
@@ -16,16 +16,20 @@ Gem::Specification.new do |spec|
16
16
  spec.license = "MIT"
17
17
 
18
18
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
- f.match(%r{^(test|spec|features)/})
19
+ f.match(%r{^(test|spec|features|.vscode)/})
20
20
  end
21
21
  spec.bindir = "exe"
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ["lib"]
24
24
 
25
25
  spec.add_development_dependency "bundler", "~> 2.0"
26
- spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rake", "~> 13.0"
27
27
  spec.add_development_dependency "rspec", "~> 3.0"
28
28
  spec.add_development_dependency "rubocop", "~> 0.71"
29
+ spec.add_development_dependency "rubocop-performance", "~> 1.5.2"
30
+ spec.add_development_dependency "simplecov", "~> 0.17.1"
31
+ spec.add_development_dependency "sidekiq", ">= 5.0"
32
+ spec.add_development_dependency "solargraph"
29
33
 
30
34
  spec.add_runtime_dependency "actionpack", ">= 5"
31
35
  spec.add_runtime_dependency "activesupport", ">= 5"
data/lib/heavylog.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require "heavylog/version"
4
4
  require "heavylog/formatters/raw"
5
5
  require "heavylog/formatters/json"
6
+ require "heavylog/formatters/ecs"
6
7
  require "heavylog/log_subscriber"
7
8
  require "heavylog/middleware"
8
9
  require "heavylog/ordered_options"
@@ -136,8 +137,10 @@ module Heavylog
136
137
  messages: buffer.string.dup,
137
138
  }.merge(RequestStore.store[:heavylog_request_data] || {})
138
139
 
139
- formatted = Heavylog.formatter.call(request)
140
+ formatted = Heavylog.formatter.call(request.transform_keys(&:to_s))
140
141
  Heavylog.logger.send(Heavylog.log_level, formatted)
142
+ rescue StandardError => e
143
+ config.error_handler&.(e)
141
144
  end
142
145
 
143
146
  def finish_sidekiq
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Heavylog
6
+ module Formatters
7
+ class ECS
8
+ # mapping from heavylog standard keys to ECS https://www.elastic.co/guide/en/ecs/current/ecs-reference.html
9
+ ECS_MAP = {
10
+ "request_start" => "@timestamp",
11
+ "messages" => "message",
12
+ "request_id" => "http.request.id",
13
+ "method" => "http.request.method",
14
+ "referrer" => "http.request.referrer",
15
+ "format" => "http.response.format",
16
+ "status" => "http.response.status_code",
17
+ "location" => "http.response.location",
18
+ "ip" => "source.address",
19
+ "path" => "url.original",
20
+ "controller" => "heavylog.controller",
21
+ "action" => "heavylog.action",
22
+ "unpermitted_params" => "heavylog.unpermitted_params",
23
+ "args" => "heavylog.args",
24
+ "duration" => "heavylog.duration",
25
+ "view_runtime" => "heavylog.view_runtime",
26
+ "db_runtime" => "heavylog.db_runtime",
27
+ }.freeze
28
+
29
+ def call(data)
30
+ ECS_MAP.each do |original, correct|
31
+ dig_set(data, correct.split("."), data.delete(original)) if data[original]
32
+ end
33
+
34
+ dig_set(data, %w[event module], "heavylog")
35
+ dig_set(data, %w[event category], "web")
36
+
37
+ unless data.dig("event", "dataset")
38
+ value = data.dig("heavylog", "controller") == "SidekiqLogger" ? "heavylog.sidekiq" : "heavylog.rails"
39
+ dig_set(data, %w[event dataset], value)
40
+ end
41
+
42
+ if (code = data.dig("http", "response", "status_code"))
43
+ dig_set(data, %w[event outcome], (200..399).cover?(code) ? "success" : "failure")
44
+ end
45
+
46
+ dig_set(data, %w[source ip], data.dig("source", "address")) unless data.dig("source", "ip")
47
+ dig_set(data, %w[url path], data.dig("url", "original")) unless data.dig("url", "path")
48
+
49
+ ::JSON.dump(data)
50
+ end
51
+
52
+ private
53
+
54
+ def dig_set(obj, keys, value)
55
+ key = keys.first
56
+ if keys.length == 1
57
+ obj[key] = value
58
+ else
59
+ obj[key] = {} unless obj[key]
60
+ dig_set(obj[key], keys.slice(1..-1), value)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -31,6 +31,7 @@ module Heavylog
31
31
  data.merge!(extract_runtimes(event, payload))
32
32
  data.merge!(extract_location)
33
33
  data.merge!(extract_unpermitted_params)
34
+ data.merge!(extract_referrer(payload))
34
35
  data.merge!(custom_options(event))
35
36
  end
36
37
 
@@ -101,5 +102,13 @@ module Heavylog
101
102
  RequestStore.store[:heavylog_unpermitted_params] = nil
102
103
  { unpermitted_params: unpermitted_params }
103
104
  end
105
+
106
+ def extract_referrer(payload)
107
+ if payload[:request].is_a?(ActionDispatch::Request) && payload[:request].referrer
108
+ return { referrer: payload[:request].referrer }
109
+ end
110
+
111
+ {}
112
+ end
104
113
  end
105
114
  end
@@ -7,6 +7,9 @@ module Heavylog
7
7
  config.heavylog.path = "log/heavylog.log"
8
8
  config.heavylog.message_limit = 1024 * 1024 * 50 # 50MB
9
9
  config.heavylog.log_sidekiq = false
10
+ config.heavylog.error_handler = lambda { |e|
11
+ Kernel.puts "HeavyLog: Error writing to log: #{e.class}: #{e.message}\n #{e.backtrace.join("\n ")}"
12
+ }
10
13
 
11
14
  initializer "heavylog.insert_middleware" do |app|
12
15
  app.config.middleware.insert_before Rails::Rack::Logger, Heavylog::Middleware
@@ -1,17 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "sidekiq/job_logger"
3
+ begin
4
+ require "sidekiq/job_logger"
4
5
 
5
- module Heavylog
6
- class SidekiqLogger < Sidekiq::JobLogger
7
- def call(item, _queue)
8
- # item = {"class"=>"SuspiciousJob", "args"=>[12754545, [3858890], "invoice"], "retry"=>true, "queue"=>"default",
9
- # "jid"=>"5ec968571e358497d70a3cf2", "created_at"=>1540484817.3950138, "enqueued_at"=>1540484817.395076}
6
+ module Heavylog
7
+ class SidekiqLogger < Sidekiq::JobLogger
8
+ def call(item, _queue)
9
+ # item = {"class"=>"SuspiciousJob", "args"=>[12754545, [3858890], "invoice"], "retry"=>true, "queue"=>"default",
10
+ # "jid"=>"5ec968571e358497d70a3cf2", "created_at"=>1540484817.3950138, "enqueued_at"=>1540484817.395076}
10
11
 
11
- Heavylog.log_sidekiq(item["jid"], item["class"], item["args"])
12
- super
13
- ensure
14
- Heavylog.finish_sidekiq
12
+ Heavylog.log_sidekiq(item["jid"], item["class"], item["args"])
13
+ super
14
+ ensure
15
+ Heavylog.finish_sidekiq
16
+ end
15
17
  end
16
18
  end
19
+ rescue LoadError
17
20
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Heavylog
4
- VERSION = "0.0.16"
4
+ VERSION = "0.0.21"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heavylog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.16
4
+ version: 0.0.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kristjan Rang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-04 00:00:00.000000000 Z
11
+ date: 2021-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,62 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.71'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-performance
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.5.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.5.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.17.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.17.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: sidekiq
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '5.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '5.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: solargraph
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
69
125
  - !ruby/object:Gem::Dependency
70
126
  name: actionpack
71
127
  requirement: !ruby/object:Gem::Requirement
@@ -129,10 +185,11 @@ executables: []
129
185
  extensions: []
130
186
  extra_rdoc_files: []
131
187
  files:
188
+ - ".editorconfig"
189
+ - ".github/workflows/test.yml"
132
190
  - ".gitignore"
133
191
  - ".rspec"
134
192
  - ".rubocop.yml"
135
- - ".travis.yml"
136
193
  - Gemfile
137
194
  - Gemfile.lock
138
195
  - LICENSE.txt
@@ -142,6 +199,7 @@ files:
142
199
  - bin/setup
143
200
  - heavylog.gemspec
144
201
  - lib/heavylog.rb
202
+ - lib/heavylog/formatters/ecs.rb
145
203
  - lib/heavylog/formatters/json.rb
146
204
  - lib/heavylog/formatters/raw.rb
147
205
  - lib/heavylog/log_subscriber.rb
@@ -171,7 +229,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
229
  - !ruby/object:Gem::Version
172
230
  version: '0'
173
231
  requirements: []
174
- rubygems_version: 3.0.3
232
+ rubygems_version: 3.2.15
175
233
  signing_key:
176
234
  specification_version: 4
177
235
  summary: Format all Rails logging per request
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.5.0
5
- before_install: gem install bundler -v 2.0.1
6
- script: bundle exec rspec