g5-logger 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 029c522b3fe68fc729373e20db3b0af62d86c5ac
4
+ data.tar.gz: 9b76ed4782d5b609a6b4c252d0960ed1b26a059f
5
+ SHA512:
6
+ metadata.gz: 16bbc49d56331e18980a113600f2609c81f2d18cc401466b7b486d46d51543a986d99b8264bb7b027529520c879c09c6b2c15a45c06ea819493606b492047c7a
7
+ data.tar.gz: 090375bb4aefe62dfc7a7a70b203ca5305316e95cb5980b957c0b55edab960fe7545c6db2a47bef8765c99f0f862f3abc3e6dff1cd2ca3ad85df813eca6bb8dd
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+
16
+ /.idea/
17
+
18
+ /g5-logger*.gem
@@ -0,0 +1 @@
1
+ 2.1.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in g5-logger.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Perry Hertler
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # G5::Logger
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'g5-logger'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install g5-logger
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/g5-logger/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'g5/logger/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "g5-logger"
8
+ spec.version = G5::Logger::VERSION
9
+ spec.authors = ["Perry Hertler"]
10
+ spec.email = ["perry@hertler.org"]
11
+ spec.summary = %q{Client gem that logs to the G5-logging-service.}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.7"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency 'rspec', '~> 3.0'
23
+ spec.add_development_dependency 'rspec-its', '~> 1.0'
24
+ spec.add_development_dependency 'pry-nav', '~> 0.2'
25
+
26
+ spec.add_runtime_dependency 'typhoeus', '~> 0.6'
27
+ spec.add_runtime_dependency 'activesupport', '~> 4.1'
28
+ end
@@ -0,0 +1,18 @@
1
+ require 'g5/logger/version'
2
+ require 'g5/logger/log'
3
+ require 'active_support/core_ext'
4
+
5
+ module G5
6
+ module Logger
7
+ KEY_VALUE_FORMAT = 'key_value'
8
+ JSON_FORMAT = 'json'
9
+ # override in your Rails.root/config/initializers
10
+ Config = {
11
+ logger: 'REQUIRED', #usually Rails.logger
12
+ source_app_name: 'REQUIRED - this is the name of the app using it',
13
+ format: JSON_FORMAT, # json or key_value
14
+ redact_keys: [/credit/, /password/, /cvv/],
15
+ redact_value: '***'
16
+ }
17
+ end
18
+ end
@@ -0,0 +1,74 @@
1
+ module G5
2
+ module Logger
3
+ class Log
4
+ Levels = %w(debug info warn error fatal unknown)
5
+
6
+ class << self
7
+ Levels.each do |name|
8
+ define_method(name) do |attributes|
9
+ log({level: name}.merge(attributes))
10
+ end
11
+ end
12
+
13
+ def log(attributes)
14
+ default_merge = {source_app_name: Config[:source_app_name]}.merge(attributes)
15
+ log_level = level(default_merge.delete(:level))
16
+ Config[:logger].send(log_level, log_entry(default_merge))
17
+ end
18
+
19
+ def level(level)
20
+ Levels.include?(level) ? level : :info
21
+ end
22
+
23
+ def log_entry(hash)
24
+ scrubbed = redact hash.clone
25
+ if G5::Logger::KEY_VALUE_FORMAT== G5::Logger::Config[:format]
26
+ scrubbed.keys.collect { |key| "#{key}=\"#{hash[key]}\"" }.join(", ")
27
+ else
28
+ scrubbed.to_json
29
+ end
30
+ end
31
+
32
+ def log_json_req_resp(request, response, options={})
33
+ options = options.merge(
34
+ status: response.try(:code),
35
+ request: request,
36
+ response: response.try(:body))
37
+
38
+ send(log_method(response.code), options)
39
+ end
40
+
41
+ def log_method(code)
42
+ error = code > 299 rescue false
43
+ error ? :error : :info
44
+ end
45
+
46
+ def redact(hash)
47
+ hash.keys.each do |key|
48
+ redact(hash[key]) if hash[key].kind_of?(Hash)
49
+ redact_array(hash[key]) if hash[key].kind_of?(Array)
50
+ hash[key] = Config[:redact_value] if redactable?(key)
51
+ end
52
+ hash
53
+ end
54
+
55
+ def redactable?(value)
56
+ return false if value.blank? || ![String, Symbol].include?(value.class)
57
+ !!Config[:redact_keys].detect { |rk|
58
+ if rk.class == String
59
+ rk == value
60
+ else
61
+ value.match(rk)
62
+ end
63
+ }
64
+ end
65
+
66
+ def redact_array(array)
67
+ array.each do |array_val|
68
+ redact array_val if array_val.kind_of?(Hash)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,5 @@
1
+ module G5
2
+ module Logger
3
+ VERSION = "0.0.5"
4
+ end
5
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ describe G5::Logger::Log do
4
+ context 'json' do
5
+ before { G5::Logger::Config[:format] = G5::Logger::JSON_FORMAT }
6
+
7
+ describe 'redact sensitive data' do
8
+ before do
9
+ G5::Logger::Config[:redact_keys] << 'redactme'
10
+ end
11
+ let(:request) { {'credit_card' => '4344122144442222', foo: 'bar', parent: {cvv: '323', jimmy: 'joe'}, 'array' => [{'my_password' => 'jimpass', 'redactme' => 'secretval'}]} }
12
+ let(:body) { {credit_exp_date: '10/2015', whatever: 'brah'} }
13
+ let(:response) { double(:response, code: 201, body: body) }
14
+ let(:redact_value) {G5::Logger::Config[:redact_value]}
15
+
16
+ subject do
17
+ G5::Logger::Log.log_json_req_resp(request, response, {foo: 'bar', 'j_cvv' => 343})
18
+ indifferent_hash_from_json TestLogger.last_payload
19
+ end
20
+
21
+ it { is_expected.to eq({"source_app_name" => "test", "foo" => "bar", "j_cvv" => redact_value, "status" => 201,
22
+ "request" => {"credit_card" => redact_value, "foo" => "bar",
23
+ "parent" => {"cvv" => redact_value, "jimmy" => "joe"},
24
+ "array" => [{"my_password" => redact_value, "redactme" => redact_value}]},
25
+ "response" => {"credit_exp_date" => redact_value, "whatever" => "brah"}}) }
26
+ end
27
+
28
+ describe :log_json_req_resp do
29
+ let(:request) { {payload: 'foo'} }
30
+ let(:code) { 201 }
31
+ let(:body) { {model: {id: 1, name: 'yeah'}} }
32
+ let(:response) { double(:response, code: code, body: body) }
33
+ subject do
34
+ G5::Logger::Log.log_json_req_resp(request, response, {foo: 'bar'})
35
+ indifferent_hash_from_json TestLogger.last_payload
36
+ end
37
+
38
+ its([:source_app_name]) { is_expected.to eq('test') }
39
+ its([:foo]) { is_expected.to eq('bar') }
40
+ its([:status]) { is_expected.to eq(201) }
41
+ its([:response]) { is_expected.to eq({"model" => {"id" => 1, "name" => "yeah"}}) }
42
+ its([:request]) { is_expected.to eq({"payload" => "foo"}) }
43
+ end
44
+ end
45
+
46
+ context 'key_value' do
47
+ before { G5::Logger::Config[:format] = G5::Logger::KEY_VALUE_FORMAT }
48
+
49
+ describe 'levels' do
50
+ G5::Logger::Log::Levels.each do |method|
51
+ it "delegates #{method} to log method" do
52
+ expect(TestLogger).to receive(method).with("source_app_name=\"test\", foo=\"bar\"")
53
+ G5::Logger::Log.send(method, foo: 'bar')
54
+ end
55
+ end
56
+ end
57
+
58
+ describe :log do
59
+ let(:params) do
60
+ {source_name: 'test',
61
+ level: 3,
62
+ external_parent_id: 33,
63
+ external_parent_source_name: 'g5-jobs',
64
+ title: 'attachments title',
65
+ request: '<request></request>',
66
+ response: {foo: 'bar'}.to_json
67
+ }
68
+ end
69
+ subject do
70
+ G5::Logger::Log.log(params)
71
+ TestLogger.last_payload
72
+ end
73
+ it { is_expected.to eq("source_app_name=\"test\", source_name=\"test\", external_parent_id=\"33\", external_parent_source_name=\"g5-jobs\", title=\"attachments title\", request=\"<request></request>\", response=\"{\"foo\":\"bar\"}\"") }
74
+ end
75
+
76
+ describe :log_json_req_resp do
77
+ let(:request) { 'req' }
78
+ let(:code) { 201 }
79
+ let(:body) { 'body' }
80
+ let(:response) { double(:response, code: code, body: body) }
81
+ subject do
82
+ G5::Logger::Log.log_json_req_resp(request, response, {foo: 'bar'})
83
+ TestLogger.last_payload
84
+ end
85
+ it { is_expected.to eq("source_app_name=\"test\", foo=\"bar\", status=\"201\", request=\"req\", response=\"body\"") }
86
+ end
87
+
88
+ describe :log_method do
89
+ [{code: 201, expected: :info}, {code: 300, expected: :error}, {code: nil, expected: :info}].each do |test_hash|
90
+ it "uses #{test_hash[:expected]} when code is #{test_hash[:code]}" do
91
+ expect(G5::Logger::Log.log_method(test_hash[:code])).to eq(test_hash[:expected])
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,18 @@
1
+ require 'g5/logger'
2
+ require 'pry'
3
+ require 'rspec/its'
4
+
5
+ ROOTPATH = File.expand_path('..', __FILE__)
6
+ Dir[File.join(ROOTPATH, 'support/**/*.rb')].each { |support| require support }
7
+ G5::Logger::Config[:logger] = TestLogger
8
+ G5::Logger::Config[:source_app_name] = 'test'
9
+
10
+ RSpec.configure do |config|
11
+ config.run_all_when_everything_filtered = true
12
+ config.filter_run :focus
13
+ end
14
+
15
+ def indifferent_hash_from_json(json)
16
+ ActiveSupport::HashWithIndifferentAccess.new(JSON.parse(json))
17
+ end
18
+
@@ -0,0 +1,22 @@
1
+ class TestLogger
2
+ Levels = [
3
+ :debug, :info, :warn, :error, :fatal, :unknown
4
+ ]
5
+
6
+ class << self
7
+ Levels.each do |name|
8
+ define_method(name) do |payload|
9
+ @@last_payload = payload
10
+ @@last_level = name
11
+ end
12
+ end
13
+
14
+ def last_payload
15
+ @@last_payload
16
+ end
17
+
18
+ def last_level
19
+ @@last_level
20
+ end
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: g5-logger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Perry Hertler
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-its
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-nav
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: typhoeus
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.6'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.6'
97
+ - !ruby/object:Gem::Dependency
98
+ name: activesupport
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '4.1'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '4.1'
111
+ description:
112
+ email:
113
+ - perry@hertler.org
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".ruby-version"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - g5-logger.gemspec
125
+ - lib/g5/logger.rb
126
+ - lib/g5/logger/log.rb
127
+ - lib/g5/logger/version.rb
128
+ - spec/g5/logger/log_spec.rb
129
+ - spec/spec_helper.rb
130
+ - spec/support/test_logger.rb
131
+ homepage: ''
132
+ licenses:
133
+ - MIT
134
+ metadata: {}
135
+ post_install_message:
136
+ rdoc_options: []
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ requirements: []
150
+ rubyforge_project:
151
+ rubygems_version: 2.2.2
152
+ signing_key:
153
+ specification_version: 4
154
+ summary: Client gem that logs to the G5-logging-service.
155
+ test_files:
156
+ - spec/g5/logger/log_spec.rb
157
+ - spec/spec_helper.rb
158
+ - spec/support/test_logger.rb