twiglet 3.4.8 → 3.5.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: aa66002d342a4010bd45cfac5f9d379feedf444bb0b7da9183abd32c48eefb73
4
- data.tar.gz: 8c09fc2eae272156fb47e8bece9ec1ddc8aa20e30ea582554a45b7471fca6e43
3
+ metadata.gz: 00772aa96a6be0df63c418fc7cc077cf599e9909af51e00be9992bf78d298660
4
+ data.tar.gz: 479f94b2de093c797e863b66f02287e37d1b1c5aa58931553bdff269844ed792
5
5
  SHA512:
6
- metadata.gz: ac5edd60f8444dce77ec6f5e0ee2c2d0cd7bc317944788ce4f8731564eadb89650f4fc25834bc6aedcdacd91f0f10ca9108b9bb0cfef70b2769a79ca6a344096
7
- data.tar.gz: 59dc3907ede5435f2f1daa09f862c3d3ca7cd144cddf6e75f04b35698eb8a8262484c5d0705dd7c4ec6a99b4d8972a4d765c1bbf30956638043073f15e54e9ca
6
+ metadata.gz: 17317a0d26e6b66b573e5eeeafc7d4957c6bdb87e70f320279098cb405464e68fe29a56cbe4421663d809cf39b6e7f72d5d5b5c0261fecd59766bf420e928250
7
+ data.tar.gz: 222e608e335c4a6406e08376356f1cd7e42c89ea09f7d4eba6432fc33aa26d614421f60ef123d45b2eed73ab334741b50fbf096ee17631f38dbf8930cb4c4397
@@ -18,7 +18,7 @@ jobs:
18
18
 
19
19
  strategy:
20
20
  matrix:
21
- ruby-version: [2.6, 2.7, 3.0]
21
+ ruby-version: [2.7, 3.0, 3.1]
22
22
 
23
23
  steps:
24
24
  - uses: actions/checkout@v3
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.5
1
+ 2.7.6
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Twiglet: Ruby version
2
2
  Like a log, only smaller.
3
3
 
4
- This library provides a minimal JSON logging interface suitable for use in (micro)services. See the [RATIONALE](RATIONALE.md) for design rationale and an explantion of the Elastic Common Schema that we are using for log attribute naming.
4
+ This library provides a minimal JSON logging interface suitable for use in (micro)services. See the [RATIONALE](docs/RATIONALE.md) for design rationale and an explantion of the Elastic Common Schema that we are using for log attribute naming.
5
5
 
6
6
  See [Full docs](docs/index.md)
@@ -7,11 +7,14 @@ module Twiglet
7
7
  Hash.include HashExtensions
8
8
 
9
9
  def initialize(service_name,
10
- validator:, default_properties: {},
10
+ validator:,
11
+ default_properties: {},
12
+ context_provider: nil,
11
13
  now: -> { Time.now.utc })
12
14
  @service_name = service_name
13
15
  @now = now
14
16
  @default_properties = default_properties
17
+ @context_provider = context_provider
15
18
  @validator = validator
16
19
 
17
20
  super()
@@ -40,8 +43,11 @@ module Twiglet
40
43
  }
41
44
  }
42
45
 
46
+ context = @context_provider&.call || {}
47
+
43
48
  base_message
44
49
  .deep_merge(@default_properties.to_nested)
50
+ .deep_merge(context.to_nested)
45
51
  .deep_merge(message.to_nested)
46
52
  .to_json
47
53
  .concat("\n")
@@ -16,7 +16,6 @@ module Twiglet
16
16
  **args
17
17
  )
18
18
  @service_name = service_name
19
- default_properties = args.delete(:default_properties) || {}
20
19
  @args = args
21
20
 
22
21
  now = args.fetch(:now, -> { Time.now.utc })
@@ -31,7 +30,8 @@ module Twiglet
31
30
 
32
31
  formatter = Twiglet::Formatter.new(
33
32
  service_name,
34
- default_properties: default_properties,
33
+ default_properties: args.fetch(:default_properties, {}),
34
+ context_provider: args[:context_provider],
35
35
  now: now,
36
36
  validator: @validator
37
37
  )
@@ -58,12 +58,19 @@ module Twiglet
58
58
  end
59
59
 
60
60
  def with(default_properties)
61
- Logger.new(
61
+ self.class.new(
62
62
  @service_name,
63
63
  **@args.merge(default_properties: default_properties)
64
64
  )
65
65
  end
66
66
 
67
+ def context_provider(&blk)
68
+ self.class.new(
69
+ @service_name,
70
+ **@args.merge(context_provider: blk)
71
+ )
72
+ end
73
+
67
74
  alias_method :warning, :warn
68
75
  alias_method :critical, :fatal
69
76
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Twiglet
4
- VERSION = '3.4.8'
4
+ VERSION = '3.5.1'
5
5
  end
@@ -32,4 +32,30 @@ describe Twiglet::Formatter do
32
32
  }
33
33
  assert_equal JSON.parse(msg), expected_log
34
34
  end
35
+
36
+ it 'merges the outputs of the context provider into messages logs' do
37
+ provider = -> { { 'request' => { 'id' => '1234567890' } } }
38
+ formatter = Twiglet::Formatter.new(
39
+ 'petshop', now: @now, validator: Twiglet::Validator.new({}.to_json),
40
+ context_provider: provider
41
+ )
42
+ msg = formatter.call('warn', nil, nil, 'shop is running low on dog food')
43
+ expected_log = {
44
+ "ecs" => {
45
+ "version" => '1.5.0'
46
+ },
47
+ "@timestamp" => '2020-05-11T15:01:01.000Z',
48
+ "service" => {
49
+ "name" => 'petshop'
50
+ },
51
+ "log" => {
52
+ "level" => 'warn'
53
+ },
54
+ "message" => 'shop is running low on dog food',
55
+ "request" => {
56
+ 'id' => '1234567890'
57
+ }
58
+ }
59
+ assert_equal JSON.parse(msg), expected_log
60
+ end
35
61
  end
data/test/logger_test.rb CHANGED
@@ -146,6 +146,115 @@ describe Twiglet::Logger do
146
146
  assert_equal 'Barker', log[:pet][:name]
147
147
  end
148
148
 
149
+ it "isn't possible to chain .with methods to gradually add messages" do
150
+ # Let's add some context to this customer journey
151
+ purchase_logger = @logger.with(
152
+ {
153
+ trace: { id: '1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb' }
154
+ }
155
+ ).with(
156
+ {
157
+ customer: { full_name: 'Freda Bloggs' },
158
+ event: { action: 'pet purchase' }
159
+ }
160
+ )
161
+
162
+ # do stuff
163
+ purchase_logger.info(
164
+ {
165
+ message: 'customer bought a dog',
166
+ pet: { name: 'Barker', species: 'dog', breed: 'Bitsa' }
167
+ }
168
+ )
169
+
170
+ log = read_json @buffer
171
+
172
+ assert_nil log[:trace]
173
+ assert_equal 'Freda Bloggs', log[:customer][:full_name]
174
+ assert_equal 'pet purchase', log[:event][:action]
175
+ assert_equal 'customer bought a dog', log[:message]
176
+ assert_equal 'Barker', log[:pet][:name]
177
+ end
178
+
179
+ it "should be able to add contextual information to events with the context_provider" do
180
+ purchase_logger = @logger.context_provider do
181
+ { 'context' => { 'id' => 'my-context-id' } }
182
+ end
183
+
184
+ # do stuff
185
+ purchase_logger.info(
186
+ {
187
+ message: 'customer bought a dog',
188
+ pet: { name: 'Barker', species: 'dog', breed: 'Bitsa' }
189
+ }
190
+ )
191
+
192
+ log = read_json @buffer
193
+
194
+ assert_equal 'customer bought a dog', log[:message]
195
+ assert_equal 'my-context-id', log[:context][:id]
196
+ end
197
+
198
+ it "chaining .with and .context_provider is possible" do
199
+ # Let's add some context to this customer journey
200
+ purchase_logger = @logger.with(
201
+ {
202
+ trace: { id: '1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb' },
203
+ customer: { full_name: 'Freda Bloggs' },
204
+ event: { action: 'pet purchase' }
205
+ }
206
+ ).context_provider do
207
+ { 'context' => { 'id' => 'my-context-id' } }
208
+ end
209
+
210
+ # do stuff
211
+ purchase_logger.info(
212
+ {
213
+ message: 'customer bought a dog',
214
+ pet: { name: 'Barker', species: 'dog', breed: 'Bitsa' }
215
+ }
216
+ )
217
+
218
+ log = read_json @buffer
219
+
220
+ assert_equal '1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb', log[:trace][:id]
221
+ assert_equal 'Freda Bloggs', log[:customer][:full_name]
222
+ assert_equal 'pet purchase', log[:event][:action]
223
+ assert_equal 'customer bought a dog', log[:message]
224
+ assert_equal 'Barker', log[:pet][:name]
225
+ assert_equal 'my-context-id', log[:context][:id]
226
+ end
227
+
228
+ it "chaining .context_provider and .with is possible" do
229
+ # Let's add some context to this customer journey
230
+ purchase_logger = @logger
231
+ .context_provider do
232
+ { 'context' => { 'id' => 'my-context-id' } }
233
+ end.with(
234
+ {
235
+ trace: { id: '1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb' },
236
+ customer: { full_name: 'Freda Bloggs' },
237
+ event: { action: 'pet purchase' }
238
+ }
239
+ )
240
+ # do stuff
241
+ purchase_logger.info(
242
+ {
243
+ message: 'customer bought a dog',
244
+ pet: { name: 'Barker', species: 'dog', breed: 'Bitsa' }
245
+ }
246
+ )
247
+
248
+ log = read_json @buffer
249
+
250
+ assert_equal '1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb', log[:trace][:id]
251
+ assert_equal 'Freda Bloggs', log[:customer][:full_name]
252
+ assert_equal 'pet purchase', log[:event][:action]
253
+ assert_equal 'customer bought a dog', log[:message]
254
+ assert_equal 'Barker', log[:pet][:name]
255
+ assert_equal 'my-context-id', log[:context][:id]
256
+ end
257
+
149
258
  it "should log 'message' string property" do
150
259
  message = {}
151
260
  message['message'] = 'Guinea pigs arrived'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twiglet
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.8
4
+ version: 3.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simply Business
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-17 00:00:00.000000000 Z
11
+ date: 2022-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json-schema
@@ -145,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
145
  - !ruby/object:Gem::Version
146
146
  version: '0'
147
147
  requirements: []
148
- rubygems_version: 3.0.3
148
+ rubygems_version: 3.1.6
149
149
  signing_key:
150
150
  specification_version: 4
151
151
  summary: Twiglet