json_tagged_logger 0.2.0 → 0.2.1

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: 3ddcb4231cfc04738123f81259ad35a28fe118f920dd5ab256f24b8edd76d4ac
4
- data.tar.gz: b44b6ee19cd6e763e9065aaa919145217025dcdc72408b38d577d4630017eb7e
3
+ metadata.gz: 5d6a91dae71312da17de8ad46580f46a3a5d7c6c20d8e1444107734cb7775c49
4
+ data.tar.gz: 159b9a61bf557b8324c2d1c1f3dd03e4fc2f37625996046e7de29fd2b2f05a0f
5
5
  SHA512:
6
- metadata.gz: 8183f8c49929f51528b940e8111a68cc66762cd85d058f40fc0b5af21797e92439967442232dee6db8ce0937571b749a09cfc891f0cbc2f74f407648b6d4097d
7
- data.tar.gz: d81145bcdee2da86974f5c234aed2e033b63da4a2a80d1492ffa1f749a8cbd44b2e0d9c35e1b3b66f628adbfadbc68302072545cf341cd79cf23c30652d24285
6
+ metadata.gz: 43d1c8b1d1905f04271bdb538618e4b24d6b1eefc1d2864d01c38949ae5b1f6dcfccc0af60254136667cef7dd345becf52cf65169030818f911d4d56c7abdf4f
7
+ data.tar.gz: 06fd82f28251e33f49a31273d415f76d4d9a5b1fc085b05a707722b3be9046f96148731f64324c9a44f6cbc86c2a3769d44652c893713f7fd4553173e35df1d9
data/README.md CHANGED
@@ -1,89 +1,139 @@
1
1
  # JsonTaggedLogger
2
2
 
3
- JsonTaggedLogger provides a log formatter that works in conjunction with ActiveSupport::TaggedLogging to product JSON-formatted log output.
3
+ `JsonTaggedLogger` works in conjunction with [`ActiveSupport::TaggedLogging`](https://api.rubyonrails.org/classes/ActiveSupport/TaggedLogging.html) and (optionally) [Lograge](https://github.com/roidrage/lograge) to produce JSON-formatted log output. By itself, `ActiveSupport::TaggedLogging` supports simple tagging. With `JsonTaggedLogger`, you can compose key/value pairs, simple tags, and the log message itself into a single JSON document for easy consumption and parsing in log aggregators.
4
4
 
5
+ ## Usage
6
+
7
+ Given the following configuration,
5
8
 
6
9
  ```ruby
7
10
  # Gemfile
8
11
  gem 'json_tagged_logger'
12
+ gem 'lograge' # since you probably want all your request logs in JSON
9
13
 
10
14
  # config/environments/production.rb
11
15
  Rails.application.configure do
12
- # …
13
- config.log_tags = JsonTaggedLogger::LogTagsConfig.generate(:request_id, :host, ->(request) { { example: "proc" }.to_json })
14
- logger = ActiveSupport::Logger.new(STDOUT)
15
- config.logger = JsonTaggedLogger::Logger.new(logger)
16
- #
16
+ # …
17
+ config.log_tags = JsonTaggedLogger::LogTagsConfig.generate(
18
+ :request_id,
19
+ :host,
20
+ ->(request) { { my_param: request.query_parameters["my_param"] }.to_json },
21
+ JsonTaggedLogger::TagFromSession.get(:user_id),
22
+ JsonTaggedLogger::TagFromHeaders.get(:my_custom_header, "X-Custom-Header"),
23
+ )
24
+
25
+ logger = ActiveSupport::Logger.new(STDOUT)
26
+ config.logger = JsonTaggedLogger::Logger.new(logger)
27
+
28
+ config.lograge.enabled = true
29
+ config.lograge.formatter = Lograge::Formatters::Json.new
30
+ # …
17
31
  end
18
-
19
32
  ```
20
33
 
21
-
22
- ## Why?
23
-
24
- On its own, ActiveSupport::TaggedLogging adds individual tags wrapped in squre brackets at the start of each line of log output, like so
34
+ A request like
25
35
 
26
36
  ```
27
- [tag1] [tag2] : Foo bar
37
+ curl -H "X-Custom-Header: some header value" 'http://127.0.0.1:3000/?my_param=param%20value'
28
38
  ```
29
39
 
30
- This is fine as far as it goes, but if you wish to use tagged logging with something like [Lograge](https://github.com/roidrage/lograge) to format your logs as JSON, there's no good way to get the tags into that json output, specially if any of your tags are generated by procs.
31
-
32
- ## How does it work?
40
+ will get you something like
33
41
 
34
- First, JsonTaggedLogger::LogTags helps you generate an array lof log tags suitable for passing to Rails.application.config.log_tags to produce JSON logs. For example, given
35
-
36
- ```
37
- Rails.application.config.log_tags = JsonTaggedLogger::LogTags.generate_config(:request_id, :host)
42
+ ```json
43
+ {
44
+ "level": "INFO",
45
+ "request_id": "914f6104-538d-4ddc-beef-37bfe06ca1c7",
46
+ "host": "127.0.0.1",
47
+ "my_param": "param value",
48
+ "user_id": "99",
49
+ "my_custom_header": "some header value",
50
+ "method": "GET",
51
+ "path": "/",
52
+ "format": "*/*",
53
+ "controller": "SessionsController",
54
+ "action": "new",
55
+ "status": 302,
56
+ "duration": 0.51,
57
+ "view": 0,
58
+ "db": 0,
59
+ "location": "http://127.0.0.1:3000/profile"
60
+ }
38
61
  ```
39
62
 
40
- ActiveSupport::TaggedLogging will see the following log tags
63
+ [Note: I've pretty-printed the output in these examples for easier reading. The actual log output will be on a single line without extra whitespace.]
41
64
 
42
- ```
43
- [
44
- -> (request) { { request_id: request.send(:request_id) }.to_json },
45
- -> (request) { { host: request.send(:host) }.to_json }
46
- ]
65
+ Importantly, if the controller action (or any code it calls along the way) has an explicit call to `Rails.logger.tagged("TAG").info("tagged log message")`, you'll get the same key/value tags (`request_id`, `host`, `my_param`, &c.) in the JSON document along with a `tags` key:
66
+
67
+ ```json
68
+ {
69
+ "level": "INFO",
70
+ "request_id": "914f6104-538d-4ddc-beef-37bfe06ca1c7",
71
+ "host": "127.0.0.1",
72
+ "my_param": "param value",
73
+ "user_id": "99",
74
+ "my_custom_header": "some header value",
75
+ "tags": [
76
+ "TAG"
77
+ ],
78
+ "msg": "tagged log message"
79
+ }
47
80
  ```
48
81
 
49
- Why is this an improvement over `Rails.application.config.log_tags = [:request_id, :host]`? Well, with the JsonTaggedLogger version, your logs will now contain
82
+ If you have nested calls to the tagged logger, like
83
+
84
+ ```ruby
85
+ Rails.logger.tagged("TAG") do
86
+ Rails.logger.tagged("NESTED").info("nested tagged log message")
87
+ end
50
88
 
51
- ```
52
- [{"request_id":"c31c3658-5b76-40cd-b583-d0fcbdee0710"}] [{"host":"127.0.0.1"}] log message
53
89
  ```
54
90
 
55
- which `JsonTaggedLogger::Formatter` will turn into
91
+ those will be added to the `tags` key in the JSON document
56
92
 
57
93
  ```json
58
- {"request_id":"c31c3658-5b76-40cd-b583-d0fcbdee0710","host":"127.0.0.1","msg":"log message"}
94
+ {
95
+ "level": "INFO",
96
+ "request_id": "914f6104-538d-4ddc-beef-37bfe06ca1c7",
97
+ "host": "127.0.0.1",
98
+ "my_param": "param value",
99
+ "user_id": "99",
100
+ "my_custom_header": "some header value",
101
+ "tags": [
102
+ "TAG",
103
+ "NESTED"
104
+ ],
105
+ "msg": "nested tagged log message"
106
+ }
59
107
  ```
60
108
 
61
- Lovely, eh?
109
+ ## Why?
62
110
 
63
- The real advantage comes when you have more complicated procs that generage your log tags. So long as your proc produces a JSON string, `JsonTaggedLogger::Formatter` will be able to extract it from the tag and add it to the log hash.
111
+ On its own, `ActiveSupport::TaggedLogging` adds individual tags wrapped in squre brackets at the start of each line of log output. A configuration like
64
112
 
65
113
  ```ruby
66
- class UserInfoLogTag
67
- def self.user_info
68
- lambda do |request|
69
- user_info = build_user_info_from_session(request) # build user info from request by inspecting session, etc
70
- { user_info: user_info }.to_json
71
- end
72
- end
73
-
74
- private
75
-
76
- def self.build_user_info_from_session(request)
77
- # left as an exercise for the reader
78
- end
114
+ Rails.application.configure do
115
+ #
116
+ config.log_tags = [ :request_id, :host, ->(request) { request.query_parameters["my_param"] } ]
117
+ logger = ActiveSupport::Logger.new(STDOUT)
118
+ config.logger = ActiveSupport::TaggedLogging.new(logger)
119
+ # …
79
120
  end
80
-
81
- Rails.application.config.log_tags = [ :request_id, :host, UserInfoLogTag.user_info ]
82
121
  ```
83
122
 
84
- That will get you
123
+ will get you logs like
85
124
 
86
125
  ```
87
- {"request_id":"c31c3658-5b76-40cd-b583-d0fcbdee0710","host":"127.0.0.1","user_info":{"user_id":"1234","user_email":"user@example.com"},"msg":"log message"}
126
+ [22a03298-5fd9-4b28-bbe2-1d4c0d7f74f0] [127.0.0.1] [param value] Started GET "/?my_param=param%20value" for 127.0.0.1 at 2023-01-15 00:13:21 -0500
127
+ [22a03298-5fd9-4b28-bbe2-1d4c0d7f74f0] [127.0.0.1] [param value] Processing by SessionsController#new as */*
128
+ [22a03298-5fd9-4b28-bbe2-1d4c0d7f74f0] [127.0.0.1] [param value] Parameters: {"my_param"=>"param value"}
129
+ [22a03298-5fd9-4b28-bbe2-1d4c0d7f74f0] [127.0.0.1] [param value] [TAG] [NESTED] nested tagged log message
130
+ [22a03298-5fd9-4b28-bbe2-1d4c0d7f74f0] [127.0.0.1] [param value] Redirected to http://127.0.0.1:3000/sign_in
131
+ [22a03298-5fd9-4b28-bbe2-1d4c0d7f74f0] [127.0.0.1] [param value] Completed 302 Found in 1ms (ActiveRecord: 0.0ms | Allocations: 1070)
88
132
  ```
89
133
 
134
+ This is fine as far as it goes, but if you use tagged logging with something like [Lograge](https://github.com/roidrage/lograge) to format your request logs as JSON, the list of square-bracketed tags will still just be prepended to the log line, followed by the JSON. Also, any calls to `Rails.logger.tagged` will be logged as plain text:
135
+
136
+ ```
137
+ [d4fac896-f916-48d7-9d32-d35a39cfb7d8] [127.0.0.1] [param value] [TAG] [NESTED] nested tagged log message
138
+ [d4fac896-f916-48d7-9d32-d35a39cfb7d8] [127.0.0.1] [param value] {"method":"GET","path":"/","format":"*/*","controller":"SessionsController","action":"new","status":302,"duration":1.2,"view":0.0,"db":0.0,"location":"http://127.0.0.1:3000/sign_in"}
139
+ ```
@@ -1,3 +1,3 @@
1
1
  module JsonTaggedLogger
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json_tagged_logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Santry