heavylog 0.0.16 → 0.0.21

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