berkeley_library-logging 0.2.0 → 0.2.4

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: 55747e6057035bf2f9f2d078ba3f66a6c0456891d7bde0fc019898ee28582ac1
4
- data.tar.gz: c8c9f150c6278fa08b239fc1ace35211d09e1b33bc85a172e6025ae5e18d4756
3
+ metadata.gz: 91d0f1a398e99a9e138f90946025b7d5576cda6a4b6e4e8c137b77ec8febbd2f
4
+ data.tar.gz: 1300926d8af70a24e6fff33e3ac1e8af79c428e7c35302fab335d255f713d7a1
5
5
  SHA512:
6
- metadata.gz: c72ac07ab71e93d87bbc6dc2479a243e1fb17f68a9eb373112d99b59587c35fd81b42c259f79f519c016a0abe0700c9c13d19c249e14d730b33216548c5168e3
7
- data.tar.gz: 05dbcb9d79db5886f908d3f3965c4c303f9dd04a382feb6ce38bdc2557ec5d25f27f3ce945129cf88f95eebf9ab9239f0ee2b0658ee832a93de58decb2af4c5c
6
+ metadata.gz: 2271582ebc293b95a3f9dc18c9c922b780abf1ab1636f549f9ac1093a4b72dabd8a6c224bd51e53be7b128b0f65759dd639bef744f7586659b98fcbd4eb19431
7
+ data.tar.gz: 874db3c599bfa7a1a00d9b15c35bc85120f1ed573ba5088c99c83bc12ef81ea1ab8e5c2fd081996c6ac684a0c2befc573de57547c951111b6e9e41c726847e64
@@ -0,0 +1,18 @@
1
+ name: Build
2
+ on: [ push, pull_request ]
3
+ jobs:
4
+ test:
5
+ strategy:
6
+ fail-fast: false
7
+ matrix:
8
+ os: [ ubuntu-latest, macos-latest ]
9
+ ruby: [ '2.7', '3.0' ]
10
+ runs-on: ${{ matrix.os }}
11
+
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+ - uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: ${{ matrix.ruby }}
17
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
18
+ - run: bundle exec rake
data/.idea/logging.iml CHANGED
@@ -9,93 +9,93 @@
9
9
  <sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
10
10
  <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
11
11
  </content>
12
- <orderEntry type="jdk" jdkName="RVM: ruby-2.7.3" jdkType="RUBY_SDK" />
12
+ <orderEntry type="jdk" jdkName="RVM: ruby-2.7.4" jdkType="RUBY_SDK" />
13
13
  <orderEntry type="sourceFolder" forTests="false" />
14
- <orderEntry type="library" scope="PROVIDED" name="actioncable (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
15
- <orderEntry type="library" scope="PROVIDED" name="actionmailbox (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
16
- <orderEntry type="library" scope="PROVIDED" name="actionmailer (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
17
- <orderEntry type="library" scope="PROVIDED" name="actionpack (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
18
- <orderEntry type="library" scope="PROVIDED" name="actiontext (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
19
- <orderEntry type="library" scope="PROVIDED" name="actionview (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
20
- <orderEntry type="library" scope="PROVIDED" name="activejob (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
21
- <orderEntry type="library" scope="PROVIDED" name="activemodel (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
22
- <orderEntry type="library" scope="PROVIDED" name="activerecord (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
23
- <orderEntry type="library" scope="PROVIDED" name="activestorage (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
24
- <orderEntry type="library" scope="PROVIDED" name="activesupport (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
25
- <orderEntry type="library" scope="PROVIDED" name="amazing_print (v1.3.0, RVM: ruby-2.7.3) [gem]" level="application" />
26
- <orderEntry type="library" scope="PROVIDED" name="ansi (v1.5.0, RVM: ruby-2.7.3) [gem]" level="application" />
27
- <orderEntry type="library" scope="PROVIDED" name="ast (v2.4.2, RVM: ruby-2.7.3) [gem]" level="application" />
28
- <orderEntry type="library" scope="PROVIDED" name="brakeman (v4.10.1, RVM: ruby-2.7.3) [gem]" level="application" />
29
- <orderEntry type="library" scope="PROVIDED" name="builder (v3.2.4, RVM: ruby-2.7.3) [gem]" level="application" />
30
- <orderEntry type="library" scope="PROVIDED" name="bundle-audit (v0.1.0, RVM: ruby-2.7.3) [gem]" level="application" />
31
- <orderEntry type="library" scope="PROVIDED" name="bundler (v2.2.14, RVM: ruby-2.7.3) [gem]" level="application" />
32
- <orderEntry type="library" scope="PROVIDED" name="bundler-audit (v0.8.0, RVM: ruby-2.7.3) [gem]" level="application" />
33
- <orderEntry type="library" scope="PROVIDED" name="ci_reporter (v2.0.0, RVM: ruby-2.7.3) [gem]" level="application" />
34
- <orderEntry type="library" scope="PROVIDED" name="ci_reporter_rspec (v1.0.0, RVM: ruby-2.7.3) [gem]" level="application" />
35
- <orderEntry type="library" scope="PROVIDED" name="colorize (v0.8.1, RVM: ruby-2.7.3) [gem]" level="application" />
36
- <orderEntry type="library" scope="PROVIDED" name="concurrent-ruby (v1.1.9, RVM: ruby-2.7.3) [gem]" level="application" />
37
- <orderEntry type="library" scope="PROVIDED" name="crass (v1.0.6, RVM: ruby-2.7.3) [gem]" level="application" />
38
- <orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.4.4, RVM: ruby-2.7.3) [gem]" level="application" />
39
- <orderEntry type="library" scope="PROVIDED" name="docile (v1.4.0, RVM: ruby-2.7.3) [gem]" level="application" />
40
- <orderEntry type="library" scope="PROVIDED" name="dotenv (v2.7.6, RVM: ruby-2.7.3) [gem]" level="application" />
41
- <orderEntry type="library" scope="PROVIDED" name="erubi (v1.10.0, RVM: ruby-2.7.3) [gem]" level="application" />
42
- <orderEntry type="library" scope="PROVIDED" name="ffi (v1.15.3, RVM: ruby-2.7.3) [gem]" level="application" />
43
- <orderEntry type="library" scope="PROVIDED" name="globalid (v0.5.2, RVM: ruby-2.7.3) [gem]" level="application" />
44
- <orderEntry type="library" scope="PROVIDED" name="i18n (v1.8.10, RVM: ruby-2.7.3) [gem]" level="application" />
45
- <orderEntry type="library" scope="PROVIDED" name="io-console (v0.5.9, RVM: ruby-2.7.3) [gem]" level="application" />
46
- <orderEntry type="library" scope="PROVIDED" name="irb (v1.3.7, RVM: ruby-2.7.3) [gem]" level="application" />
47
- <orderEntry type="library" scope="PROVIDED" name="listen (v3.1.5, RVM: ruby-2.7.3) [gem]" level="application" />
48
- <orderEntry type="library" scope="PROVIDED" name="lograge (v0.11.2, RVM: ruby-2.7.3) [gem]" level="application" />
49
- <orderEntry type="library" scope="PROVIDED" name="loofah (v2.12.0, RVM: ruby-2.7.3) [gem]" level="application" />
50
- <orderEntry type="library" scope="PROVIDED" name="mail (v2.7.1, RVM: ruby-2.7.3) [gem]" level="application" />
51
- <orderEntry type="library" scope="PROVIDED" name="marcel (v1.0.1, RVM: ruby-2.7.3) [gem]" level="application" />
52
- <orderEntry type="library" scope="PROVIDED" name="method_source (v1.0.0, RVM: ruby-2.7.3) [gem]" level="application" />
53
- <orderEntry type="library" scope="PROVIDED" name="mini_mime (v1.1.0, RVM: ruby-2.7.3) [gem]" level="application" />
54
- <orderEntry type="library" scope="PROVIDED" name="minitest (v5.14.4, RVM: ruby-2.7.3) [gem]" level="application" />
55
- <orderEntry type="library" scope="PROVIDED" name="nio4r (v2.5.8, RVM: ruby-2.7.3) [gem]" level="application" />
56
- <orderEntry type="library" scope="PROVIDED" name="nokogiri (v1.12.3, RVM: ruby-2.7.3) [gem]" level="application" />
57
- <orderEntry type="library" scope="PROVIDED" name="oj (v3.13.2, RVM: ruby-2.7.3) [gem]" level="application" />
58
- <orderEntry type="library" scope="PROVIDED" name="ougai (v1.9.1, RVM: ruby-2.7.3) [gem]" level="application" />
59
- <orderEntry type="library" scope="PROVIDED" name="parallel (v1.20.1, RVM: ruby-2.7.3) [gem]" level="application" />
60
- <orderEntry type="library" scope="PROVIDED" name="parser (v3.0.2.0, RVM: ruby-2.7.3) [gem]" level="application" />
61
- <orderEntry type="library" scope="PROVIDED" name="racc (v1.5.2, RVM: ruby-2.7.3) [gem]" level="application" />
62
- <orderEntry type="library" scope="PROVIDED" name="rack (v2.2.3, RVM: ruby-2.7.3) [gem]" level="application" />
63
- <orderEntry type="library" scope="PROVIDED" name="rack-test (v1.1.0, RVM: ruby-2.7.3) [gem]" level="application" />
64
- <orderEntry type="library" scope="PROVIDED" name="rails (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
65
- <orderEntry type="library" scope="PROVIDED" name="rails-dom-testing (v2.0.3, RVM: ruby-2.7.3) [gem]" level="application" />
66
- <orderEntry type="library" scope="PROVIDED" name="rails-html-sanitizer (v1.4.1, RVM: ruby-2.7.3) [gem]" level="application" />
67
- <orderEntry type="library" scope="PROVIDED" name="railties (v6.1.4, RVM: ruby-2.7.3) [gem]" level="application" />
68
- <orderEntry type="library" scope="PROVIDED" name="rainbow (v3.0.0, RVM: ruby-2.7.3) [gem]" level="application" />
69
- <orderEntry type="library" scope="PROVIDED" name="rake (v13.0.6, RVM: ruby-2.7.3) [gem]" level="application" />
70
- <orderEntry type="library" scope="PROVIDED" name="rb-fsevent (v0.11.0, RVM: ruby-2.7.3) [gem]" level="application" />
71
- <orderEntry type="library" scope="PROVIDED" name="rb-inotify (v0.10.1, RVM: ruby-2.7.3) [gem]" level="application" />
72
- <orderEntry type="library" scope="PROVIDED" name="regexp_parser (v2.1.1, RVM: ruby-2.7.3) [gem]" level="application" />
73
- <orderEntry type="library" scope="PROVIDED" name="reline (v0.2.7, RVM: ruby-2.7.3) [gem]" level="application" />
74
- <orderEntry type="library" scope="PROVIDED" name="request_store (v1.5.0, RVM: ruby-2.7.3) [gem]" level="application" />
75
- <orderEntry type="library" scope="PROVIDED" name="rexml (v3.2.5, RVM: ruby-2.7.3) [gem]" level="application" />
76
- <orderEntry type="library" scope="PROVIDED" name="rspec (v3.10.0, RVM: ruby-2.7.3) [gem]" level="application" />
77
- <orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.10.1, RVM: ruby-2.7.3) [gem]" level="application" />
78
- <orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.10.1, RVM: ruby-2.7.3) [gem]" level="application" />
79
- <orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.10.2, RVM: ruby-2.7.3) [gem]" level="application" />
80
- <orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.10.2, RVM: ruby-2.7.3) [gem]" level="application" />
81
- <orderEntry type="library" scope="PROVIDED" name="rubocop (v0.91.1, RVM: ruby-2.7.3) [gem]" level="application" />
82
- <orderEntry type="library" scope="PROVIDED" name="rubocop-ast (v0.8.0, RVM: ruby-2.7.3) [gem]" level="application" />
83
- <orderEntry type="library" scope="PROVIDED" name="ruby-progressbar (v1.11.0, RVM: ruby-2.7.3) [gem]" level="application" />
84
- <orderEntry type="library" scope="PROVIDED" name="ruby_dep (v1.5.0, RVM: ruby-2.7.3) [gem]" level="application" />
85
- <orderEntry type="library" scope="PROVIDED" name="simplecov (v0.21.2, RVM: ruby-2.7.3) [gem]" level="application" />
86
- <orderEntry type="library" scope="PROVIDED" name="simplecov-console (v0.9.1, RVM: ruby-2.7.3) [gem]" level="application" />
87
- <orderEntry type="library" scope="PROVIDED" name="simplecov-html (v0.12.3, RVM: ruby-2.7.3) [gem]" level="application" />
88
- <orderEntry type="library" scope="PROVIDED" name="simplecov-rcov (v0.2.3, RVM: ruby-2.7.3) [gem]" level="application" />
89
- <orderEntry type="library" scope="PROVIDED" name="simplecov_json_formatter (v0.1.3, RVM: ruby-2.7.3) [gem]" level="application" />
90
- <orderEntry type="library" scope="PROVIDED" name="sprockets (v4.0.2, RVM: ruby-2.7.3) [gem]" level="application" />
91
- <orderEntry type="library" scope="PROVIDED" name="sprockets-rails (v3.2.2, RVM: ruby-2.7.3) [gem]" level="application" />
92
- <orderEntry type="library" scope="PROVIDED" name="terminal-table (v3.0.1, RVM: ruby-2.7.3) [gem]" level="application" />
93
- <orderEntry type="library" scope="PROVIDED" name="thor (v1.1.0, RVM: ruby-2.7.3) [gem]" level="application" />
94
- <orderEntry type="library" scope="PROVIDED" name="tzinfo (v2.0.4, RVM: ruby-2.7.3) [gem]" level="application" />
95
- <orderEntry type="library" scope="PROVIDED" name="unicode-display_width (v1.7.0, RVM: ruby-2.7.3) [gem]" level="application" />
96
- <orderEntry type="library" scope="PROVIDED" name="websocket-driver (v0.7.5, RVM: ruby-2.7.3) [gem]" level="application" />
97
- <orderEntry type="library" scope="PROVIDED" name="websocket-extensions (v0.1.5, RVM: ruby-2.7.3) [gem]" level="application" />
98
- <orderEntry type="library" scope="PROVIDED" name="zeitwerk (v2.4.2, RVM: ruby-2.7.3) [gem]" level="application" />
14
+ <orderEntry type="library" scope="PROVIDED" name="actioncable (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
15
+ <orderEntry type="library" scope="PROVIDED" name="actionmailbox (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
16
+ <orderEntry type="library" scope="PROVIDED" name="actionmailer (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
17
+ <orderEntry type="library" scope="PROVIDED" name="actionpack (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
18
+ <orderEntry type="library" scope="PROVIDED" name="actiontext (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
19
+ <orderEntry type="library" scope="PROVIDED" name="actionview (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
20
+ <orderEntry type="library" scope="PROVIDED" name="activejob (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
21
+ <orderEntry type="library" scope="PROVIDED" name="activemodel (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
22
+ <orderEntry type="library" scope="PROVIDED" name="activerecord (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
23
+ <orderEntry type="library" scope="PROVIDED" name="activestorage (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
24
+ <orderEntry type="library" scope="PROVIDED" name="activesupport (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
25
+ <orderEntry type="library" scope="PROVIDED" name="amazing_print (v1.3.0, RVM: ruby-2.7.4) [gem]" level="application" />
26
+ <orderEntry type="library" scope="PROVIDED" name="ansi (v1.5.0, RVM: ruby-2.7.4) [gem]" level="application" />
27
+ <orderEntry type="library" scope="PROVIDED" name="ast (v2.4.2, RVM: ruby-2.7.4) [gem]" level="application" />
28
+ <orderEntry type="library" scope="PROVIDED" name="brakeman (v4.10.1, RVM: ruby-2.7.4) [gem]" level="application" />
29
+ <orderEntry type="library" scope="PROVIDED" name="builder (v3.2.4, RVM: ruby-2.7.4) [gem]" level="application" />
30
+ <orderEntry type="library" scope="PROVIDED" name="bundle-audit (v0.1.0, RVM: ruby-2.7.4) [gem]" level="application" />
31
+ <orderEntry type="library" scope="PROVIDED" name="bundler (v2.2.14, RVM: ruby-2.7.4) [gem]" level="application" />
32
+ <orderEntry type="library" scope="PROVIDED" name="bundler-audit (v0.9.0.1, RVM: ruby-2.7.4) [gem]" level="application" />
33
+ <orderEntry type="library" scope="PROVIDED" name="ci_reporter (v2.0.0, RVM: ruby-2.7.4) [gem]" level="application" />
34
+ <orderEntry type="library" scope="PROVIDED" name="ci_reporter_rspec (v1.0.0, RVM: ruby-2.7.4) [gem]" level="application" />
35
+ <orderEntry type="library" scope="PROVIDED" name="colorize (v0.8.1, RVM: ruby-2.7.4) [gem]" level="application" />
36
+ <orderEntry type="library" scope="PROVIDED" name="concurrent-ruby (v1.1.9, RVM: ruby-2.7.4) [gem]" level="application" />
37
+ <orderEntry type="library" scope="PROVIDED" name="crass (v1.0.6, RVM: ruby-2.7.4) [gem]" level="application" />
38
+ <orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.4.4, RVM: ruby-2.7.4) [gem]" level="application" />
39
+ <orderEntry type="library" scope="PROVIDED" name="docile (v1.4.0, RVM: ruby-2.7.4) [gem]" level="application" />
40
+ <orderEntry type="library" scope="PROVIDED" name="dotenv (v2.7.6, RVM: ruby-2.7.4) [gem]" level="application" />
41
+ <orderEntry type="library" scope="PROVIDED" name="erubi (v1.10.0, RVM: ruby-2.7.4) [gem]" level="application" />
42
+ <orderEntry type="library" scope="PROVIDED" name="ffi (v1.15.4, RVM: ruby-2.7.4) [gem]" level="application" />
43
+ <orderEntry type="library" scope="PROVIDED" name="globalid (v0.5.2, RVM: ruby-2.7.4) [gem]" level="application" />
44
+ <orderEntry type="library" scope="PROVIDED" name="i18n (v1.8.10, RVM: ruby-2.7.4) [gem]" level="application" />
45
+ <orderEntry type="library" scope="PROVIDED" name="io-console (v0.5.9, RVM: ruby-2.7.4) [gem]" level="application" />
46
+ <orderEntry type="library" scope="PROVIDED" name="irb (v1.3.7, RVM: ruby-2.7.4) [gem]" level="application" />
47
+ <orderEntry type="library" scope="PROVIDED" name="listen (v3.1.5, RVM: ruby-2.7.4) [gem]" level="application" />
48
+ <orderEntry type="library" scope="PROVIDED" name="lograge (v0.11.2, RVM: ruby-2.7.4) [gem]" level="application" />
49
+ <orderEntry type="library" scope="PROVIDED" name="loofah (v2.12.0, RVM: ruby-2.7.4) [gem]" level="application" />
50
+ <orderEntry type="library" scope="PROVIDED" name="mail (v2.7.1, RVM: ruby-2.7.4) [gem]" level="application" />
51
+ <orderEntry type="library" scope="PROVIDED" name="marcel (v1.0.2, RVM: ruby-2.7.4) [gem]" level="application" />
52
+ <orderEntry type="library" scope="PROVIDED" name="method_source (v1.0.0, RVM: ruby-2.7.4) [gem]" level="application" />
53
+ <orderEntry type="library" scope="PROVIDED" name="mini_mime (v1.1.1, RVM: ruby-2.7.4) [gem]" level="application" />
54
+ <orderEntry type="library" scope="PROVIDED" name="minitest (v5.14.4, RVM: ruby-2.7.4) [gem]" level="application" />
55
+ <orderEntry type="library" scope="PROVIDED" name="nio4r (v2.5.8, RVM: ruby-2.7.4) [gem]" level="application" />
56
+ <orderEntry type="library" scope="PROVIDED" name="nokogiri (v1.12.4, RVM: ruby-2.7.4) [gem]" level="application" />
57
+ <orderEntry type="library" scope="PROVIDED" name="oj (v3.13.7, RVM: ruby-2.7.4) [gem]" level="application" />
58
+ <orderEntry type="library" scope="PROVIDED" name="ougai (v1.9.1, RVM: ruby-2.7.4) [gem]" level="application" />
59
+ <orderEntry type="library" scope="PROVIDED" name="parallel (v1.21.0, RVM: ruby-2.7.4) [gem]" level="application" />
60
+ <orderEntry type="library" scope="PROVIDED" name="parser (v3.0.2.0, RVM: ruby-2.7.4) [gem]" level="application" />
61
+ <orderEntry type="library" scope="PROVIDED" name="racc (v1.5.2, RVM: ruby-2.7.4) [gem]" level="application" />
62
+ <orderEntry type="library" scope="PROVIDED" name="rack (v2.2.3, RVM: ruby-2.7.4) [gem]" level="application" />
63
+ <orderEntry type="library" scope="PROVIDED" name="rack-test (v1.1.0, RVM: ruby-2.7.4) [gem]" level="application" />
64
+ <orderEntry type="library" scope="PROVIDED" name="rails (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
65
+ <orderEntry type="library" scope="PROVIDED" name="rails-dom-testing (v2.0.3, RVM: ruby-2.7.4) [gem]" level="application" />
66
+ <orderEntry type="library" scope="PROVIDED" name="rails-html-sanitizer (v1.4.2, RVM: ruby-2.7.4) [gem]" level="application" />
67
+ <orderEntry type="library" scope="PROVIDED" name="railties (v6.1.4.1, RVM: ruby-2.7.4) [gem]" level="application" />
68
+ <orderEntry type="library" scope="PROVIDED" name="rainbow (v3.0.0, RVM: ruby-2.7.4) [gem]" level="application" />
69
+ <orderEntry type="library" scope="PROVIDED" name="rake (v13.0.6, RVM: ruby-2.7.4) [gem]" level="application" />
70
+ <orderEntry type="library" scope="PROVIDED" name="rb-fsevent (v0.11.0, RVM: ruby-2.7.4) [gem]" level="application" />
71
+ <orderEntry type="library" scope="PROVIDED" name="rb-inotify (v0.10.1, RVM: ruby-2.7.4) [gem]" level="application" />
72
+ <orderEntry type="library" scope="PROVIDED" name="regexp_parser (v2.1.1, RVM: ruby-2.7.4) [gem]" level="application" />
73
+ <orderEntry type="library" scope="PROVIDED" name="reline (v0.2.7, RVM: ruby-2.7.4) [gem]" level="application" />
74
+ <orderEntry type="library" scope="PROVIDED" name="request_store (v1.5.0, RVM: ruby-2.7.4) [gem]" level="application" />
75
+ <orderEntry type="library" scope="PROVIDED" name="rexml (v3.2.5, RVM: ruby-2.7.4) [gem]" level="application" />
76
+ <orderEntry type="library" scope="PROVIDED" name="rspec (v3.10.0, RVM: ruby-2.7.4) [gem]" level="application" />
77
+ <orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.10.1, RVM: ruby-2.7.4) [gem]" level="application" />
78
+ <orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.10.1, RVM: ruby-2.7.4) [gem]" level="application" />
79
+ <orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.10.2, RVM: ruby-2.7.4) [gem]" level="application" />
80
+ <orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.10.2, RVM: ruby-2.7.4) [gem]" level="application" />
81
+ <orderEntry type="library" scope="PROVIDED" name="rubocop (v0.91.1, RVM: ruby-2.7.4) [gem]" level="application" />
82
+ <orderEntry type="library" scope="PROVIDED" name="rubocop-ast (v0.8.0, RVM: ruby-2.7.4) [gem]" level="application" />
83
+ <orderEntry type="library" scope="PROVIDED" name="ruby-progressbar (v1.11.0, RVM: ruby-2.7.4) [gem]" level="application" />
84
+ <orderEntry type="library" scope="PROVIDED" name="ruby_dep (v1.5.0, RVM: ruby-2.7.4) [gem]" level="application" />
85
+ <orderEntry type="library" scope="PROVIDED" name="simplecov (v0.21.2, RVM: ruby-2.7.4) [gem]" level="application" />
86
+ <orderEntry type="library" scope="PROVIDED" name="simplecov-console (v0.9.1, RVM: ruby-2.7.4) [gem]" level="application" />
87
+ <orderEntry type="library" scope="PROVIDED" name="simplecov-html (v0.12.3, RVM: ruby-2.7.4) [gem]" level="application" />
88
+ <orderEntry type="library" scope="PROVIDED" name="simplecov-rcov (v0.2.3, RVM: ruby-2.7.4) [gem]" level="application" />
89
+ <orderEntry type="library" scope="PROVIDED" name="simplecov_json_formatter (v0.1.3, RVM: ruby-2.7.4) [gem]" level="application" />
90
+ <orderEntry type="library" scope="PROVIDED" name="sprockets (v4.0.2, RVM: ruby-2.7.4) [gem]" level="application" />
91
+ <orderEntry type="library" scope="PROVIDED" name="sprockets-rails (v3.2.2, RVM: ruby-2.7.4) [gem]" level="application" />
92
+ <orderEntry type="library" scope="PROVIDED" name="terminal-table (v3.0.2, RVM: ruby-2.7.4) [gem]" level="application" />
93
+ <orderEntry type="library" scope="PROVIDED" name="thor (v1.1.0, RVM: ruby-2.7.4) [gem]" level="application" />
94
+ <orderEntry type="library" scope="PROVIDED" name="tzinfo (v2.0.4, RVM: ruby-2.7.4) [gem]" level="application" />
95
+ <orderEntry type="library" scope="PROVIDED" name="unicode-display_width (v1.8.0, RVM: ruby-2.7.4) [gem]" level="application" />
96
+ <orderEntry type="library" scope="PROVIDED" name="websocket-driver (v0.7.5, RVM: ruby-2.7.4) [gem]" level="application" />
97
+ <orderEntry type="library" scope="PROVIDED" name="websocket-extensions (v0.1.5, RVM: ruby-2.7.4) [gem]" level="application" />
98
+ <orderEntry type="library" scope="PROVIDED" name="zeitwerk (v2.4.2, RVM: ruby-2.7.4) [gem]" level="application" />
99
99
  </component>
100
100
  <component name="RakeTasksCache">
101
101
  <option name="myRootTask">
@@ -110,7 +110,7 @@
110
110
  <RakeTaskImpl description="Remove artifacts directory" fullCommand="clean" id="clean" />
111
111
  <RakeTaskImpl description="Run all specs in spec directory, with coverage" fullCommand="coverage" id="coverage" />
112
112
  <RakeTaskImpl description="Clean, check, build gem" fullCommand="default" id="default" />
113
- <RakeTaskImpl description="Build berkeley_library-logging.gemspec as berkeley_library-logging-0.2.0.gem" fullCommand="gem" id="gem" />
113
+ <RakeTaskImpl description="Build berkeley_library-logging.gemspec as berkeley_library-logging-0.2.3.gem" fullCommand="gem" id="gem" />
114
114
  <RakeTaskImpl description="Run RuboCop" fullCommand="rubocop" id="rubocop" />
115
115
  <RakeTaskImpl id="rubocop">
116
116
  <subtasks>
data/.rubocop.yml CHANGED
@@ -4,6 +4,7 @@ AllCops:
4
4
  - 'bin/**/*'
5
5
  - 'node_modules/**/*'
6
6
  - 'artifacts/**/*'
7
+ - 'vendor/**/*'
7
8
 
8
9
  # Allow one line around block body (Layout/EmptyLines will still disallow two or more)
9
10
  Layout/EmptyLinesAroundBlockBody:
data/.simplecov CHANGED
@@ -1,4 +1,3 @@
1
1
  SimpleCov.start 'rails' do
2
2
  add_filter 'module_info.rb'
3
- formatter SimpleCov::Formatter::SimpleFormatter
4
3
  end
data/CHANGES.md CHANGED
@@ -1,3 +1,27 @@
1
+ # 0.2.4 (2021-11-02)
2
+
3
+ - Rails event logs now include the following, in addition to the
4
+ headers already logged:
5
+
6
+ - `request.origin`
7
+ - `request.base_url`
8
+ - `request.x_csrf_token`
9
+ - `params[:authenticity_token]`
10
+
11
+ # 0.2.3 (2021-09-02)
12
+
13
+ - JSON formatter now strips all ANSI 7-bit C1 escapes from strings
14
+ (fixes [#1](https://github.com/BerkeleyLibrary/logging/issues/1) properly)
15
+
16
+ # 0.2.2 (2021-09-02)
17
+
18
+ - JSON formatter now strips ANSI color escapes from strings
19
+ (fixes [#1](https://github.com/BerkeleyLibrary/logging/issues/1))
20
+
21
+ # 0.2.1 (2021-08-19)
22
+
23
+ - Recursively log error cause
24
+
1
25
  # 0.2.0 (2021-08-18)
2
26
 
3
27
  - Rename to `BerkeleyLibrary::Logging` in prep for move to GitHub
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # The MIT License (MIT)
2
2
 
3
- Copyright © 2020 The Regents of the University of California
3
+ Copyright © 2021 The Regents of the University of California
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a
6
6
  copy of this software and associated documentation files (the “Software”),
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # BerkeleyLibrary::Logging
2
2
 
3
- [![Build Status](https://travis-ci.com/BerkeleyLibrary/logging.svg?branch=main)](https://travis-ci.com/github/BerkeleyLibrary/logging/)
4
- [![Gem Version](https://img.shields.io/gem/v/berkeley_library-logging.svg)](https://github.com/BerkeleyLibrary/logging/releases)
3
+ [![Build Status](https://github.com/BerkeleyLibrary/logging/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/BerkeleyLibrary/logging/actions/workflows/build.yml)
4
+ [![Gem Version](https://img.shields.io/gem/v/berkeley_library-logging.svg)](https://rubygems.org/gems/berkeley_library-logging/)
5
5
 
6
6
  Opinionated logging for UCB Library IT Rails applications.
7
7
 
data/artifacts/.keep ADDED
File without changes
@@ -27,13 +27,13 @@ Gem::Specification.new do |spec|
27
27
 
28
28
  spec.add_dependency 'activesupport', '~> 6.0'
29
29
  spec.add_dependency 'amazing_print', '~> 1.1'
30
+ spec.add_dependency 'colorize', '~> 0.8.1'
30
31
  spec.add_dependency 'lograge', '~> 0.11'
31
32
  spec.add_dependency 'ougai', '~> 1.8'
32
33
 
33
34
  spec.add_development_dependency 'brakeman', '~> 4.9'
34
35
  spec.add_development_dependency 'bundle-audit', '~> 0.1'
35
36
  spec.add_development_dependency 'ci_reporter_rspec', '~> 1.0'
36
- spec.add_development_dependency 'colorize', '~> 0.8'
37
37
  spec.add_development_dependency 'dotenv', '~> 2.7'
38
38
  spec.add_development_dependency 'irb', '~> 1.2' # workaroundfor https://github.com/bundler/bundler/issues/6929
39
39
  spec.add_development_dependency 'listen', '>= 3.0.5', '< 3.2'
@@ -2,6 +2,19 @@ module BerkeleyLibrary
2
2
  module Logging
3
3
  module Events
4
4
  class << self
5
+ LOGGED_REQUEST_ATTRIBUTES = %i[origin base_url x_csrf_token].freeze
6
+ LOGGED_PARAMETERS = [:authenticity_token].freeze
7
+ LOGGED_HEADERS = {
8
+ # yes, RFC 2616 uses a variant spelling for 'referrer', it's a known issue
9
+ # https://tools.ietf.org/html/rfc2616#section-14.36
10
+ referer: 'HTTP_REFERER',
11
+ request_id: 'action_dispatch.request_id',
12
+ remote_ip: 'action_dispatch.remote_ip',
13
+ remote_addr: 'REMOTE_ADDR',
14
+ x_forwarded_for: 'HTTP_X_FORWARDED_FOR',
15
+ forwarded: 'HTTP_FORWARDED' # RFC 7239
16
+ }.freeze
17
+
5
18
  def extract_data_for_lograge
6
19
  ->(event) { extract_event_data(event) }
7
20
  end
@@ -9,29 +22,50 @@ module BerkeleyLibrary
9
22
  private
10
23
 
11
24
  def extract_event_data(event)
12
- event_data = { time: Time.now }
13
- extracted_headers = extract_headers(event)
14
- event_data.merge(extracted_headers)
25
+ { time: Time.now }.tap do |event_data|
26
+ headers = extract_headers(event)
27
+ event_data.merge!(headers)
28
+
29
+ request_attributes = extract_request_attributes(event)
30
+ event_data.merge!(request_attributes)
31
+
32
+ param_values = extract_param_values(event)
33
+ event_data.merge!(param_values)
34
+ end
35
+ end
36
+
37
+ def extract_param_values(event)
38
+ return {} unless (params = event.payload[:params])
39
+
40
+ LOGGED_PARAMETERS.each_with_object({}) do |param, values|
41
+ next unless (param_val = params[param])
42
+
43
+ values[param] = param_val
44
+ end
45
+ end
46
+
47
+ def extract_request_attributes(event)
48
+ return {} unless (request = event.payload[:request])
49
+
50
+ LOGGED_REQUEST_ATTRIBUTES.each_with_object({}) do |attr, values|
51
+ next unless request.respond_to?(attr)
52
+ next unless (attr_val = request.send(attr))
53
+
54
+ values[attr] = attr_val
55
+ end
15
56
  end
16
57
 
17
58
  def extract_headers(event)
18
59
  return {} unless (headers = event.payload[:headers])
19
60
 
20
- extracted_headers = {
21
- # yes, RFC 2616 uses a variant spelling for 'referrer', it's a known issue
22
- # https://tools.ietf.org/html/rfc2616#section-14.36
23
- referer: headers['HTTP_REFERER'],
24
- request_id: headers['action_dispatch.request_id'],
25
- remote_ip: headers['action_dispatch.remote_ip'],
26
- remote_addr: headers['REMOTE_ADDR'],
27
- x_forwarded_for: headers['HTTP_X_FORWARDED_FOR'],
28
- forwarded: headers['HTTP_FORWARDED'] # RFC 7239
29
- }
30
-
31
- # Some of these 'headers' include recursive structures
32
- # that cause SystemStackErrors in JSON serialization,
33
- # so we convert them all to strings
34
- extracted_headers.transform_values(&:to_s)
61
+ LOGGED_HEADERS.each_with_object({}) do |(key, header), values|
62
+ next unless (header_val = headers[header])
63
+
64
+ # Some of these 'headers' include recursive structures
65
+ # that cause SystemStackErrors in JSON serialization,
66
+ # so we convert them all to strings
67
+ values[key] = header_val.to_s
68
+ end
35
69
  end
36
70
  end
37
71
  end
@@ -5,12 +5,16 @@ module BerkeleyLibrary
5
5
  module Formatters
6
6
 
7
7
  class << self
8
+
9
+ # See https://stackoverflow.com/a/14693789/27358
10
+ ANSI_7C1_RE = %r{\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])}.freeze
11
+
8
12
  def new_json_formatter
9
13
  Bunyan.new
10
14
  end
11
15
 
12
16
  def new_readable_formatter
13
- Ougai::Formatters::Readable.new
17
+ Readable.new
14
18
  end
15
19
 
16
20
  def lograge_formatter
@@ -23,21 +27,76 @@ module BerkeleyLibrary
23
27
 
24
28
  { msg: message }
25
29
  end
30
+
31
+ def strip_ansi_escapes(message)
32
+ return unless message
33
+ return message.gsub(ANSI_7C1_RE, '') if message.is_a?(String)
34
+ return message.map { |v| strip_ansi_escapes(v) } if message.is_a?(Array)
35
+ return message.transform_values { |v| strip_ansi_escapes(v) } if message.is_a?(Hash)
36
+
37
+ message
38
+ end
26
39
  end
27
40
 
28
41
  # ------------------------------------------------------------
29
42
  # Private helper classes
30
43
 
44
+ module ErrorCauseSerializer
45
+ def serialize_exc(ex, serialized = Set.new)
46
+ super(ex).tap do |result|
47
+ next unless (cause = ex.cause)
48
+ next if (serialized << ex).include?(cause) # prevent circular references
49
+
50
+ result[:cause] = serialize_exc(cause, serialized)
51
+ end
52
+ end
53
+ end
54
+
55
+ private_constant :ErrorCauseSerializer
56
+
57
+ class Readable < Ougai::Formatters::Readable
58
+ include ErrorCauseSerializer
59
+
60
+ protected
61
+
62
+ def create_err_str(data)
63
+ return unless (err_hash = data.delete(:err))
64
+
65
+ format_err(err_hash)
66
+ end
67
+
68
+ private
69
+
70
+ def format_err(err_hash)
71
+ " #{err_hash[:name]} (#{err_hash[:message]}):".tap do |msg|
72
+ next unless (stack = err_hash[:stack])
73
+
74
+ msg << "\n"
75
+ msg << (' ' * @trace_indent)
76
+ msg << stack
77
+
78
+ next unless (cause_hash = err_hash[:cause])
79
+
80
+ msg << "\n Caused by: "
81
+ msg << format_err(cause_hash).strip
82
+ end
83
+ end
84
+
85
+ end
86
+ private_constant :Readable
87
+
31
88
  class Bunyan < Ougai::Formatters::Bunyan
32
89
  include Ougai::Logging::Severity
90
+ include ErrorCauseSerializer
33
91
 
34
92
  def _call(severity, time, progname, data)
35
93
  original_data = Formatters.ensure_hash(data)
94
+ decolorized_data = Formatters.strip_ansi_escapes(original_data)
36
95
 
37
96
  # Ougai::Formatters::Bunyan replaces the human-readable severity string
38
97
  # with a numeric level, so we add it here as a separate attribute
39
98
  severity = ensure_human_readable(severity)
40
- merged_data = { severity: severity }.merge(original_data)
99
+ merged_data = { severity: severity }.merge(decolorized_data)
41
100
  super(severity, time, progname, merged_data)
42
101
  end
43
102
 
@@ -7,7 +7,7 @@ module BerkeleyLibrary
7
7
  SUMMARY = 'Opinionated Ruby/Rails logging for UC Berkeley Library'.freeze
8
8
  DESCRIPTION = 'A gem providing shared logging code for UC Berkeley Library gems and Rails applications'.freeze
9
9
  LICENSE = 'MIT'.freeze
10
- VERSION = '0.2.0'.freeze
10
+ VERSION = '0.2.4'.freeze
11
11
  HOMEPAGE = 'https://github.com/BerkeleyLibrary/logging'.freeze
12
12
 
13
13
  private_class_method :new
@@ -34,6 +34,13 @@ module BerkeleyLibrary
34
34
  Configurator.configure(config)
35
35
  lograge = config.lograge
36
36
 
37
+ params = { authenticity_token: '8675309' }
38
+ request = OpenStruct.new(
39
+ origin: 'http://example.org:3000',
40
+ base_url: 'https://example.org:3443',
41
+ x_csrf_token: '5551212'
42
+ )
43
+
37
44
  request_headers = {
38
45
  'HTTP_REFERER' => 'value from HTTP_REFERER',
39
46
  'action_dispatch.request_id' => 'value from action_dispatch.request_id',
@@ -52,14 +59,25 @@ module BerkeleyLibrary
52
59
  forwarded: 'HTTP_FORWARDED'
53
60
  }
54
61
 
62
+ payload = {
63
+ params: params,
64
+ request: request,
65
+ headers: request_headers
66
+ }
67
+
55
68
  event = instance_double(ActiveSupport::Notifications::Event)
56
- allow(event).to receive(:payload).and_return({ headers: request_headers })
69
+ allow(event).to receive(:payload).and_return(payload)
57
70
 
58
71
  custom_options = lograge.custom_options
59
72
  data = custom_options.call(event)
60
73
  expect(data).to be_a(Hash)
61
- expect(data[:time]).to be_a(Time) # TODO: check for accuracy
74
+ expect(data[:time]).to be_a(Time)
75
+ expect(data[:time].to_i).to be_within(60).of(Time.now.to_i)
62
76
  expected_header_map.each { |xh, rh| expect(data[xh]).to eq(request_headers[rh]) }
77
+ expect(data[:authenticity_token]).to eq(params[:authenticity_token])
78
+ %i[origin base_url x_csrf_token].each do |attr|
79
+ expect(data[attr]).to eq(request.send(attr))
80
+ end
63
81
  end
64
82
 
65
83
  it 'formats Lograge data as a hash' do
@@ -1,27 +1,81 @@
1
1
  require 'rails_helper'
2
2
  require 'json'
3
+ require 'colorize'
3
4
  require 'berkeley_library/logging'
4
5
 
5
6
  module BerkeleyLibrary
6
7
  module Logging
7
8
  describe Formatters do
8
9
  describe :new_json_formatter do
9
- it 'supports tagged logging' do
10
- out = StringIO.new
11
- logger = Logger.new(out)
10
+ attr_reader :out, :logger
11
+
12
+ before(:each) do
13
+ @out = StringIO.new
14
+ @logger = Logger.new(out)
12
15
  logger.formatter = Formatters.new_json_formatter
16
+ end
13
17
 
14
- logger = ActiveSupport::TaggedLogging.new(logger)
18
+ it 'supports tagged logging' do
19
+ tagged_logger = ActiveSupport::TaggedLogging.new(logger)
15
20
 
16
21
  expected_tag = 'hello'
17
22
  expected_msg = 'this is a test'
18
23
 
19
- logger.tagged(expected_tag) { logger.info(expected_msg) }
24
+ tagged_logger.tagged(expected_tag) { tagged_logger.info(expected_msg) }
20
25
 
21
26
  logged_json = JSON.parse(out.string)
22
27
  expect(logged_json['msg']).to eq(expected_msg)
23
28
  expect(logged_json['tags']).to eq([expected_tag])
24
29
  end
30
+
31
+ it 'decolorizes ANSI-colored strings' do
32
+ colors = %i[red green yellow blue magenta cyan]
33
+ colorized_string = colors.map { |c| c.to_s.colorize(c) }.join(' ')
34
+ expect(colorized_string).to include("\u001b") # just to be sure
35
+
36
+ expected_string = colors.map(&:to_s).join(' ')
37
+
38
+ logger.info(colorized_string)
39
+ logged_json = JSON.parse(out.string)
40
+ msg = logged_json['msg']
41
+ expect(msg).not_to include("\u001b")
42
+ expect(msg).to eq(expected_string)
43
+ end
44
+
45
+ it 'decolorizes ANSI-colored strings in attached data' do
46
+ colors = %i[red green yellow blue magenta cyan]
47
+ colorized_string = colors.map { |c| c.to_s.colorize(c) }.join(' ')
48
+ expect(colorized_string).to include("\u001b") # just to be sure
49
+
50
+ expected_string = colors.map(&:to_s).join(' ')
51
+
52
+ data = {
53
+ the_string: colorized_string,
54
+ additional_data: {
55
+ not_a_string: 12,
56
+ another_string: colorized_string,
57
+ more_strings: [colorized_string, colorized_string]
58
+ }
59
+ }
60
+ logger.info('a colorized string', data)
61
+
62
+ logged_json = JSON.parse(out.string)
63
+ data = logged_json
64
+ expect(data['the_string']).to eq(expected_string)
65
+ additional_data = data['additional_data']
66
+ expect(additional_data['not_a_string']).to eq(12)
67
+ expect(additional_data['another_string']).to eq(expected_string)
68
+ expect(additional_data['more_strings']).to eq([expected_string, expected_string])
69
+ end
70
+
71
+ it 'removes ANSI formatting from ActiveRecord logs' do
72
+ original = " \e[1m\e[36mLendingItem Load (2.0ms)\e[0m \e[1m\e[34mSELECT \"lending_items\".* FROM \"lending_items\" WHERE \"lending_items\".\"directory\" = $1 LIMIT $2\e[0m [[\"directory\", \"b135297126_C068087930\"], [\"LIMIT\", 1]]"
73
+ expected = ' LendingItem Load (2.0ms) SELECT "lending_items".* FROM "lending_items" WHERE "lending_items"."directory" = $1 LIMIT $2 [["directory", "b135297126_C068087930"], ["LIMIT", 1]]'
74
+ logger.info(original)
75
+ logged_json = JSON.parse(out.string)
76
+ msg = logged_json['msg']
77
+ expect(msg).to eq(expected)
78
+ end
25
79
  end
26
80
 
27
81
  describe :ensure_hash do
@@ -14,6 +14,20 @@ module BerkeleyLibrary
14
14
  Rails.env = orig_rails_env
15
15
  end
16
16
 
17
+ describe :new_readable_logger do
18
+ it 'logs ANSI colors' do
19
+ out = StringIO.new
20
+
21
+ logger = Loggers.new_readable_logger(out)
22
+ colors = %i[red green yellow blue magenta cyan]
23
+ colorized_string = colors.map { |c| c.to_s.colorize(c) }.join(' ')
24
+ expect(colorized_string).to include("\u001b") # just to be sure
25
+
26
+ logger.info(colorized_string)
27
+ expect(out.string).to include(colorized_string)
28
+ end
29
+ end
30
+
17
31
  describe :new_json_logger do
18
32
  it 'supports tagged logging' do
19
33
  out = StringIO.new
@@ -1,27 +1,79 @@
1
1
  require 'standalone_helper'
2
2
  require 'json'
3
+ require 'colorize'
3
4
  require 'berkeley_library/logging'
4
5
 
5
6
  module BerkeleyLibrary
6
7
  module Logging
7
8
  describe Formatters do
8
9
  describe :new_json_formatter do
9
- it 'supports tagged logging' do
10
- out = StringIO.new
11
- logger = Logger.new(out)
10
+ attr_reader :out, :logger
11
+
12
+ before(:each) do
13
+ @out = StringIO.new
14
+ @logger = Logger.new(out)
12
15
  logger.formatter = Formatters.new_json_formatter
16
+ end
13
17
 
14
- logger = ActiveSupport::TaggedLogging.new(logger)
18
+ it 'supports tagged logging' do
19
+ tagged_logger = ActiveSupport::TaggedLogging.new(logger)
15
20
 
16
21
  expected_tag = 'hello'
17
22
  expected_msg = 'this is a test'
18
23
 
19
- logger.tagged(expected_tag) { logger.info(expected_msg) }
24
+ tagged_logger.tagged(expected_tag) { tagged_logger.info(expected_msg) }
20
25
 
21
26
  logged_json = JSON.parse(out.string)
22
27
  expect(logged_json['msg']).to eq(expected_msg)
23
28
  expect(logged_json['tags']).to eq([expected_tag])
24
29
  end
30
+
31
+ it 'decolorizes ANSI-colored strings' do
32
+ colors = %i[red green yellow blue magenta cyan]
33
+ colorized_string = colors.map { |c| c.to_s.colorize(c) }.join(' ')
34
+ expect(colorized_string).to include("\u001b") # just to be sure
35
+
36
+ expected_string = colors.map(&:to_s).join(' ')
37
+
38
+ logger.info(colorized_string)
39
+ logged_json = JSON.parse(out.string)
40
+ msg = logged_json['msg']
41
+ expect(msg).not_to include("\u001b")
42
+ expect(msg).to eq(expected_string)
43
+ end
44
+
45
+ it 'decolorizes ANSI-colored strings in attached data' do
46
+ colors = %i[red green yellow blue magenta cyan]
47
+ colorized_string = colors.map { |c| c.to_s.colorize(c) }.join(' ')
48
+ expect(colorized_string).to include("\u001b") # just to be sure
49
+
50
+ expected_string = colors.map(&:to_s).join(' ')
51
+
52
+ data = {
53
+ the_string: colorized_string,
54
+ additional_data: {
55
+ another_string: colorized_string,
56
+ more_strings: [colorized_string, colorized_string]
57
+ }
58
+ }
59
+ logger.info('a colorized string', data)
60
+
61
+ logged_json = JSON.parse(out.string)
62
+ data = logged_json
63
+ expect(data['the_string']).to eq(expected_string)
64
+ additional_data = data['additional_data']
65
+ expect(additional_data['another_string']).to eq(expected_string)
66
+ expect(additional_data['more_strings']).to eq([expected_string, expected_string])
67
+ end
68
+
69
+ it 'removes ANSI formatting from ActiveRecord logs' do
70
+ original = " \e[1m\e[36mLendingItem Load (2.0ms)\e[0m \e[1m\e[34mSELECT \"lending_items\".* FROM \"lending_items\" WHERE \"lending_items\".\"directory\" = $1 LIMIT $2\e[0m [[\"directory\", \"b135297126_C068087930\"], [\"LIMIT\", 1]]"
71
+ expected = ' LendingItem Load (2.0ms) SELECT "lending_items".* FROM "lending_items" WHERE "lending_items"."directory" = $1 LIMIT $2 [["directory", "b135297126_C068087930"], ["LIMIT", 1]]'
72
+ logger.info(original)
73
+ logged_json = JSON.parse(out.string)
74
+ msg = logged_json['msg']
75
+ expect(msg).to eq(expected)
76
+ end
25
77
  end
26
78
 
27
79
  describe :ensure_hash do
@@ -1,5 +1,6 @@
1
1
  require 'standalone_helper'
2
2
  require 'json'
3
+ require 'colorize'
3
4
 
4
5
  module BerkeleyLibrary
5
6
  module Logging
@@ -9,7 +10,13 @@ module BerkeleyLibrary
9
10
  # rubocop:disable Lint/ConstantDefinitionInBlock
10
11
  before(:each) do
11
12
  @out = StringIO.new
12
- class ::TestError < StandardError; end
13
+ class ::TestError < StandardError
14
+ attr_writer :cause
15
+
16
+ def cause
17
+ @cause || super
18
+ end
19
+ end
13
20
  end
14
21
  # rubocop:enable Lint/ConstantDefinitionInBlock
15
22
 
@@ -17,7 +24,36 @@ module BerkeleyLibrary
17
24
  Object.send(:remove_const, :TestError)
18
25
  end
19
26
 
27
+ describe :new_readable_logger do
28
+ it 'logs ANSI colors' do
29
+ logger = Loggers.new_readable_logger(out)
30
+ colors = %i[red green yellow blue magenta cyan]
31
+ colorized_string = colors.map { |c| c.to_s.colorize(c) }.join(' ')
32
+ expect(colorized_string).to include("\u001b") # just to be sure
33
+
34
+ logger.info(colorized_string)
35
+ expect(out.string).to include(colorized_string)
36
+ end
37
+ end
38
+
20
39
  describe :new_json_logger do
40
+
41
+ # TODO: rewrite this as a matcher
42
+ # rubocop:disable Metrics/AbcSize
43
+ def assert_serialized_error(err_json, err)
44
+ expect(err_json).to be_a(Hash)
45
+ expect(err_json['name']).to eq(TestError.name)
46
+ expect(err_json['message']).to eq(err.message)
47
+
48
+ err_stack = err_json['stack']
49
+ backtrace = err.backtrace
50
+ expect(backtrace).not_to be_nil # just to be sure
51
+ backtrace.each do |line|
52
+ expect(err_stack).to include(line)
53
+ end
54
+ end
55
+ # rubocop:enable Metrics/AbcSize
56
+
21
57
  it 'supports tagged logging' do
22
58
  logger = Loggers.new_json_logger(out)
23
59
  logger = ActiveSupport::TaggedLogging.new(logger)
@@ -38,25 +74,66 @@ module BerkeleyLibrary
38
74
  begin
39
75
  raise TestError, msg
40
76
  rescue TestError => e
41
- ex = e
42
77
  Loggers.new_json_logger(out).error(e)
43
78
  end
44
79
 
45
80
  logged_json = JSON.parse(out.string)
46
- expect(logged_json['msg']).to eq(msg)
81
+ expect(logged_json['msg']).to eq(e.message)
82
+ assert_serialized_error(logged_json['err'], e)
83
+ end
84
+
85
+ # rubocop:disable Naming/RescuedExceptionsVariableName
86
+ it 'includes the error cause' do
87
+ msg_outer = 'Help I am trapped in the outer part of a unit test'
88
+ msg_inner = 'Help I am trapped in the inner part of a unit test'
89
+
90
+ begin
91
+ raise TestError, msg_inner
92
+ rescue TestError => ex_inner
93
+ begin
94
+ raise TestError, msg_outer
95
+ rescue TestError => ex_outer
96
+ Loggers.new_json_logger(out).error(ex_outer)
97
+ end
98
+ end
99
+
100
+ expect(ex_outer.cause).to eq(ex_inner) # just to be sure
101
+
102
+ logged_json = JSON.parse(out.string)
103
+ expect(logged_json['msg']).to eq(ex_outer.message)
104
+
47
105
  err_json = logged_json['err']
48
- expect(err_json).to be_a(Hash)
49
- expect(err_json['name']).to eq(TestError.name)
50
- expect(err_json['message']).to eq(msg)
106
+ assert_serialized_error(err_json, ex_outer)
51
107
 
52
- err_stack = err_json['stack']
53
- backtrace = ex.backtrace
54
- expect(backtrace).not_to be_nil # just to be sure
55
- backtrace.each do |line|
56
- expect(err_stack).to include(line)
108
+ cause_json = err_json['cause']
109
+ expect(cause_json).not_to be_nil
110
+ assert_serialized_error(cause_json, ex_inner)
111
+ end
112
+ end
113
+ # rubocop:enable Naming/RescuedExceptionsVariableName
114
+
115
+ # rubocop:disable Naming/RescuedExceptionsVariableName
116
+ it 'handles pathological circular references' do
117
+ msg_outer = 'Help I am trapped in the outer part of a unit test'
118
+ msg_inner = 'Help I am trapped in the inner part of a unit test'
119
+
120
+ begin
121
+ raise TestError, msg_inner
122
+ rescue TestError => ex_inner
123
+ begin
124
+ raise TestError, msg_outer
125
+ rescue TestError => ex_outer
126
+ ex_inner.cause = ex_outer
57
127
  end
58
128
  end
129
+
130
+ begin
131
+ Loggers.new_json_logger(out).error(ex_outer)
132
+ rescue SystemStackError => e
133
+ RSpec::Expectations.fail_with("Expected no SystemStackError, but got #{e}: #{e.backtrace[0]}")
134
+ end
59
135
  end
136
+ # rubocop:enable Naming/RescuedExceptionsVariableName
60
137
 
61
138
  describe :default_logger do
62
139
  it 'returns a readable $stdout logger' do
@@ -132,7 +209,7 @@ module BerkeleyLibrary
132
209
  end
133
210
  end
134
211
 
135
- it 'logs an error with cause and backtrace' do
212
+ it 'logs an error with backtrace' do
136
213
  msg_txt = 'message text'
137
214
  ex_msg = 'Help I am trapped in a unit test'
138
215
 
@@ -154,6 +231,37 @@ module BerkeleyLibrary
154
231
  end
155
232
  end
156
233
 
234
+ # rubocop:disable Naming/RescuedExceptionsVariableName
235
+ it 'includes the error cause' do
236
+ msg_outer = 'Help I am trapped in the outer part of a unit test'
237
+ msg_inner = 'Help I am trapped in the inner part of a unit test'
238
+
239
+ begin
240
+ raise TestError, msg_inner
241
+ rescue TestError => ex_inner
242
+ begin
243
+ raise TestError, msg_outer
244
+ rescue TestError => ex_outer
245
+ Loggers.new_readable_logger(out).error(ex_outer)
246
+ end
247
+ end
248
+
249
+ expect(ex_outer.cause).to eq(ex_inner) # just to be sure
250
+
251
+ logged_txt = out.string
252
+ [ex_inner, ex_outer].each do |ex|
253
+ msg = ex.message
254
+ expect(logged_txt).to include(msg)
255
+
256
+ backtrace = ex.backtrace
257
+ expect(backtrace).not_to be_nil # just to be sure
258
+ backtrace.each do |line|
259
+ expect(logged_txt).to include(line)
260
+ end
261
+ end
262
+ end
263
+ # rubocop:enable Naming/RescuedExceptionsVariableName
264
+
157
265
  end
158
266
 
159
267
  describe 'messages with data and no text' do
@@ -274,5 +382,6 @@ module BerkeleyLibrary
274
382
  end
275
383
  end
276
384
  end
385
+
277
386
  end
278
387
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: berkeley_library-logging
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Moles
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-19 00:00:00.000000000 Z
11
+ date: 2021-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: colorize
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.8.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.8.1
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: lograge
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -108,20 +122,6 @@ dependencies:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
124
  version: '1.0'
111
- - !ruby/object:Gem::Dependency
112
- name: colorize
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '0.8'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '0.8'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: dotenv
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -275,6 +275,7 @@ executables: []
275
275
  extensions: []
276
276
  extra_rdoc_files: []
277
277
  files:
278
+ - ".github/workflows/build.yml"
278
279
  - ".gitignore"
279
280
  - ".idea/inspectionProfiles/Project_Default.xml"
280
281
  - ".idea/logging.iml"
@@ -283,14 +284,13 @@ files:
283
284
  - ".rubocop.yml"
284
285
  - ".ruby-version"
285
286
  - ".simplecov"
286
- - ".travis.yml"
287
287
  - CHANGES.md
288
288
  - Dockerfile
289
289
  - Gemfile
290
- - Jenkinsfile
291
290
  - LICENSE.md
292
291
  - README.md
293
292
  - Rakefile
293
+ - artifacts/.keep
294
294
  - berkeley_library-logging.gemspec
295
295
  - docker-compose.yml
296
296
  - lib/berkeley_library/logging.rb
data/.travis.yml DELETED
@@ -1,9 +0,0 @@
1
- language: ruby
2
-
3
- os:
4
- - linux
5
- - osx
6
-
7
- rvm:
8
- - 2.7
9
- - ruby-head
data/Jenkinsfile DELETED
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env groovy
2
-
3
- dockerComposePipeline(
4
- commands: [
5
- 'bundle exec rake coverage',
6
- 'bundle exec rake rubocop',
7
- 'bundle exec rake bundle:audit',
8
- 'bundle exec rake gem'
9
- ],
10
- artifacts: [
11
- junit: 'artifacts/rspec/**/*.xml',
12
- html : [
13
- 'Code Coverage': 'artifacts/rcov',
14
- 'RuboCop' : 'artifacts/rubocop'
15
- ],
16
- raw : [
17
- 'artifacts/**/*.gem',
18
- 'artifacts/**/*.json'
19
- ]
20
- ]
21
- )