twiglet 2.3.5 → 2.3.10

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: 7d22277c768790e3abfc51413438a55db70d811e86d30b8116781acd06aac938
4
- data.tar.gz: '0017814848a2ebde3254c51f18771271c1c17d8834d1e03c9c7ff7c620e70349'
3
+ metadata.gz: 113edbe5053c76bc7490f90c4e3d85e68077547d26d9dc4e6e98ea474cc5beea
4
+ data.tar.gz: 94b8925876c5cc095db0f5a8380701ebd9e85d22dbca3bf2aa91cd46012920db
5
5
  SHA512:
6
- metadata.gz: 833ee6bc382e10b7203041e532244d6a5582913afe56ce62170fba00f9d442e8fb70aeef294e826a7f9874f53b0f73d7801df50179d85069ac53d67928ef7b5b
7
- data.tar.gz: 590bb2ba1b31b8e6eef8f6d81bab98fc3bcf34210f5e6b6acffd46350f3e8ba7679bbbb2e332d516f742af96dc4f1dc54882d20b83851699734f523558fac059
6
+ metadata.gz: 38f61f947ee52bfd29a0990d9dd2624ae68f628e66ecb2e67569499e3d7a81459f66d0316c9edd4ec45b2d514707474a91c0d6bd2c7661646d21ad0322a40f33
7
+ data.tar.gz: 20afdfefcd5b37363eca9797472bf1fb9f0947af68b53e994786671a69c2d26acce667351794c2e5540de786115c95cec34b8d8a52d16a206128a88382d71ff2
@@ -4,6 +4,9 @@ on:
4
4
  push:
5
5
  branches:
6
6
 
7
+ env:
8
+ CI: true
9
+
7
10
  jobs:
8
11
  build:
9
12
  runs-on: ubuntu-latest
@@ -23,11 +26,22 @@ jobs:
23
26
  ruby-version: ${{ matrix.ruby-version }}
24
27
  - name: Install dependencies
25
28
  run: bundle install
29
+ - name: install cc-test-reporter
30
+ env:
31
+ CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
32
+ run: |
33
+ curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-0.6.3-linux-amd64 > ./cc-test-reporter
34
+ chmod +x ./cc-test-reporter
35
+ ./cc-test-reporter before-build
26
36
  - name: Rubocop Check
27
37
  run: bundle exec rubocop
28
38
  - name: Run all tests
29
39
  run: bundle exec rake test
30
40
  shell: bash
41
+ - name: upload test coverage to CodeClimate
42
+ env:
43
+ CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
44
+ run: ./cc-test-reporter after-build
31
45
  - name: Run example_app
32
46
  run: bundle exec ruby example_app.rb
33
47
  shell: bash
@@ -0,0 +1,16 @@
1
+ name: Check version
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - master
7
+ types: [opened, synchronize]
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-18.04
11
+
12
+ steps:
13
+ - uses: simplybusiness/version-forget-me-not@v1
14
+ env:
15
+ ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
16
+ VERSION_FILE_PATH: "lib/twiglet/version.rb"
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ *~
1
2
  *.gem
2
3
  Gemfile.lock
3
4
  *.rbc
@@ -0,0 +1,7 @@
1
+ FROM ruby:2.6.5
2
+
3
+ WORKDIR /var/app
4
+ COPY Gemfile .
5
+ RUN bundle install
6
+
7
+ CMD ["bash"]
data/Gemfile CHANGED
@@ -5,4 +5,5 @@ gem 'simplycop', git: 'https://github.com/simplybusiness/simplycop.git'
5
5
  group :development, :test do
6
6
  gem 'minitest'
7
7
  gem 'rake'
8
+ gem 'simplecov', '0.17.1'
8
9
  end
@@ -0,0 +1,9 @@
1
+ .PHONY: all build test
2
+
3
+ all: build test
4
+
5
+ build:
6
+ docker build -t simplybusiness/ruby-dev:2.6.5 .
7
+
8
+ test:
9
+ docker run -it -v `pwd`:/var/app simplybusiness/ruby-dev:2.6.5 bundle exec rake test
data/README.md CHANGED
@@ -42,9 +42,10 @@ This will write to STDOUT a JSON string:
42
42
 
43
43
  Obviously the timestamp will be different.
44
44
 
45
- Alternatively, if you just want to log some error message in text format
45
+ Alternatively, if you just want to log some error string:
46
+
46
47
  ```ruby
47
- logger.error( "Emergency! There's an Emergency going on")
48
+ logger.error("Emergency! There's an Emergency going on")
48
49
  ```
49
50
 
50
51
  This will write to STDOUT a JSON string:
@@ -53,11 +54,22 @@ This will write to STDOUT a JSON string:
53
54
  {"service":{"name":"service name"},"@timestamp":"2020-05-14T10:54:59.164+01:00","log":{"level":"error"}, "message":"Emergency! There's an Emergency going on"}
54
55
  ```
55
56
 
56
- Errors can be logged as well, and this will log the error message and backtrace in the relevant ECS compliant fields:
57
+ A message is always required unless a block is provided. The message can be an object or a string.
58
+
59
+ An optional error can also be provided, in which case the error message and backtrace will be logged in the relevant ECS compliant fields:
57
60
 
58
61
  ```ruby
59
62
  db_err = StandardError.new('Connection timed-out')
60
63
  logger.error({ message: 'DB connection failed.' }, db_err)
64
+
65
+ # this is also valid
66
+ logger.error('DB connection failed.', db_err)
67
+ ```
68
+
69
+ These will both result in the same JSON string written to STDOUT:
70
+
71
+ ```json
72
+ {"ecs":{"version":"1.5.0"},"@timestamp":"2020-08-21T15:44:37.890Z","service":{"name":"service name"},"log":{"level":"error"},"message":"DB connection failed.","error":{"message":"Connection timed-out"}}
61
73
  ```
62
74
 
63
75
  Add log event specific information simply as attributes in a hash:
@@ -81,18 +93,18 @@ This writes:
81
93
  {"service":{"name":"service name"},"@timestamp":"2020-05-14T10:56:49.527+01:00","log":{"level":"info"},"event":{"action":"HTTP request"},"message":"GET /pets success","trace":{"id":"1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb"},"http":{"request":{"method":"get"},"response":{"status_code":200}},"url":{"path":"/pets"}}
82
94
  ```
83
95
 
84
- Similar to error you can use text logging here as:
96
+ Similar to error you can use string logging here as:
85
97
 
86
98
  ```
87
99
  logger.info('GET /pets success')
88
100
  ```
101
+
89
102
  This writes:
90
103
 
91
104
  ```json
92
105
  {"service":{"name":"service name"},"@timestamp":"2020-05-14T10:56:49.527+01:00","log":{"level":"info"}}
93
106
  ```
94
107
 
95
-
96
108
  It may be that when making a series of logs that write information about a single event, you may want to avoid duplication by creating an event specific logger that includes the context:
97
109
 
98
110
  ```ruby
@@ -117,7 +129,7 @@ which will print:
117
129
  {"service":{"name":"service name"},"@timestamp":"2020-05-14T10:58:30.780+01:00","log":{"level":"error"},"event":{"action":"HTTP request"},"trace":{"id":"126bb6fa-28a2-470f-b013-eefbf9182b2d"},"message":"Error 500 in /pets/buy","http":{"request":{"method":"post","url.path":"/pet/buy"},"response":{"status_code":500}}}
118
130
  ```
119
131
 
120
- ## Use of dotted keys
132
+ ## Use of dotted keys (DEPRECATED)
121
133
 
122
134
  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:
123
135
 
data/Rakefile CHANGED
@@ -2,6 +2,6 @@ require 'rake/testtask'
2
2
 
3
3
  Rake::TestTask.new do |t|
4
4
  t.libs << "test"
5
- t.test_files = FileList['test/*_test.rb']
5
+ t.test_files = FileList['test/test_coverage.rb', 'test/*_test.rb', 'examples/rack/request_logger_test.rb']
6
6
  t.verbose = true
7
7
  end
@@ -0,0 +1,17 @@
1
+ require 'twiglet/logger'
2
+ require 'request_logger'
3
+
4
+ # basic rack application
5
+ class Application
6
+ def call(_env)
7
+ status = 200
8
+ headers = { "Content-Type" => "text/json" }
9
+ body = ["Example rack app"]
10
+
11
+ [status, headers, body]
12
+ end
13
+ end
14
+
15
+ use RequestLogger, Twiglet::Logger.new('example_app')
16
+
17
+ run Application.new
@@ -0,0 +1,49 @@
1
+ # Middleware for logging request logs
2
+ class RequestLogger
3
+ def initialize(app, logger)
4
+ @app = app
5
+ @logger = logger
6
+ end
7
+
8
+ def call(env)
9
+ status, headers, body = @app.call(env)
10
+ log(env, status)
11
+ [status, headers, body]
12
+ rescue StandardError => e
13
+ log_error(env, 500, e)
14
+ [500, {}, body]
15
+ end
16
+
17
+ private
18
+
19
+ def log(env, status)
20
+ fields = get_fields(env, status)
21
+ @logger.info(fields)
22
+ end
23
+
24
+ def log_error(env, status, error)
25
+ fields = get_fields(env, status)
26
+ @logger.error(fields, error)
27
+ end
28
+
29
+ def get_fields(env, status)
30
+ message = "#{env['REQUEST_METHOD']}: #{env['PATH_INFO']}"
31
+
32
+ {
33
+ http: {
34
+ request: {
35
+ method: env['REQUEST_METHOD'],
36
+ server: env['SERVER_NAME'],
37
+ https_enabled: env['HTTPS'],
38
+ path: env['PATH_INFO'],
39
+ query: env['QUERY_STRING'] # Don't log PII query params
40
+ },
41
+ response: {
42
+ status: status,
43
+ body: { bytes: env['CONTENT_LENGTH'] }
44
+ }
45
+ },
46
+ message: message
47
+ }
48
+ end
49
+ end
@@ -0,0 +1,66 @@
1
+ require 'minitest/autorun'
2
+ require_relative './request_logger'
3
+ require 'rack'
4
+
5
+ describe RequestLogger do
6
+ let(:output) { StringIO.new }
7
+
8
+ before { output.rewind }
9
+
10
+ it 'log should not be empty' do
11
+ request.get("/some/path")
12
+ log = output.string
13
+ refute_empty log
14
+ end
15
+
16
+ it 'logs the request data' do
17
+ request.get("/some/path?some_var=1")
18
+ log = JSON.parse(output.string)
19
+ http_body = {
20
+ "request" => {
21
+ "https_enabled" => "off",
22
+ "method" => "GET",
23
+ "path" => "/some/path",
24
+ "query" => "some_var=1",
25
+ "server" => "example.org"
26
+ },
27
+ "response" => {
28
+ "status" => 200,
29
+ "body" => { "bytes" => "0" }
30
+ }
31
+ }
32
+ assert_equal http_body, log["http"]
33
+ assert_equal "GET: /some/path", log["message"]
34
+ end
35
+
36
+ it 'does not log PII' do
37
+ request.post("/user/info", input_data: {credit_card_no: '1234'})
38
+ log = output.string
39
+ assert_includes log, "POST: /user/info"
40
+ refute_includes log, 'credit_card_no'
41
+ refute_includes log, '1234'
42
+ end
43
+
44
+ it 'logs an error message when a request is bad' do
45
+ bad_request.get("/some/path")
46
+ log = JSON.parse(output.string)
47
+ assert_equal 'error', log['log']['level']
48
+ assert_equal 'some exception', log['error']['message']
49
+ end
50
+ end
51
+
52
+ def request
53
+ app = ->(env) { [200, env, "app"] }
54
+ base_request(app)
55
+ end
56
+
57
+ def bad_request
58
+ app = Rack::Lint.new ->(_env) { raise StandardError, 'some exception' }
59
+ base_request(app)
60
+ end
61
+
62
+ def base_request(app)
63
+ logger = Twiglet::Logger.new('example', output: output)
64
+ req_logger = RequestLogger.new(app, logger)
65
+ Rack::MockRequest.new(req_logger)
66
+ end
@@ -50,6 +50,9 @@ module Twiglet
50
50
 
51
51
  def log_message(level, message:)
52
52
  base_message = {
53
+ ecs: {
54
+ version: '1.5.0'
55
+ },
53
56
  "@timestamp": @now.call.iso8601(3),
54
57
  service: {
55
58
  name: @service_name
@@ -29,7 +29,7 @@ module Twiglet
29
29
  super(output, formatter: formatter, level: level)
30
30
  end
31
31
 
32
- def error(message = {}, error = nil, &block)
32
+ def error(message = nil, error = nil, &block)
33
33
  if error
34
34
  error_fields = {
35
35
  'error': {
@@ -37,7 +37,7 @@ module Twiglet
37
37
  }
38
38
  }
39
39
  add_stack_trace(error_fields, error)
40
- message.is_a?(Hash) ? message.merge!(error_fields) : error_fields.merge!(message: message)
40
+ message = message.is_a?(Hash) ? message.merge(error_fields) : error_fields.merge(message: message)
41
41
  end
42
42
 
43
43
  super(message, &block)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Twiglet
4
- VERSION = '2.3.5'
4
+ VERSION = '2.3.10'
5
5
  end
@@ -17,6 +17,9 @@ describe Twiglet::Formatter do
17
17
  it 'returns a formatted log from a string message' do
18
18
  msg = @formatter.call('warn', nil, nil, 'shop is running low on dog food')
19
19
  expected_log = {
20
+ "ecs" => {
21
+ "version" => '1.5.0'
22
+ },
20
23
  "@timestamp" => '2020-05-11T15:01:01.000Z',
21
24
  "service" => {
22
25
  "name" => 'petshop'
@@ -49,6 +49,9 @@ describe Twiglet::Logger do
49
49
 
50
50
  expected_log = {
51
51
  message: 'Out of pets exception',
52
+ ecs: {
53
+ version: '1.5.0'
54
+ },
52
55
  "@timestamp": '2020-05-11T15:01:01.000Z',
53
56
  service: {
54
57
  name: 'petshop'
@@ -136,10 +139,10 @@ describe Twiglet::Logger do
136
139
  @logger.info({message: 'there'})
137
140
 
138
141
  expected_output =
139
- '{"@timestamp":"2020-05-11T15:01:01.000Z",'\
142
+ '{"ecs":{"version":"1.5.0"},"@timestamp":"2020-05-11T15:01:01.000Z",'\
140
143
  '"service":{"name":"petshop"},"log":{"level":"debug"},"message":"hi"}'\
141
144
  "\n"\
142
- '{"@timestamp":"2020-05-11T15:01:01.000Z",'\
145
+ '{"ecs":{"version":"1.5.0"},"@timestamp":"2020-05-11T15:01:01.000Z",'\
143
146
  '"service":{"name":"petshop"},"log":{"level":"info"},"message":"there"}'\
144
147
  "\n"\
145
148
 
@@ -227,6 +230,16 @@ describe Twiglet::Logger do
227
230
  refute actual_log[:error].key?(:stack_trace)
228
231
  end
229
232
 
233
+ it 'should log an error with string message' do
234
+ e = StandardError.new('Unknown error')
235
+ @logger.error('Artificially raised exception with string message', e)
236
+
237
+ actual_log = read_json(@buffer)
238
+
239
+ assert_equal 'Artificially raised exception with string message', actual_log[:message]
240
+ assert_equal 'Unknown error', actual_log[:error][:message]
241
+ end
242
+
230
243
  LEVELS.each do |attrs|
231
244
  it "should correctly log level when calling #{attrs[:method]}" do
232
245
  @logger.public_send(attrs[:method], {message: 'a log message'})
@@ -251,6 +264,9 @@ describe Twiglet::Logger do
251
264
 
252
265
  expected_log = {
253
266
  message: 'Out of pets exception',
267
+ ecs: {
268
+ version: '1.5.0'
269
+ },
254
270
  "@timestamp": '2020-05-11T15:01:01.000Z',
255
271
  service: {
256
272
  name: 'petshop'
@@ -0,0 +1,13 @@
1
+ require 'simplecov'
2
+
3
+ SimpleCov.start do
4
+ add_filter "/test/"
5
+ add_filter "examples/rack/request_logger_test.rb"
6
+
7
+ if ENV['CI']
8
+ formatter SimpleCov::Formatter::SimpleFormatter
9
+ else
10
+ formatter SimpleCov::Formatter::MultiFormatter.new([SimpleCov::Formatter::SimpleFormatter,
11
+ SimpleCov::Formatter::HTMLFormatter])
12
+ end
13
+ end
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: 2.3.5
4
+ version: 2.3.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simply Business
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-07 00:00:00.000000000 Z
11
+ date: 2020-08-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Like a log, only smaller.
14
14
  email:
@@ -20,16 +20,22 @@ files:
20
20
  - ".github/CODEOWNERS"
21
21
  - ".github/workflows/gem-publish.yml"
22
22
  - ".github/workflows/ruby.yml"
23
+ - ".github/workflows/version-forget-me-not.yml"
23
24
  - ".gitignore"
24
25
  - ".rubocop.yml"
25
26
  - ".ruby-version"
26
27
  - CODE_OF_CONDUCT.md
28
+ - Dockerfile
27
29
  - Gemfile
28
30
  - LICENSE
31
+ - Makefile
29
32
  - RATIONALE.md
30
33
  - README.md
31
34
  - Rakefile
32
35
  - example_app.rb
36
+ - examples/rack/example_rack_app.rb
37
+ - examples/rack/request_logger.rb
38
+ - examples/rack/request_logger_test.rb
33
39
  - lib/hash_extensions.rb
34
40
  - lib/twiglet/formatter.rb
35
41
  - lib/twiglet/logger.rb
@@ -37,6 +43,7 @@ files:
37
43
  - test/formatter_test.rb
38
44
  - test/hash_extensions_test.rb
39
45
  - test/logger_test.rb
46
+ - test/test_coverage.rb
40
47
  - twiglet.gemspec
41
48
  homepage: https://github.com/simplybusiness/twiglet-ruby
42
49
  licenses: