twiglet 2.3.5 → 2.3.10

Sign up to get free protection for your applications and to get access to all the features.
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: