logasm 0.5.2 → 0.7.0

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
  SHA1:
3
- metadata.gz: a9ade685a2af887a257340ed2dab29d09abceb8a
4
- data.tar.gz: 1b5671acbe54ce055156a496a481ce524270a3b1
3
+ metadata.gz: 56e3d511b8873dffb529444790ec2c111f2e06ce
4
+ data.tar.gz: 26ae968b0af65670a1fe9db8801b69748f6d6c96
5
5
  SHA512:
6
- metadata.gz: d5a206ab30b603af225468e52195c9ef3e87b42d2bf71cd7794ebe98b3eabe952fe9df666d1a1618915a379e7ac0559fba7e5543d6dbf5d1de1574157fb3ce83
7
- data.tar.gz: b363d87991efde13a6ea82b82e673536aa83179ad1f103f1d8098fe00222bf2b9e321b5a9bc59cf3ce0b9fbf451ec53eeb11c5ebfd8b3f11c21265d9a363d88e
6
+ metadata.gz: f71ce0380318847e9fe3eafd4cd4f9ab26b4175e2cd796dd575d9cf2f4192ca298d0b801b5e9464ccdc649c7dc0b0071b4f29fce2514bd099f8342806123de89
7
+ data.tar.gz: 38cf576d4f1e8f2961cbf8416373de2a06f6960bb83e13dc692940a56cd1554ca5537eac9be9650aba935030ea0dbd4b83d4e396f826dfac1178d6205b9303ef
data/README.md CHANGED
@@ -108,7 +108,7 @@ Received request {"info":{"phone":"************"}}
108
108
 
109
109
  Masks all the fields except those whitelisted in the configuration using [JSON Pointer](https://tools.ietf.org/html/rfc6901).
110
110
  Only simple values(`string`, `number`, `boolean`) can be whitelisted.
111
- Whitelisting array elements can be done using wildcard symbol `~`.
111
+ Whitelisting array and hash elements can be done using wildcard symbol `~`.
112
112
 
113
113
  #### Configuration
114
114
 
@@ -0,0 +1,43 @@
1
+ class Logasm
2
+ module Adapters
3
+ class StdoutJsonAdapter
4
+ def initialize(level, service_name, *)
5
+ @level = level
6
+ @service_name = service_name
7
+ end
8
+
9
+ def log(level, metadata = {})
10
+ if meets_threshold?(level)
11
+ message = Utils.build_event(metadata, level, @service_name)
12
+ STDOUT.puts(JSON.dump(message))
13
+ end
14
+ end
15
+
16
+ def debug?
17
+ meets_threshold?(:debug)
18
+ end
19
+
20
+ def info?
21
+ meets_threshold?(:info)
22
+ end
23
+
24
+ def warn?
25
+ meets_threshold?(:warn)
26
+ end
27
+
28
+ def error?
29
+ meets_threshold?(:error)
30
+ end
31
+
32
+ def fatal?
33
+ meets_threshold?(:fatal)
34
+ end
35
+
36
+ private
37
+
38
+ def meets_threshold?(level)
39
+ LOG_LEVELS.index(level.to_s) >= @level
40
+ end
41
+ end
42
+ end
43
+ end
@@ -3,8 +3,24 @@ class Logasm
3
3
  LOG_LEVELS = %w(debug info warn error fatal unknown).freeze
4
4
 
5
5
  def self.get(type, service_name, arguments)
6
- require_relative "adapters/#{type.to_s}_adapter"
7
- adapter = const_get(Inflecto.camelize(type.to_s) + 'Adapter')
6
+ adapter =
7
+ if type == 'rabbitmq'
8
+ require_relative 'adapters/rabbitmq_adapter'
9
+ RabbitmqAdapter
10
+ elsif type == 'logstash'
11
+ require_relative 'adapters/logstash_adapter'
12
+ LogstashAdapter
13
+ elsif type == 'stdout'
14
+ if arguments.fetch(:json, false)
15
+ require_relative 'adapters/stdout_json_adapter'
16
+ StdoutJsonAdapter
17
+ else
18
+ require_relative 'adapters/stdout_adapter'
19
+ StdoutAdapter
20
+ end
21
+ else
22
+ raise "Unsupported logger: #{type}"
23
+ end
8
24
  level = LOG_LEVELS.index(arguments.fetch(:level, 'debug'))
9
25
  adapter.new(level, service_name, arguments)
10
26
  end
@@ -4,6 +4,7 @@ class Logasm
4
4
 
5
5
  DEFAULT_ACTION = 'exclude'
6
6
  MASK_SYMBOL = '*'
7
+ MASKED_VALUE = MASK_SYMBOL * 5
7
8
 
8
9
  class UnsupportedActionException < Exception
9
10
  end
@@ -48,20 +49,12 @@ class Logasm
48
49
  end
49
50
 
50
51
  def mask_field(data, key, val)
51
- if val.is_a?(Hash) || val.is_a?(Array) || is_boolean?(val)
52
- data.merge(key => MASK_SYMBOL)
53
- else
54
- data.merge(key => MASK_SYMBOL * val.to_s.length)
55
- end
52
+ data.merge(key => MASKED_VALUE)
56
53
  end
57
54
 
58
55
  def exclude_field(data, *)
59
56
  data
60
57
  end
61
-
62
- def is_boolean?(val)
63
- val.is_a?(TrueClass) || val.is_a?(FalseClass)
64
- end
65
58
  end
66
59
  end
67
60
  end
@@ -4,6 +4,7 @@ class Logasm
4
4
 
5
5
  DEFAULT_WHITELIST = %w(/id /message /correlation_id /queue)
6
6
  MASK_SYMBOL = '*'
7
+ MASKED_VALUE = MASK_SYMBOL * 5
7
8
  WILDCARD = '~'
8
9
 
9
10
  class InvalidPointerFormatException < Exception
@@ -85,8 +86,14 @@ class Logasm
85
86
  end
86
87
 
87
88
  def process_hash(parent_pointer, hash)
89
+ create_child_pointer =
90
+ if @wildcards["#{parent_pointer}/~"]
91
+ lambda { |_| "#{parent_pointer}/~" }
92
+ else
93
+ lambda { |key| "#{parent_pointer}/#{key}" }
94
+ end
88
95
  hash.inject({}) do |mem, (key, value)|
89
- pointer = "#{parent_pointer}/#{key}"
96
+ pointer = create_child_pointer.call(key)
90
97
  processed_value = process_data(pointer, value)
91
98
  mem.merge(key => processed_value)
92
99
  end
@@ -110,21 +117,9 @@ class Logasm
110
117
  if @fields_to_include[parent_pointer]
111
118
  value
112
119
  else
113
- mask value
120
+ MASKED_VALUE
114
121
  end
115
122
  end
116
-
117
- def mask(value)
118
- if value && value.respond_to?(:to_s) && !is_boolean?(value)
119
- MASK_SYMBOL * value.to_s.length
120
- else
121
- MASK_SYMBOL
122
- end
123
- end
124
-
125
- def is_boolean?(value)
126
- value.is_a?(TrueClass) || value.is_a?(FalseClass)
127
- end
128
123
  end
129
124
  end
130
125
  end
data/logasm.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |gem|
6
6
  gem.name = "logasm"
7
- gem.version = '0.5.2'
7
+ gem.version = '0.7.0'
8
8
  gem.authors = ["Salemove"]
9
9
  gem.email = ["support@salemove.com"]
10
10
  gem.description = %q{It's logasmic}
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ require_relative '../../lib/logasm/adapters/stdout_json_adapter'
3
+
4
+ describe Logasm::Adapters::StdoutJsonAdapter do
5
+ let(:debug_level_code) { 0 }
6
+ let(:debug_level) { Logasm::Adapters::LOG_LEVELS[debug_level_code] }
7
+ let(:info_level_code) { 1 }
8
+ let(:info_level) { Logasm::Adapters::LOG_LEVELS[info_level_code] }
9
+
10
+ describe '#log' do
11
+ context 'when below threshold' do
12
+ let(:adapter) { described_class.new(debug_level_code, service_name) }
13
+ let(:metadata) { {x: 'y'} }
14
+ let(:event) { {a: 'b', x: 'y'} }
15
+ let(:serialized_event) { JSON.dump(event) }
16
+ let(:service_name) { 'my-service' }
17
+
18
+ before do
19
+ allow(Logasm::Utils).to receive(:build_event)
20
+ .with(metadata, info_level, service_name)
21
+ .and_return(event)
22
+ end
23
+
24
+ it 'sends serialized event to STDOUT' do
25
+ expect(STDOUT).to receive(:puts).with(serialized_event)
26
+ adapter.log(info_level, metadata)
27
+ end
28
+ end
29
+
30
+ context 'when above threshold' do
31
+ let(:adapter) { described_class.new(info_level_code, service_name) }
32
+ let(:metadata) { {x: 'y'} }
33
+ let(:service_name) { 'my-service' }
34
+
35
+ it 'does not log the event' do
36
+ expect(STDOUT).to_not receive(:puts)
37
+ adapter.log(debug_level, metadata)
38
+ end
39
+ end
40
+ end
41
+ end
data/spec/logasm_spec.rb CHANGED
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Logasm do
4
4
  describe '.build' do
5
- it 'creates file logger' do
5
+ it 'creates stdout logger' do
6
6
  expect(described_class).to receive(:new) do |adapters|
7
7
  expect(adapters.count).to be(1)
8
8
  expect(adapters.first).to be_a(described_class::Adapters::StdoutAdapter)
@@ -11,6 +11,15 @@ describe Logasm do
11
11
  described_class.build('test_service', stdout: nil)
12
12
  end
13
13
 
14
+ it 'creates stdout json logger' do
15
+ expect(described_class).to receive(:new) do |adapters|
16
+ expect(adapters.count).to be(1)
17
+ expect(adapters.first).to be_a(described_class::Adapters::StdoutJsonAdapter)
18
+ end
19
+
20
+ described_class.build('test_service', stdout: {json: true})
21
+ end
22
+
14
23
  it 'creates logstash logger' do
15
24
  expect(described_class).to receive(:new) do |adapters|
16
25
  expect(adapters.count).to be(1)
@@ -56,18 +56,18 @@ describe Logasm::Preprocessors::Blacklist do
56
56
  let(:action) { 'mask' }
57
57
 
58
58
  it 'masks nested field' do
59
- expect(processed_data).to include_at_depth({field: '******'}, 1)
59
+ expect(processed_data).to include_at_depth({field: '*****'}, 1)
60
60
  end
61
61
 
62
62
  it 'masks nested in array field' do
63
- expect(processed_data[:array]).to include({field: '******'})
63
+ expect(processed_data[:array]).to include({field: '*****'})
64
64
  end
65
65
 
66
66
  context 'when field is string' do
67
67
  let(:value) { 'secret' }
68
68
 
69
69
  it 'masks value with asterisks' do
70
- expect(processed_data).to include(field: '******')
70
+ expect(processed_data).to include(field: '*****')
71
71
  end
72
72
  end
73
73
 
@@ -75,31 +75,31 @@ describe Logasm::Preprocessors::Blacklist do
75
75
  let(:value) { 42 }
76
76
 
77
77
  it 'masks number value' do
78
- expect(processed_data).to include(field: '**')
78
+ expect(processed_data).to include(field: '*****')
79
79
  end
80
80
  end
81
81
 
82
82
  context 'when field is boolean' do
83
83
  let(:value) { true }
84
84
 
85
- it 'masks value with one asterisk' do
86
- expect(processed_data).to include(field: '*')
85
+ it 'masks value with asterisks' do
86
+ expect(processed_data).to include(field: '*****')
87
87
  end
88
88
  end
89
89
 
90
90
  context 'when field is array' do
91
91
  let(:value) { [1,2,3,4] }
92
92
 
93
- it 'masks value with one asterisk' do
94
- expect(processed_data).to include(field: '*')
93
+ it 'masks value with asterisks' do
94
+ expect(processed_data).to include(field: '*****')
95
95
  end
96
96
  end
97
97
 
98
98
  context 'when field is hash' do
99
99
  let(:value) { {data: {}} }
100
100
 
101
- it 'masks value with one asterisk' do
102
- expect(processed_data).to include(field: '*')
101
+ it 'masks value with asterisks' do
102
+ expect(processed_data).to include(field: '*****')
103
103
  end
104
104
  end
105
105
 
@@ -108,7 +108,7 @@ describe Logasm::Preprocessors::Blacklist do
108
108
  let(:data) { data_with_nested_field({field: 'secret'}, depth) }
109
109
 
110
110
  it 'masks deeply nested field' do
111
- expect(processed_data).to include_at_depth({field: '******'}, depth)
111
+ expect(processed_data).to include_at_depth({field: '*****'}, depth)
112
112
  end
113
113
  end
114
114
  end
@@ -16,11 +16,11 @@ describe Logasm::Preprocessors::Whitelist do
16
16
 
17
17
  it 'masks all non-whitelisted fields' do
18
18
  expect(processed_data).to eq({
19
- field: '******',
19
+ field: '*****',
20
20
  data: {
21
- field: '******'
21
+ field: '*****'
22
22
  },
23
- array: [{field: '******'}]
23
+ array: [{field: '*****'}]
24
24
  })
25
25
  end
26
26
 
@@ -39,9 +39,9 @@ describe Logasm::Preprocessors::Whitelist do
39
39
  expect(processed_data).to eq({
40
40
  field: 'secret',
41
41
  data: {
42
- field: '******'
42
+ field: '*****'
43
43
  },
44
- array: [{field: '******'}]
44
+ array: [{field: '*****'}]
45
45
  })
46
46
  end
47
47
  end
@@ -51,11 +51,11 @@ describe Logasm::Preprocessors::Whitelist do
51
51
 
52
52
  it 'includes nested field' do
53
53
  expect(processed_data).to eq({
54
- field: '******',
54
+ field: '*****',
55
55
  data: {
56
56
  field: 'secret'
57
57
  },
58
- array: [{field: '******'}]
58
+ array: [{field: '*****'}]
59
59
  })
60
60
  end
61
61
  end
@@ -65,15 +65,29 @@ describe Logasm::Preprocessors::Whitelist do
65
65
 
66
66
  it 'includes array element' do
67
67
  expect(processed_data).to eq({
68
- field: '******',
68
+ field: '*****',
69
69
  data: {
70
- field: '******'
70
+ field: '*****'
71
71
  },
72
72
  array: [{field: 'secret'}]
73
73
  })
74
74
  end
75
75
  end
76
76
 
77
+ context 'with whitelisted hash' do
78
+ it 'includes all whitelisted hash elements' do
79
+ source = {foo: {bar: 'baz'}}
80
+ target = {foo: {bar: 'baz'}}
81
+ expect(process(['/foo/~'], source)).to eq(target)
82
+ end
83
+
84
+ it 'does not include nested elements' do
85
+ source = {foo: {bar: {baz: 'asd'}}}
86
+ target = {foo: {bar: {baz: '***'}}}
87
+ expect(process(['/foo/~'], source)).to eq(target)
88
+ end
89
+ end
90
+
77
91
  context 'with whitelisted array elements field with wildcard' do
78
92
  let(:data) {{
79
93
  array: [{field: 'data1', secret: 'secret1'}, {field: 'data2', secret: 'secret2'}]
@@ -82,7 +96,7 @@ describe Logasm::Preprocessors::Whitelist do
82
96
 
83
97
  it 'includes array elements field' do
84
98
  expect(processed_data).to include(
85
- array: [{field: 'data1', secret: '*******'}, {field: 'data2', secret: '*******'}]
99
+ array: [{field: 'data1', secret: '*****'}, {field: 'data2', secret: '*****'}]
86
100
  )
87
101
  end
88
102
  end
@@ -102,7 +116,7 @@ describe Logasm::Preprocessors::Whitelist do
102
116
  let(:pointers) { ['/array/0'] }
103
117
 
104
118
  it 'masks array element' do
105
- expect(processed_data).to include(array: [{field: '******'}])
119
+ expect(processed_data).to include(array: [{field: '*****'}])
106
120
  end
107
121
  end
108
122
 
@@ -110,7 +124,7 @@ describe Logasm::Preprocessors::Whitelist do
110
124
  let(:pointers) { ['/array'] }
111
125
 
112
126
  it 'masks array' do
113
- expect(processed_data).to include(array: [{field: '******'}])
127
+ expect(processed_data).to include(array: [{field: '*****'}])
114
128
  end
115
129
  end
116
130
 
@@ -118,15 +132,15 @@ describe Logasm::Preprocessors::Whitelist do
118
132
  let(:pointers) { ['/data'] }
119
133
 
120
134
  it 'masks hash' do
121
- expect(processed_data).to include(data: {field: '******'})
135
+ expect(processed_data).to include(data: {field: '*****'})
122
136
  end
123
137
  end
124
138
 
125
139
  context 'when boolean present' do
126
140
  let(:data) { {bool: true} }
127
141
 
128
- it 'masks it with single asteriks' do
129
- expect(processed_data).to eq(bool: '*')
142
+ it 'masks it with asteriks' do
143
+ expect(processed_data).to eq(bool: '*****')
130
144
  end
131
145
  end
132
146
 
@@ -173,7 +187,7 @@ describe Logasm::Preprocessors::Whitelist do
173
187
  expect(processed_data).to include('field_with_~'=> 'secret')
174
188
  end
175
189
  end
176
-
190
+
177
191
  context 'when field has tilde and 1' do
178
192
  let(:data) {{
179
193
  'field_with_~1' => 'secret'
@@ -184,4 +198,8 @@ describe Logasm::Preprocessors::Whitelist do
184
198
  expect(processed_data).to include('field_with_~1'=> 'secret')
185
199
  end
186
200
  end
201
+
202
+ def process(pointers, data)
203
+ described_class.new(pointers: pointers).process(data)
204
+ end
187
205
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logasm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Salemove
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-01 00:00:00.000000000 Z
11
+ date: 2017-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inflecto
@@ -86,6 +86,7 @@ files:
86
86
  - lib/logasm/adapters/logstash_adapter/formatter.rb
87
87
  - lib/logasm/adapters/rabbitmq_adapter.rb
88
88
  - lib/logasm/adapters/stdout_adapter.rb
89
+ - lib/logasm/adapters/stdout_json_adapter.rb
89
90
  - lib/logasm/null_logger.rb
90
91
  - lib/logasm/preprocessors.rb
91
92
  - lib/logasm/preprocessors/blacklist.rb
@@ -96,6 +97,7 @@ files:
96
97
  - spec/adapters/logstash_adapter_spec.rb
97
98
  - spec/adapters/rabbitmq_adapter_spec.rb
98
99
  - spec/adapters/stdout_adapter_spec.rb
100
+ - spec/adapters/stdout_json_adapter_spec.rb
99
101
  - spec/logasm_spec.rb
100
102
  - spec/preprocessors/blacklist_spec.rb
101
103
  - spec/preprocessors/whitelist_spec.rb
@@ -131,6 +133,7 @@ test_files:
131
133
  - spec/adapters/logstash_adapter_spec.rb
132
134
  - spec/adapters/rabbitmq_adapter_spec.rb
133
135
  - spec/adapters/stdout_adapter_spec.rb
136
+ - spec/adapters/stdout_json_adapter_spec.rb
134
137
  - spec/logasm_spec.rb
135
138
  - spec/preprocessors/blacklist_spec.rb
136
139
  - spec/preprocessors/whitelist_spec.rb