twiglet 3.1.3 → 3.2.5

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: 9cace8decdc47857c5ce0bec8ae85b92fe93f866521bc6872371db38999b25c3
4
- data.tar.gz: dc9bf4d673968a4c718af21c117584f7770a3f2d50cc704ff5d39da1bec26626
3
+ metadata.gz: 98f1c6b47cc30e450a1318ea8040d210cb1af5103124fbeee26bb4b5c5ccbb36
4
+ data.tar.gz: 4a1affb0ad177358ac4b66e33326b39e089fdf8bb63cee4e78593db3a2fd4109
5
5
  SHA512:
6
- metadata.gz: 12c4455ae13471d0ebf0899966c9dbd32bf17841c468beaddb0a912a234033921a1694c2007d6a9d1732bdb69dbabc21f88cf98a195b9eea9a9be52d51cc07db
7
- data.tar.gz: 91fab7466ae13a05de15fe66c2b8e4b78b28e2ee31220cd0f427d3928bfd59b15dbec2facc444f5c3a10a29bade3ee568e369fb921360fd6ddbb4c76f80bafd0
6
+ metadata.gz: bf39d61c9cdf97257a040ee3246facd81c3376a656e024817c7abc96153fce7404138b022923aafc4ba84b54c85a74553cdc59ca19dc88af0d5ea5b71e3ef171
7
+ data.tar.gz: 6d17f9991a7535f4083138cf1c65861e4890c0d4ef3a19cf0c14931d5766afb09136a7d56fbb7a782b166270eeb8fbeb74a6671b1301fc10cfe83f7ddb23085e
@@ -9,7 +9,7 @@ jobs:
9
9
 
10
10
  steps:
11
11
  - name: bump version
12
- uses: simplybusiness/dobby@v2.0.0
12
+ uses: simplybusiness/dobby@v2.1.0
13
13
  env:
14
14
  DOBBY_APP_ID: ${{ secrets.DOBBY_APP_ID }}
15
15
  DOBBY_PRIVATE_KEY: ${{ secrets.DOBBY_PRIVATE_KEY }}
@@ -10,7 +10,7 @@ jobs:
10
10
  runs-on: ubuntu-18.04
11
11
 
12
12
  steps:
13
- - uses: simplybusiness/version-forget-me-not@v2
13
+ - uses: simplybusiness/version-forget-me-not@v2.1.0
14
14
  env:
15
15
  ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
16
16
  VERSION_FILE_PATH: "lib/twiglet/version.rb"
data/README.md CHANGED
@@ -144,7 +144,72 @@ logger.formatter
144
144
  Take a look at this sample [Rack application](examples/rack/example_rack_app.rb#L15) with an ECS compliant
145
145
  [request logger](/examples/rack/request_logger.rb) as a template when configuring your own request logging middleware with Twiglet.
146
146
 
147
- ## Use of dotted keys (DEPRECATED)
147
+ ### Log format validation
148
+ Twiglet allows for the configuration of a custom validation schema. The validation schema must be [JSON Schema](https://json-schema.org/) compliant. Any fields not explicitly included in the provided schema are permitted by default.
149
+
150
+ For example, given the following JSON Schema:
151
+ ```ruby
152
+ validation_schema = <<-JSON
153
+ {
154
+ "type": "object",
155
+ "required": ["pet"],
156
+ "properties": {
157
+ "pet": {
158
+ "type": "object",
159
+ "required": ["name", "best_boy_or_girl?"],
160
+ "properties": {
161
+ "name": {
162
+ "type": "string",
163
+ "minLength": 1
164
+ },
165
+ "good_boy?": {
166
+ "type": "boolean"
167
+ }
168
+ }
169
+ }
170
+ }
171
+ }
172
+ JSON
173
+ ```
174
+
175
+ The logger can be instantiated with the custom schema
176
+ ```ruby
177
+ custom_logger = Twiglet::Logger.new('service name', validation_schema: validation_schema)
178
+ ```
179
+
180
+ Compliant log messages will log as normal.
181
+ ```ruby
182
+ # this is compliant
183
+ custom_logger.debug(pet: { name: 'Davis', good_boy?: true })
184
+
185
+ # the result
186
+ {:ecs=>{:version=>"1.5.0"}, :@timestamp=>"2020-05-11T15:01:01.000Z", :service=>{:name=>"petshop"}, :log=>{:level=>"debug"}, :pet=>{:name=>"Davis", :good_boy?=>true}}
187
+ ```
188
+
189
+ Non compliant messages will raise an error.
190
+ ```ruby
191
+ begin
192
+ custom_logger.debug(pet: { name: 'Davis' })
193
+ rescue JSON::Schema::ValidationError
194
+ # we forgot to specify that he's a good boy!
195
+ puts 'uh-oh'
196
+ end
197
+ ```
198
+
199
+ #### Customizing error responses
200
+ Depending on the application, it may not be desirable for the logger to raise Runtime errors. Twiglet allows you to configure a custom response for handling validation errors.
201
+
202
+ Configure error handling by writing a block
203
+ ```ruby
204
+ logger.configure_validation_error_response do |error|
205
+ # validation error handling goes here
206
+ # for example:
207
+ {YOUR APPLICATION BUG TRACKING SERVICE}.notify_error(error)
208
+ end
209
+
210
+ ```
211
+
212
+ ### Use of dotted keys (DEPRECATED)
148
213
 
149
214
  Writing nested json objects could be confusing. This library has a built-in feature to convert dotted keys into nested objects, so if you log like this:
150
215
 
@@ -65,7 +65,7 @@ describe RequestLogger do
65
65
  end
66
66
 
67
67
  it 'logs an error message when a request is bad' do
68
- -> { bad_request.get("/some/path") }.must_raise StandardError
68
+ expect { bad_request.get("/some/path") }.must_raise StandardError
69
69
  log = JSON.parse(output.string)
70
70
  assert_equal log['log']['level'], 'error'
71
71
  assert_equal log['error']['message'], 'some exception'
@@ -24,6 +24,6 @@ module HashExtensions
24
24
  key.to_s
25
25
  .split('.')
26
26
  .reverse
27
- .reduce(val) { |nested, key_part| Hash[key_part.to_sym, nested] }
27
+ .reduce(val) { |nested, key_part| { key_part.to_sym => nested } }
28
28
  end
29
29
  end
@@ -13,28 +13,29 @@ module Twiglet
13
13
 
14
14
  def initialize(
15
15
  service_name,
16
- default_properties: {},
17
- now: -> { Time.now.utc },
18
- output: $stdout,
19
- level: Logger::DEBUG
16
+ **args
20
17
  )
21
18
  @service_name = service_name
22
- @now = now
23
- @output = output
24
- @level = level
19
+ default_properties = args.delete(:default_properties) || {}
20
+ @args = args
21
+
22
+ now = args.fetch(:now, -> { Time.now.utc })
23
+ output = args.fetch(:output, $stdout)
24
+ level = args.fetch(:level, DEBUG)
25
+ validation_schema = args.fetch(:validation_schema, File.read("#{__dir__}/validation_schema.json"))
25
26
 
26
27
  raise 'Service name is mandatory' \
27
28
  unless service_name.is_a?(String) && !service_name.strip.empty?
28
29
 
29
- @validator = Validator.from_file("#{__dir__}/validation_schema.json")
30
+ @validator = Validator.new(validation_schema)
30
31
 
31
- @formatter = Twiglet::Formatter.new(
32
+ formatter = Twiglet::Formatter.new(
32
33
  service_name,
33
34
  default_properties: default_properties,
34
35
  now: now,
35
36
  validator: @validator
36
37
  )
37
- super(output, formatter: @formatter, level: level)
38
+ super(output, formatter: formatter, level: level)
38
39
  end
39
40
 
40
41
  def configure_validation_error_response(&block)
@@ -59,10 +60,7 @@ module Twiglet
59
60
  def with(default_properties)
60
61
  Logger.new(
61
62
  @service_name,
62
- default_properties: default_properties,
63
- now: @now,
64
- output: @output,
65
- level: @level
63
+ **@args.merge(default_properties: default_properties)
66
64
  )
67
65
  end
68
66
 
@@ -8,14 +8,10 @@ module Twiglet
8
8
  attr_accessor :custom_error_handler
9
9
 
10
10
  def initialize(schema)
11
- @schema = schema
11
+ @schema = JSON.parse(schema)
12
12
  @custom_error_handler = ->(e) { raise e }
13
13
  end
14
14
 
15
- def self.from_file(file_path)
16
- new(JSON.parse(File.read(file_path)))
17
- end
18
-
19
15
  def validate(message)
20
16
  JSON::Validator.validate!(@schema, message)
21
17
  rescue JSON::Schema::ValidationError => e
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Twiglet
4
- VERSION = '3.1.3'
4
+ VERSION = '3.2.5'
5
5
  end
@@ -8,7 +8,7 @@ require_relative '../lib/twiglet/validator'
8
8
  describe Twiglet::Formatter do
9
9
  before do
10
10
  @now = -> { Time.utc(2020, 5, 11, 15, 1, 1) }
11
- @formatter = Twiglet::Formatter.new('petshop', now: @now, validator: Twiglet::Validator.new({}))
11
+ @formatter = Twiglet::Formatter.new('petshop', now: @now, validator: Twiglet::Validator.new({}.to_json))
12
12
  end
13
13
 
14
14
  it 'initializes an instance of a Ruby Logger Formatter' do
data/test/logger_test.rb CHANGED
@@ -357,6 +357,17 @@ describe Twiglet::Logger do
357
357
  it 'initializes the logger with the provided level' do
358
358
  assert_equal Logger::WARN, Twiglet::Logger.new('petshop', level: :warn).level
359
359
  end
360
+
361
+ it 'does not log lower level' do
362
+ logger = Twiglet::Logger.new(
363
+ 'petshop',
364
+ now: @now,
365
+ output: @buffer,
366
+ level: Logger::INFO
367
+ )
368
+ logger.debug({ name: 'Davis', best_boy_or_girl?: true, species: 'dog' })
369
+ assert_empty @buffer.read
370
+ end
360
371
  end
361
372
 
362
373
  describe 'configuring error response' do
@@ -380,6 +391,61 @@ describe Twiglet::Logger do
380
391
  end
381
392
  end
382
393
 
394
+ describe 'validation schema' do
395
+ before do
396
+ validation_schema = <<-JSON
397
+ {
398
+ "type": "object",
399
+ "required": ["pet"],
400
+ "properties": {
401
+ "pet": {
402
+ "type": "object",
403
+ "required": ["name", "best_boy_or_girl?"],
404
+ "properties": {
405
+ "name": {
406
+ "type": "string",
407
+ "minLength": 1
408
+ },
409
+ "best_boy_or_girl?": {
410
+ "type": "boolean"
411
+ }
412
+ }
413
+ }
414
+ }
415
+ }
416
+ JSON
417
+
418
+ @logger = Twiglet::Logger.new(
419
+ 'petshop',
420
+ now: @now,
421
+ output: @buffer,
422
+ validation_schema: validation_schema
423
+ )
424
+ end
425
+
426
+ it 'allows for the configuration of custom validation rules' do
427
+ @logger.debug(
428
+ {
429
+ pet: { name: 'Davis', best_boy_or_girl?: true, species: 'dog' }
430
+ }
431
+ )
432
+ log = read_json(@buffer)
433
+
434
+ assert_equal true, log[:pet][:best_boy_or_girl?]
435
+ end
436
+
437
+ it 'raises when custom validation rules are broken' do
438
+ nonconformant = {
439
+ pet: { name: 'Davis' }
440
+ }
441
+
442
+ assert_raises JSON::Schema::ValidationError,
443
+ "The property '#/pet' did not contain a required property of 'best_boy_or_girl?'" do
444
+ @logger.debug(nonconformant)
445
+ end
446
+ end
447
+ end
448
+
383
449
  private
384
450
 
385
451
  def read_json(buffer)
@@ -17,7 +17,7 @@ describe Twiglet::Validator do
17
17
  }
18
18
  }
19
19
 
20
- @validator = Twiglet::Validator.new(schema)
20
+ @validator = Twiglet::Validator.new(schema.to_json)
21
21
  end
22
22
 
23
23
  it 'does not raise when validation passes' do
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.1.3
4
+ version: 3.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simply Business
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-16 00:00:00.000000000 Z
11
+ date: 2021-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json-schema
@@ -141,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
141
  - !ruby/object:Gem::Version
142
142
  version: '0'
143
143
  requirements: []
144
- rubygems_version: 3.2.3
144
+ rubygems_version: 3.2.15
145
145
  signing_key:
146
146
  specification_version: 4
147
147
  summary: Twiglet