sherlog-holmes 0.2.0 → 0.3.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: 0f7d4009b72347473254b169427804b5dfb0ed36
4
- data.tar.gz: 9cad2d96b5b02ac7fedef91ba8b39c32a9c8d3eb
3
+ metadata.gz: 03f964fa6606b37a8676bd7dad10ad3c92d52416
4
+ data.tar.gz: d749eb7ce9c8768f55143c77f69b0b5fe286fa92
5
5
  SHA512:
6
- metadata.gz: 940283aab12cf1fd5ab55d81addca4812e3715bb411367294d2e7d64de9c4d94368ba0cf9a8b83db56962704cbfccf1ec7e37f887b5cc1e22b74ac0cefd72634
7
- data.tar.gz: d105d4e8a515179053a92ae15149c54a3b3b80c001a3b5f201135402c176e3a98f2cd6a460572cfafcd91c9222819c672763cf580fa4596ff3971149c4ee860e
6
+ metadata.gz: 6569c425092b97809a0073b0e6f2019b72df7eb6674c6c775537333a8c45078e956d1ac621326a51e4ebb4042bb2ab1369981f16213a15b27293abd34fd4e012
7
+ data.tar.gz: 623ed201b563e60d0d5e9930c0f5b2ff0f3cc953833ad7f94e51297eeeb30f231d300274487e27182591e5ed62e4da1068398659d9017149db3f219a4afaf779
@@ -1,12 +1,5 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <project version="4">
3
- <component name="MavenImportPreferences">
4
- <option name="generalSettings">
5
- <MavenGeneralSettings>
6
- <option name="mavenHome" value="Bundled (Maven 3)" />
7
- </MavenGeneralSettings>
8
- </option>
9
- </component>
10
3
  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
11
4
  <OptionsSetting value="true" id="Add" />
12
5
  <OptionsSetting value="true" id="Remove" />
data/README.md CHANGED
@@ -29,16 +29,16 @@ Sherlog works by grabbing every line of a log and parsing it into a simple struc
29
29
  - Category
30
30
  - Origin
31
31
  - Message
32
- - Exception (if present)
33
- - Stacktrace (if present)
32
+ - Exception
33
+ - Stacktrace
34
34
 
35
- You need to supply a regular expression that maps that fields to match your log entry. Here is an example:
35
+ You need to supply a regular expression that maps those fields in order to match your log entry. Here is an example:
36
36
 
37
37
  ```regexp
38
38
  (<?level>\w+)\s(<?category>\s+)\s(<?message>.+)
39
39
  ```
40
40
 
41
- Notice that you don't need to define every field, just the ones you need to filter.
41
+ Notice that you don't need to define every field, just the ones shown in your log.
42
42
 
43
43
  Patterns for exception and stacktrace should be defined separately. The exception pattern is used only in the message field. Here is a complete example of a pattern configuration:
44
44
 
@@ -49,16 +49,28 @@ jboss:
49
49
  stacktrace: ^(\s+at)|(Caused by\:)|(\s+\.{3}\s\d+\smore)
50
50
  ```
51
51
 
52
- The configuration should contain a unique id and at least a pattern for the log **entry**. Place you configuration file in a `*.yml` file inside you `$HOME/.sherlog/patterns` directory and you're ready to go!
52
+ The configuration should contain a unique id and at least a pattern for the log **entry**. Place you configuration file in a `*.yml` file inside your `$HOME/.sherlog/patterns` directory and you're ready to go!
53
53
 
54
54
  ## Usage
55
55
 
56
56
  Shelog Holmes provides the command line tool `sherlog`. You can use this to pass a log, the filters you need to apply and the process that needs to be executed (like showing the filtered entries or counting the exceptions):
57
57
 
58
+ ### Config Options
59
+
58
60
  `-p, --patterns FILE`
59
61
 
60
62
  Additionally to having definitions in your `$HOME/.sherlog` directory, you can pass a definition file from anywhere in your machine and Sherlog will scan and register the definitions.
61
63
 
64
+ `--encode ENCODE`
65
+
66
+ This sets the encode to use while reading the log file.
67
+
68
+ `-t, --type TYPE`
69
+
70
+ This will manually set the patterns definitions. If you don't specify this option, Sherlog will try the mapped ones with the first input line.
71
+
72
+ ### Filter Options
73
+
62
74
  `-c, --category EXPRESSION`
63
75
 
64
76
  This will filter entries using the category field. You can use the wildcard `*` here.
@@ -85,6 +97,8 @@ This will filter entries using the exception field. You can use the wildcard `*`
85
97
 
86
98
  This will filter entries with exceptions, regardless the kind.
87
99
 
100
+ ### Logical Options
101
+
88
102
  `--and`
89
103
 
90
104
  This will use the **AND** operation to connect the next filter. This is the default operation.
@@ -93,13 +107,53 @@ This will use the **AND** operation to connect the next filter. This is the defa
93
107
 
94
108
  This will use the **OR** operation to connect the next filter.
95
109
 
96
- sherlog --level WARN --or --level ERROR --and --any-exception
110
+ `--not`
111
+
112
+ This will negate the next filter.
113
+
114
+ ```
115
+ sherlog --level WARN --or --not --level INFO --and --any-exception
116
+ ```
97
117
 
98
118
  This is equivalent to:
99
119
 
100
- (WARN || ERROR) && EXCEPTION
120
+ (WARN || ! INFO) && EXCEPTION
121
+
122
+ *NOTICE: try not to do fuzzy logics with this operators*
123
+
124
+ ### Operation Options
125
+
126
+ `--print`
127
+
128
+ This will instruct Sherlog to print every filtered entry. This is useful to reduce that crazy log file into a sane one.
129
+
130
+ ```
131
+ $ sherlog --level ERROR --print crazy-log-file.log > sane-log-file.log
132
+ ```
133
+
134
+ `--no-stacktrace`
135
+
136
+ This will instruct Sherlog to not print stacktraces for entries. This only has effect if used with `--print`.
137
+
138
+ `--count GROUPS...`
139
+
140
+ Set this and Sherlog will count the number of entries per level, category, origin or exception. The possible parameters are (separated by a `,`):
141
+
142
+ - `levels`: counts the number of entries per level
143
+ - `categories`: counts the number of entries per category
144
+ - `origins`: counts the number of entries per origin
145
+ - `exception`: counts the number of entries per exception
146
+ - `all`: counts all groups
147
+
148
+ ```
149
+ $ sherlog --count levels,categories log-file.log
150
+ ```
151
+
152
+ ## Built-in Patterns
153
+
154
+ Currently, Sherlog has the following patterns:
101
155
 
102
- *NOTICE: you cannot do some fuzzy logics with these operations because there are no options to define the precedence*
156
+ - `jboss`: matches Wildfly | EAP logs
103
157
 
104
158
  ## License
105
159
 
@@ -32,22 +32,50 @@ include Sherlog
32
32
  @stacktrace = true
33
33
  @filter = nil
34
34
  @operation = :and
35
- @listeners = []
35
+ @listeners = {}
36
+ @groups = []
36
37
 
37
38
  def add_filter(filter)
39
+ filter = filter.negate if @negate
38
40
  if @filter
39
41
  @filter = @filter.send @operation, filter
40
42
  else
41
43
  @filter = filter
42
44
  end
45
+ @negate = false
46
+ end
47
+
48
+ def print_table(name, data)
49
+ table = Yummi::Table::new
50
+ table.title = name.to_s.capitalize
51
+ table.header = %w{Name Count}
52
+ table.colorize :name, with: 'bold.white'
53
+ table.colorize :count, with: 'magenta'
54
+ data.each do |name, count|
55
+ table << [name, count]
56
+ end
57
+ table.print
58
+ puts
43
59
  end
44
60
 
45
61
  @opts.banner = 'Usage: sherlog [options] <logfile>'
46
62
 
63
+ @opts.separator "\n Config Options\n".bold.white
64
+
47
65
  @opts.on '-p FILE', '--patterns FILE', 'Configures the patterns' do |file|
48
66
  Sherlog.load_patterns file
49
67
  end
50
68
 
69
+ @opts.on '--encode ENCODE', 'Sets the encode to read the log' do |encode|
70
+ ENV['SHERLOG_FILE_ENCODE'] = encode
71
+ end
72
+
73
+ @opts.on '-t TYPE', '--type TYPE', 'Sets the type of the log (for loading patterns)' do |type|
74
+ @type = type.to_sym
75
+ end
76
+
77
+ @opts.separator "\n Filter Options\n".bold.white
78
+
51
79
  @opts.on '-c EXPRESSION', '--category EXPRESSION', 'Set the category filter expression' do |expression|
52
80
  add_filter Filter::category(expression)
53
81
  end
@@ -72,6 +100,8 @@ end
72
100
  add_filter Filter::exceptions
73
101
  end
74
102
 
103
+ @opts.separator "\n Logical Options\n".bold.white
104
+
75
105
  @opts.on '--and', 'Sets the next filter to use the AND operator' do
76
106
  @operation = :and
77
107
  end
@@ -80,14 +110,32 @@ end
80
110
  @operation = :or
81
111
  end
82
112
 
83
- @opts.on '-t TYPE', '--type TYPE', 'Sets the type of the log (for loading patterns)' do |type|
84
- @type = type.to_sym
113
+ @opts.on '--not', 'Negates the next filter' do
114
+ @negate = true
85
115
  end
86
116
 
117
+ @opts.separator "\n Operation Options\n".bold.white
118
+
87
119
  @opts.on '--print', 'Prints the filtered entries' do
88
- @listeners << lambda do |entry|
89
- puts entry.raw_content
90
- end
120
+ @listeners[:print] = PrintListener::new
121
+ end
122
+
123
+ @opts.on '--no-stacktrace', 'Do not print stacktraces (use with --print)' do
124
+ @no_stacktrace = true
125
+ end
126
+
127
+ @opts.on '--count GROUPS...',
128
+ 'Counts entries and print the result by group (levels, categories, origins, exceptions or all)',
129
+ Array do |groups|
130
+ all_groups = [:levels, :categories, :origins, :exceptions]
131
+ @groups = if groups == ['all']
132
+ all_groups
133
+ else
134
+ all_groups.find_all do |name|
135
+ groups.index name.to_s
136
+ end
137
+ end
138
+ @listeners[:count] = CountListener::new
91
139
  end
92
140
 
93
141
  @opts.on '-h', '--help', 'Shows the usage help' do
@@ -97,11 +145,13 @@ end
97
145
 
98
146
  @opts.parse! ARGV
99
147
 
148
+ @listeners[:print].hide_stacktrace if @no_stacktrace and @listeners[:print]
149
+
100
150
  file = ARGV.first
101
151
  parser = Sherlog.parser @type if @type
102
152
  parser ||= Parser::new
103
153
  parser.filter @filter
104
- @listeners.each do |listener|
154
+ @listeners.values.each do |listener|
105
155
  parser.on_new_entry listener
106
156
  end
107
157
  begin
@@ -112,6 +162,9 @@ begin
112
162
  parser.parse line.chomp
113
163
  end
114
164
  end
165
+ @groups.each do |group|
166
+ print_table group, @listeners[:count].send(group).sort_by { |name, count| -count }
167
+ end
115
168
  rescue Interrupt
116
169
  exit
117
170
  end
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ ## v0.3.0
4
+
5
+ - Operation to count entries
6
+ - Entries can now have multiple exceptions (but the first one will be returned by `#exception`)
7
+ - Option to hide stacktrace while printing entries
8
+ - Option to set the encode
9
+ - Option to negate a filter
10
+
11
+ ## v0.2.0
12
+
13
+ - Patterns configurable through files
14
+ - Code Refactor
15
+ - Specs
16
+
17
+ ## v0.1.0
18
+
19
+ - Initial version
@@ -1,4 +1,4 @@
1
1
  jboss:
2
- entry: (?<time>[0-9,.:]+)\s+(?<level>\w+)\s+\[(?<category>\S+)\]\s\((?<origin>[^)]+)\)?\s?(?<message>.+)
2
+ entry: (?<time>(\d{4}-\d{2}-\d{2}\s)?(\d{2}:\d{2}:\d{2},\d{3}))\s+(?<level>\w+)\s+\[(?<category>\S+)\]\s\((?<origin>[^)]+)\)?\s?(?<message>.+)
3
3
  exception: (?<exception>\w+(\.\w+)+(Exception|Error))
4
4
  stacktrace: ^(\s+at)|(Caused by\:)|(\s+\.{3}\s\d+\smore)
@@ -28,6 +28,8 @@ require_relative 'sherlog_holmes/result'
28
28
  require_relative 'sherlog_holmes/entry'
29
29
  require_relative 'sherlog_holmes/filter'
30
30
  require_relative 'sherlog_holmes/parser'
31
+ require_relative 'sherlog_holmes/listeners/print_listener'
32
+ require_relative 'sherlog_holmes/listeners/count_listener'
31
33
 
32
34
  module Sherlog
33
35
 
@@ -61,3 +63,5 @@ module Sherlog
61
63
  end
62
64
 
63
65
  end
66
+
67
+ ENV['SHERLOG_FILE_ENCODE'] ||= Encoding.default_external.name
@@ -23,7 +23,7 @@
23
23
  module Sherlog
24
24
  class Entry
25
25
 
26
- attr_accessor :time, :level, :category, :origin, :message, :exception, :stacktrace, :raw_content
26
+ attr_accessor :time, :level, :category, :origin, :message, :exceptions, :stacktrace, :raw_content
27
27
 
28
28
  def initialize(params = {})
29
29
  @time = params[:time]
@@ -31,12 +31,18 @@ module Sherlog
31
31
  @category = params[:category]
32
32
  @origin = params[:origin]
33
33
  @message = params[:message]
34
- @exception = params[:exception]
34
+ @exceptions = [params[:exception]] if params[:exception]
35
+ @exceptions ||= params[:exceptions]
36
+ @exceptions ||= []
35
37
  @stacktrace = []
36
38
  end
37
39
 
38
40
  def exception?
39
- !@exception.nil?
41
+ !@exceptions.empty?
42
+ end
43
+
44
+ def exception
45
+ @exceptions.first
40
46
  end
41
47
 
42
48
  def <<(line)
@@ -50,6 +50,12 @@ module Sherlog
50
50
  end
51
51
  end
52
52
 
53
+ def negate
54
+ Filter::new do |entry|
55
+ !self.accept?(entry)
56
+ end
57
+ end
58
+
53
59
  def self.expression(expression)
54
60
  Filter::new do |object|
55
61
  wildcard_at_start = expression.start_with? '*'
@@ -92,7 +98,9 @@ module Sherlog
92
98
 
93
99
  def self.exception(expression)
94
100
  Filter::new do |entry|
95
- expression(expression).accept? entry.exception
101
+ entry.exceptions.find do |exception|
102
+ expression(expression).accept? exception
103
+ end
96
104
  end
97
105
  end
98
106
 
@@ -0,0 +1,62 @@
1
+ # The MIT License
2
+ #
3
+ # Copyright (c) 2015 Marcelo "Ataxexe" Guimarães <ataxexe@devnull.tools>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module Sherlog
24
+
25
+ class CountListener
26
+ attr_reader :levels, :categories, :origins, :exceptions
27
+
28
+ def initialize
29
+ @levels = {}
30
+ @categories = {}
31
+ @origins = {}
32
+ @exceptions = {}
33
+ end
34
+
35
+ def call(entry)
36
+ initialize_counters entry
37
+ count entry
38
+ end
39
+
40
+ private
41
+
42
+ def initialize_counters(entry)
43
+ @levels[entry.level] ||= 0 if entry.level
44
+ @categories[entry.category] ||= 0 if entry.category
45
+ @origins[entry.origin] ||= 0 if entry.origin
46
+ entry.exceptions.each do |exception|
47
+ @exceptions[exception] ||= 0
48
+ end
49
+ end
50
+
51
+ def count(entry)
52
+ @levels[entry.level] += 1 if entry.level
53
+ @categories[entry.category] += 1 if entry.category
54
+ @origins[entry.origin] += 1 if entry.origin
55
+ entry.exceptions.each do |exception|
56
+ @exceptions[exception] += 1
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ end
@@ -0,0 +1,47 @@
1
+ # The MIT License
2
+ #
3
+ # Copyright (c) 2015 Marcelo "Ataxexe" Guimarães <ataxexe@devnull.tools>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module Sherlog
24
+
25
+ class PrintListener
26
+
27
+ def initialize(target = $stdout)
28
+ @target = target
29
+ end
30
+
31
+ def hide_stacktrace
32
+ @hide_stacktrace = true
33
+ end
34
+
35
+ def call(entry)
36
+ if @hide_stacktrace and not entry.stacktrace.empty?
37
+ content = entry.raw_content
38
+ message_end = content.index(entry.stacktrace.first)
39
+ @target << content[0...message_end].chomp << $/
40
+ else
41
+ @target << entry.raw_content.chomp << $/
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -64,7 +64,7 @@ module Sherlog
64
64
  notify entry
65
65
  entry = Entry::new entry_data
66
66
  entry.raw_content = line.chomp
67
- entry.exception = Regexp.last_match[:exception] if @patterns[:exception] =~ entry.message
67
+ entry.exceptions << Regexp.last_match[:exception] if @patterns[:exception] =~ entry.message
68
68
  entry = nil unless @filter.accept? entry
69
69
  else
70
70
  if entry
@@ -73,6 +73,7 @@ module Sherlog
73
73
  else
74
74
  entry << line.chomp
75
75
  end
76
+ entry.exceptions << Regexp.last_match[:exception] if @patterns[:exception] =~ line
76
77
  entry.raw_content << $/ << line.chomp
77
78
  end
78
79
  end
@@ -84,7 +85,7 @@ module Sherlog
84
85
 
85
86
  def foreach(input, &block)
86
87
  if File.exist? input
87
- IO.foreach input, &block
88
+ IO.foreach input, encoding: ENV['SHERLOG_FILE_ENCODE'], &block
88
89
  else
89
90
  input.each_line &block
90
91
  end
@@ -21,5 +21,5 @@
21
21
  # THE SOFTWARE.
22
22
 
23
23
  module Sherlog
24
- VERSION = '0.2.0'
24
+ VERSION = '0.3.0'
25
25
  end
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['Ataxexe']
10
10
  spec.email = ['ataxexe@devnull.tools']
11
11
 
12
- spec.summary = %q{A gem to analyse log files}
12
+ spec.summary = %q{The best companion for a log detective!}
13
13
  spec.homepage = 'https://github.com/devnull-tools/sherlog-holmes'
14
14
  spec.license = 'MIT'
15
15
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sherlog-holmes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ataxexe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-08 00:00:00.000000000 Z
11
+ date: 2015-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yummi
@@ -92,10 +92,13 @@ files:
92
92
  - README.md
93
93
  - Rakefile
94
94
  - bin/sherlog
95
+ - changelog.md
95
96
  - conf/patterns/jboss.yml
96
97
  - lib/sherlog_holmes.rb
97
98
  - lib/sherlog_holmes/entry.rb
98
99
  - lib/sherlog_holmes/filter.rb
100
+ - lib/sherlog_holmes/listeners/count_listener.rb
101
+ - lib/sherlog_holmes/listeners/print_listener.rb
99
102
  - lib/sherlog_holmes/parser.rb
100
103
  - lib/sherlog_holmes/result.rb
101
104
  - lib/sherlog_holmes/version.rb
@@ -123,5 +126,5 @@ rubyforge_project:
123
126
  rubygems_version: 2.4.6
124
127
  signing_key:
125
128
  specification_version: 4
126
- summary: A gem to analyse log files
129
+ summary: The best companion for a log detective!
127
130
  test_files: []