sherlog-holmes 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c34a19741cd97a879215b2062a21a8d930eebf10
4
- data.tar.gz: 8bcb4667f3a28a6cbd96526897e683a03dd28af7
3
+ metadata.gz: 0f7d4009b72347473254b169427804b5dfb0ed36
4
+ data.tar.gz: 9cad2d96b5b02ac7fedef91ba8b39c32a9c8d3eb
5
5
  SHA512:
6
- metadata.gz: 35054790cca640f9c83ef34b742e4b2a74fa48439c8e839f89d56900365dc9dae7441e3c2ea233bc68c0066db2e9ba252ac1d6cbfd30c4f7d40b501ee7433a06
7
- data.tar.gz: a73d9d44a0f4a16e4d2fe397051ab669341626119d010938277dd0efcc8a8418ba0be01b5c4e183e8c73990d430da269daacb970fa4c4b5922a4a460cd16625c
6
+ metadata.gz: 940283aab12cf1fd5ab55d81addca4812e3715bb411367294d2e7d64de9c4d94368ba0cf9a8b83db56962704cbfccf1ec7e37f887b5cc1e22b74ac0cefd72634
7
+ data.tar.gz: d105d4e8a515179053a92ae15149c54a3b3b80c001a3b5f201135402c176e3a98f2cd6a460572cfafcd91c9222819c672763cf580fa4596ff3971149c4ee860e
data/.idea/.rakeTasks ADDED
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Settings><!--This file was automatically generated by Ruby plugin.
3
+ You are allowed to:
4
+ 1. Remove rake task
5
+ 2. Add existing rake tasks
6
+ To add existing rake tasks automatically delete this file and reload the project.
7
+ --><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build sherlog-holmes-0.2.0.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Build and install sherlog-holmes-0.2.0.gem into system gems" fullCmd="install" taksId="install" /><RakeGroup description="" fullCmd="" taksId="install"><RakeTask description="Build and install sherlog-holmes-0.2.0.gem into system gems without network access" fullCmd="install:local" taksId="local" /></RakeGroup><RakeTask description="Create tag v0.2.0 and build and push sherlog-holmes-0.2.0.gem to Rubygems" fullCmd="release" taksId="release" /><RakeGroup description="" fullCmd="" taksId="release"><RakeTask description="" fullCmd="release:guard_clean" taksId="guard_clean" /><RakeTask description="" fullCmd="release:rubygem_push" taksId="rubygem_push" /><RakeTask description="" fullCmd="release:source_control_push" taksId="source_control_push" /></RakeGroup></RakeGroup></Settings>
@@ -0,0 +1,6 @@
1
+ <component name="CopyrightManager">
2
+ <copyright>
3
+ <option name="myName" value="MIT" />
4
+ <option name="notice" value="The MIT License (MIT)&#10;&#10;Copyright (c) &amp;#36;today.year Marcelo &quot;Ataxexe&quot; Guimaraes &lt;ataxexe@devnull.tools&gt;&#10;&#10;Permission is hereby granted, free of charge, to any person obtaining a copy&#10;of this software and associated documentation files (the &quot;Software&quot;), to deal&#10;in the Software without restriction, including without limitation the rights&#10;to use, copy, modify, merge, publish, distribute, sublicense, and/or sell&#10;copies of the Software, and to permit persons to whom the Software is&#10;furnished to do so, subject to the following conditions:&#10;&#10;The above copyright notice and this permission notice shall be included in&#10;all copies or substantial portions of the Software.&#10;&#10;THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR&#10;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,&#10;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE&#10;AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER&#10;LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,&#10;OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN&#10;THE SOFTWARE.&#10;" />
5
+ </copyright>
6
+ </component>
@@ -1,3 +1,7 @@
1
1
  <component name="CopyrightManager">
2
- <settings default="" />
2
+ <settings default="MIT">
3
+ <module2copyright>
4
+ <element module="Project Files" copyright="MIT" />
5
+ </module2copyright>
6
+ </settings>
3
7
  </component>
data/.idea/misc.xml CHANGED
@@ -7,161 +7,6 @@
7
7
  </MavenGeneralSettings>
8
8
  </option>
9
9
  </component>
10
- <component name="ProjectInspectionProfilesVisibleTreeState">
11
- <entry key="Project Default">
12
- <profile-state>
13
- <expanded-state>
14
- <State>
15
- <id />
16
- </State>
17
- <State>
18
- <id>AOP</id>
19
- </State>
20
- <State>
21
- <id>Abstraction issuesJava</id>
22
- </State>
23
- <State>
24
- <id>Android Lint</id>
25
- </State>
26
- <State>
27
- <id>Annotations verifyingGroovy</id>
28
- </State>
29
- <State>
30
- <id>Assignment issuesJava</id>
31
- </State>
32
- <State>
33
- <id>CDI(Contexts and Dependency Injection) issues</id>
34
- </State>
35
- <State>
36
- <id>Class structureJava</id>
37
- </State>
38
- <State>
39
- <id>Cloning issuesJava</id>
40
- </State>
41
- <State>
42
- <id>Code style issuesJava</id>
43
- </State>
44
- <State>
45
- <id>Code style issuesJavaScript</id>
46
- </State>
47
- <State>
48
- <id>Encapsulation issuesJava</id>
49
- </State>
50
- <State>
51
- <id>Error handlingJava</id>
52
- </State>
53
- <State>
54
- <id>Finalization issuesJava</id>
55
- </State>
56
- <State>
57
- <id>General</id>
58
- </State>
59
- <State>
60
- <id>GeneralJavaScript</id>
61
- </State>
62
- <State>
63
- <id>GeneralScala</id>
64
- </State>
65
- <State>
66
- <id>Groovy</id>
67
- </State>
68
- <State>
69
- <id>ImportsJava</id>
70
- </State>
71
- <State>
72
- <id>Inheritance issuesJava</id>
73
- </State>
74
- <State>
75
- <id>Internationalization issues</id>
76
- </State>
77
- <State>
78
- <id>Internationalization issuesJava</id>
79
- </State>
80
- <State>
81
- <id>J2ME issuesJava</id>
82
- </State>
83
- <State>
84
- <id>JPA issues</id>
85
- </State>
86
- <State>
87
- <id>JSON</id>
88
- </State>
89
- <State>
90
- <id>Java</id>
91
- </State>
92
- <State>
93
- <id>Java language level issuesJava</id>
94
- </State>
95
- <State>
96
- <id>Java language level migration aidsJava</id>
97
- </State>
98
- <State>
99
- <id>JavaScript</id>
100
- </State>
101
- <State>
102
- <id>Javadoc issuesJava</id>
103
- </State>
104
- <State>
105
- <id>Language Injection</id>
106
- </State>
107
- <State>
108
- <id>Memory issuesJava</id>
109
- </State>
110
- <State>
111
- <id>Modularization issuesJava</id>
112
- </State>
113
- <State>
114
- <id>Numeric issuesJava</id>
115
- </State>
116
- <State>
117
- <id>Performance issuesJava</id>
118
- </State>
119
- <State>
120
- <id>Portability issuesJava</id>
121
- </State>
122
- <State>
123
- <id>Potentially confusing code constructsGroovy</id>
124
- </State>
125
- <State>
126
- <id>Potentially confusing code constructsJavaScript</id>
127
- </State>
128
- <State>
129
- <id>Probable bugsGroovy</id>
130
- </State>
131
- <State>
132
- <id>Probable bugsJava</id>
133
- </State>
134
- <State>
135
- <id>Properties Files</id>
136
- </State>
137
- <State>
138
- <id>Scala</id>
139
- </State>
140
- <State>
141
- <id>ScaladocScala</id>
142
- </State>
143
- <State>
144
- <id>Security issuesJava</id>
145
- </State>
146
- <State>
147
- <id>Serialization issuesJava</id>
148
- </State>
149
- <State>
150
- <id>Spring</id>
151
- </State>
152
- <State>
153
- <id>Spring CoreSpring</id>
154
- </State>
155
- <State>
156
- <id>Threading issuesGroovy</id>
157
- </State>
158
- <State>
159
- <id>Threading issuesJava</id>
160
- </State>
161
- </expanded-state>
162
- </profile-state>
163
- </entry>
164
- </component>
165
10
  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
166
11
  <OptionsSetting value="true" id="Add" />
167
12
  <OptionsSetting value="true" id="Remove" />
@@ -1,18 +1,33 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <module type="RUBY_MODULE" version="4">
3
+ <component name="FacetManager">
4
+ <facet type="gem" name="Gem">
5
+ <configuration>
6
+ <option name="GEM_APP_ROOT_PATH" value="" />
7
+ <option name="GEM_APP_TEST_PATH" value="" />
8
+ <option name="GEM_APP_LIB_PATH" value="" />
9
+ </configuration>
10
+ </facet>
11
+ </component>
3
12
  <component name="NewModuleRootManager" inherit-compiler-output="true">
4
13
  <exclude-output />
5
14
  <content url="file://$MODULE_DIR$">
6
15
  <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
7
16
  <sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
8
17
  <sourceFolder url="file://$MODULE_DIR$/bin" isTestSource="false" />
18
+ <sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
9
19
  </content>
10
20
  <orderEntry type="inheritedJdk" />
11
21
  <orderEntry type="sourceFolder" forTests="false" />
12
22
  <orderEntry type="library" scope="PROVIDED" name="bundler (v1.10.6, RVM: ruby-2.2-head) [gem]" level="application" />
13
- <orderEntry type="library" scope="PROVIDED" name="power_assert (v0.2.4, RVM: ruby-2.2-head) [gem]" level="application" />
23
+ <orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.2.5, RVM: ruby-2.2-head) [gem]" level="application" />
24
+ <orderEntry type="library" scope="PROVIDED" name="rake (v10.4.2, RVM: ruby-2.2-head) [gem]" level="application" />
25
+ <orderEntry type="library" scope="PROVIDED" name="rspec (v3.4.0, RVM: ruby-2.2-head) [gem]" level="application" />
26
+ <orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.4.1, RVM: ruby-2.2-head) [gem]" level="application" />
27
+ <orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.4.0, RVM: ruby-2.2-head) [gem]" level="application" />
28
+ <orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.4.0, RVM: ruby-2.2-head) [gem]" level="application" />
29
+ <orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.4.1, RVM: ruby-2.2-head) [gem]" level="application" />
14
30
  <orderEntry type="library" scope="PROVIDED" name="term-ansicolor (v1.3.2, RVM: ruby-2.2-head) [gem]" level="application" />
15
- <orderEntry type="library" scope="PROVIDED" name="test-unit (v3.1.5, RVM: ruby-2.2-head) [gem]" level="application" />
16
31
  <orderEntry type="library" scope="PROVIDED" name="tins (v1.6.0, RVM: ruby-2.2-head) [gem]" level="application" />
17
32
  <orderEntry type="library" scope="PROVIDED" name="yummi (v0.9.5, RVM: ruby-2.2-head) [gem]" level="application" />
18
33
  </component>
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015 Ataxexe
3
+ Copyright (c) 2015 Marcelo "Ataxexe" Guimaraes <ataxexe@devnull.tools>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Sherlog Holmes
2
2
 
3
- This is a gem to help the analysis of logs
3
+ *Less data containing useful information is way better than lots of data containing a mess.*
4
+
5
+ Don't you hate thousands of lines in a log blowing up with your troubleshooting? Lots of useless data that you have to filter just to turn that 300 MB of madness into a 30 KB of useful information. If you need something that can rip off useless entries so you can have a clue about what is going on with that application, you should give Sherlog Holmes a try.
4
6
 
5
7
  ## Installation
6
8
 
@@ -18,9 +20,86 @@ Or install it yourself as:
18
20
 
19
21
  $ gem install sherlog-holmes
20
22
 
23
+ ## Concepts
24
+
25
+ Sherlog works by grabbing every line of a log and parsing it into a simple structure containing:
26
+
27
+ - Time
28
+ - Level
29
+ - Category
30
+ - Origin
31
+ - Message
32
+ - Exception (if present)
33
+ - Stacktrace (if present)
34
+
35
+ You need to supply a regular expression that maps that fields to match your log entry. Here is an example:
36
+
37
+ ```regexp
38
+ (<?level>\w+)\s(<?category>\s+)\s(<?message>.+)
39
+ ```
40
+
41
+ Notice that you don't need to define every field, just the ones you need to filter.
42
+
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
+
45
+ ```yaml
46
+ jboss:
47
+ entry: (?<time>[0-9,.:]+)\s+(?<level>\w+)\s+\[(?<category>\S+)\]\s\((?<origin>[^)]+)\)?\s?(?<message>.+)
48
+ exception: (?<exception>\w+(\.\w+)+(Exception|Error))
49
+ stacktrace: ^(\s+at)|(Caused by\:)|(\s+\.{3}\s\d+\smore)
50
+ ```
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!
53
+
21
54
  ## Usage
22
55
 
23
- Shelog Holmes provides a command line tool `sherlog`. Execute `sherlog -h` to see the options and command usage.
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
+
58
+ `-p, --patterns FILE`
59
+
60
+ 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
+
62
+ `-c, --category EXPRESSION`
63
+
64
+ This will filter entries using the category field. You can use the wildcard `*` here.
65
+
66
+ `-l, --level EXPRESSION`
67
+
68
+ This will filter entries using the level field. You can use the wildcard `*` here.
69
+
70
+ `-o, --origin EXPRESSION`
71
+
72
+ This will filter entries using the origin field. You can use the wildcard `*` here.
73
+
74
+ `-m, --message EXPRESSION`
75
+
76
+ This will filter entries using the message field. You can use the wildcard `*` here.
77
+
78
+ `-e, --exception EXPRESSION`
79
+
80
+ This will filter entries using the exception field. You can use the wildcard `*` here.
81
+
82
+ *NOTICE: the expressions are case sensitive, wildcards can be used at start, end or both*
83
+
84
+ `--any-exception`
85
+
86
+ This will filter entries with exceptions, regardless the kind.
87
+
88
+ `--and`
89
+
90
+ This will use the **AND** operation to connect the next filter. This is the default operation.
91
+
92
+ `--or`
93
+
94
+ This will use the **OR** operation to connect the next filter.
95
+
96
+ sherlog --level WARN --or --level ERROR --and --any-exception
97
+
98
+ This is equivalent to:
99
+
100
+ (WARN || ERROR) && EXCEPTION
101
+
102
+ *NOTICE: you cannot do some fuzzy logics with these operations because there are no options to define the precedence*
24
103
 
25
104
  ## License
26
105
 
data/bin/sherlog CHANGED
@@ -1,4 +1,25 @@
1
1
  #!/usr/bin/env ruby
2
+ # The MIT License
3
+ #
4
+ # Copyright (c) 2015 Marcelo "Ataxexe" Guimarães <ataxexe@devnull.tools>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
2
23
 
3
24
  require 'yummi'
4
25
  require 'optionparser'
@@ -8,59 +29,65 @@ require_relative '../lib/sherlog_holmes'
8
29
  include Sherlog
9
30
 
10
31
  @opts = OptionParser::new
11
- @filter_params = {}
12
- @params = {}
32
+ @stacktrace = true
33
+ @filter = nil
34
+ @operation = :and
35
+ @listeners = []
36
+
37
+ def add_filter(filter)
38
+ if @filter
39
+ @filter = @filter.send @operation, filter
40
+ else
41
+ @filter = filter
42
+ end
43
+ end
13
44
 
14
45
  @opts.banner = 'Usage: sherlog [options] <logfile>'
15
46
 
16
- @opts.on '-c EXPRESSION', '--category EXPRESSION', 'Set the category filter regexp' do |expression|
17
- @filter_params[:category] = expression
47
+ @opts.on '-p FILE', '--patterns FILE', 'Configures the patterns' do |file|
48
+ Sherlog.load_patterns file
18
49
  end
19
50
 
20
- @opts.on '-l EXPRESSION', '--level EXPRESSION', 'Set the level filter regexp' do |expression|
21
- @filter_params[:level] = expression
51
+ @opts.on '-c EXPRESSION', '--category EXPRESSION', 'Set the category filter expression' do |expression|
52
+ add_filter Filter::category(expression)
22
53
  end
23
54
 
24
- [:error, :info, :warn, :debug, :fatal].each do |level|
25
- @opts.on "--#{level}", "Filter #{level.upcase} logs" do
26
- if @filter_params[:level]
27
- @filter_params[:level] += "|#{level}"
28
- else
29
- @filter_params[:level] = level.to_s
30
- end
31
- end
55
+ @opts.on '-l EXPRESSION', '--level EXPRESSION', 'Set the level filter expression' do |expression|
56
+ add_filter Filter::level(expression)
32
57
  end
33
58
 
34
- @opts.on '-m EXPRESSION', '--message EXPRESSION', 'Set the message filter regexp' do |expression|
35
- @filter_params[:message] = expression
59
+ @opts.on '-o EXPRESSION', '--origin EXPRESSION', 'Sets the origin filter expression' do |expression|
60
+ add_filter Filter::origin(expression)
36
61
  end
37
62
 
38
- @opts.on '-e EXPRESSION', '--exception EXPRESSION', 'Sets the exception filter regexp' do |expression|
39
- @filter_params[:exception] = expression
63
+ @opts.on '-m EXPRESSION', '--message EXPRESSION', 'Set the message filter expression' do |expression|
64
+ add_filter Filter::message(expression)
40
65
  end
41
66
 
42
- @opts.on '--no-stacktrace', 'Omits the stacktrace when showing log entries' do
43
- @params[:stacktrace] = false
67
+ @opts.on '-e EXPRESSION', '--exception EXPRESSION', 'Sets the exception filter expression' do |expression|
68
+ add_filter Filter::exception(expression)
44
69
  end
45
70
 
46
- @opts.on '--only-exceptions', 'Filter only exception entries' do
47
- @only_exceptions = true
71
+ @opts.on '--any-exception', 'Filter exception entries' do
72
+ add_filter Filter::exceptions
48
73
  end
49
74
 
50
- @opts.on '--show-log', 'Shows the filtered entries' do
51
- @print_log = true
75
+ @opts.on '--and', 'Sets the next filter to use the AND operator' do
76
+ @operation = :and
52
77
  end
53
78
 
54
- @opts.on '--show-info', 'Shows information about the filtered entries' do
55
- @print_info = true
79
+ @opts.on '--or', 'Sets the next filter to use the OR operation' do
80
+ @operation = :or
56
81
  end
57
82
 
58
- @opts.on '--show-exception', 'Shows filtered entries that contains an exception' do
59
- @print_exception_entries = true
83
+ @opts.on '-t TYPE', '--type TYPE', 'Sets the type of the log (for loading patterns)' do |type|
84
+ @type = type.to_sym
60
85
  end
61
86
 
62
- @opts.on '--show-exception-info', 'Shows filtered entries that contains an exception' do
63
- @print_exception_info = true
87
+ @opts.on '--print', 'Prints the filtered entries' do
88
+ @listeners << lambda do |entry|
89
+ puts entry.raw_content
90
+ end
64
91
  end
65
92
 
66
93
  @opts.on '-h', '--help', 'Shows the usage help' do
@@ -71,14 +98,20 @@ end
71
98
  @opts.parse! ARGV
72
99
 
73
100
  file = ARGV.first
74
- filter = LogFilter::new
75
- filter.exceptions if @only_exceptions
76
- @filter_params.each do |param, expression|
77
- filter.send param, expression
101
+ parser = Sherlog.parser @type if @type
102
+ parser ||= Parser::new
103
+ parser.filter @filter
104
+ @listeners.each do |listener|
105
+ parser.on_new_entry listener
106
+ end
107
+ begin
108
+ if file
109
+ parser.parse file
110
+ else
111
+ ARGF.each_line do |line|
112
+ parser.parse line.chomp
113
+ end
114
+ end
115
+ rescue Interrupt
116
+ exit
78
117
  end
79
- log = LogFile::new file, filter, @params
80
- log.read
81
- log.print_info if @print_info
82
- log.print_exception_info if @print_exception_info
83
- log.print_exception_entries if @print_exception_entries
84
- log.print_entries if @print_log
@@ -0,0 +1,4 @@
1
+ jboss:
2
+ entry: (?<time>[0-9,.:]+)\s+(?<level>\w+)\s+\[(?<category>\S+)\]\s\((?<origin>[^)]+)\)?\s?(?<message>.+)
3
+ exception: (?<exception>\w+(\.\w+)+(Exception|Error))
4
+ stacktrace: ^(\s+at)|(Caused by\:)|(\s+\.{3}\s\d+\smore)
@@ -1,4 +1,63 @@
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
+ require 'yummi'
24
+ require 'yaml'
25
+
1
26
  require_relative 'sherlog_holmes/version'
2
- require_relative 'sherlog_holmes/log_entry'
3
- require_relative 'sherlog_holmes/log_filter'
4
- require_relative 'sherlog_holmes/log_file'
27
+ require_relative 'sherlog_holmes/result'
28
+ require_relative 'sherlog_holmes/entry'
29
+ require_relative 'sherlog_holmes/filter'
30
+ require_relative 'sherlog_holmes/parser'
31
+
32
+ module Sherlog
33
+
34
+ PATTERNS = {}
35
+
36
+ def self.load_patterns(file)
37
+ patterns = YAML::load_file file
38
+ patterns.each do |id, config|
39
+ PATTERNS[id.to_sym] = {
40
+ entry: Regexp::new(config['entry']),
41
+ exception: Regexp::new(config['exception']),
42
+ stacktrace: Regexp::new(config['stacktrace'])
43
+ }
44
+ end
45
+ end
46
+
47
+ Dir['%s/../conf/patterns/*.yml' % File.dirname(__FILE__)].each do |file|
48
+ load_patterns file
49
+ end
50
+
51
+ Dir['%s/.sherlog/patterns/*.yml' % ENV['HOME']].each do |file|
52
+ load_patterns file
53
+ end
54
+
55
+ def self.parser(pattern_id)
56
+ Parser::new PATTERNS[pattern_id.to_sym]
57
+ end
58
+
59
+ def self.loaded_patterns
60
+ PATTERNS
61
+ end
62
+
63
+ end
@@ -0,0 +1,59 @@
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
+ class Entry
25
+
26
+ attr_accessor :time, :level, :category, :origin, :message, :exception, :stacktrace, :raw_content
27
+
28
+ def initialize(params = {})
29
+ @time = params[:time]
30
+ @level = params[:level]
31
+ @category = params[:category]
32
+ @origin = params[:origin]
33
+ @message = params[:message]
34
+ @exception = params[:exception]
35
+ @stacktrace = []
36
+ end
37
+
38
+ def exception?
39
+ !@exception.nil?
40
+ end
41
+
42
+ def <<(line)
43
+ @message << $/ << line
44
+ end
45
+
46
+ def to_s
47
+ format = []
48
+ params = []
49
+ format << '%s' && params << time if time
50
+ format << '%s' && params << level.to_s.ljust(7) if level
51
+ format << '[%s]' && params << category if category
52
+ format << '(%s)' && params << origin if origin
53
+ format << '%s' && params << message if message
54
+ string = format.join(' ') % params
55
+ ([string] + @stacktrace).join($/)
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,107 @@
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 Filter
26
+
27
+ def initialize(&block)
28
+ @block = block
29
+ end
30
+
31
+ def call(object)
32
+ accept? object
33
+ end
34
+
35
+ def accept?(object)
36
+ @block.call object
37
+ end
38
+
39
+ def and(other_filter = nil, &other_block)
40
+ other_filter ||= Filter::new &other_block
41
+ Filter::new do |entry|
42
+ self.accept?(entry) && other_filter.accept?(entry)
43
+ end
44
+ end
45
+
46
+ def or(other_filter = nil, &other_block)
47
+ other_filter ||= Filter::new &other_block
48
+ Filter::new do |entry|
49
+ self.accept?(entry) || other_filter.accept?(entry)
50
+ end
51
+ end
52
+
53
+ def self.expression(expression)
54
+ Filter::new do |object|
55
+ wildcard_at_start = expression.start_with? '*'
56
+ wildcard_at_end = expression.end_with? '*'
57
+ if wildcard_at_start and wildcard_at_end
58
+ object.to_s.index expression[1...-1]
59
+ elsif wildcard_at_start
60
+ object.to_s.end_with? expression[1..-1]
61
+ elsif wildcard_at_end
62
+ object.to_s.start_with? expression[0...-1]
63
+ else
64
+ object.to_s == expression.to_s
65
+ end
66
+ end
67
+ end
68
+
69
+ def self.level(expression)
70
+ Filter::new do |entry|
71
+ entry.level.to_s == expression.to_s
72
+ end
73
+ end
74
+
75
+ def self.category(expression)
76
+ Filter::new do |entry|
77
+ expression(expression).accept? entry.category
78
+ end
79
+ end
80
+
81
+ def self.origin(expression)
82
+ Filter::new do |entry|
83
+ expression(expression).accept? entry.origin
84
+ end
85
+ end
86
+
87
+ def self.message(expression)
88
+ Filter::new do |entry|
89
+ expression(expression).accept? entry.message
90
+ end
91
+ end
92
+
93
+ def self.exception(expression)
94
+ Filter::new do |entry|
95
+ expression(expression).accept? entry.exception
96
+ end
97
+ end
98
+
99
+ def self.exceptions
100
+ Filter::new do |entry|
101
+ entry.exception?
102
+ end
103
+ end
104
+
105
+ end
106
+
107
+ end
@@ -0,0 +1,109 @@
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
+ class Parser
25
+
26
+ def initialize(patterns = {}, filter = nil)
27
+ @filter = filter
28
+ @patterns = {
29
+ exception: /^$/,
30
+ stacktrace: /^$/
31
+ }.merge patterns
32
+ @filter ||= filter { |entry| true }
33
+ @listeners = []
34
+ end
35
+
36
+ def collect
37
+ result = Result::new
38
+ on_new_entry do |entry|
39
+ result << entry
40
+ end
41
+ result
42
+ end
43
+
44
+ def on_new_entry(listener = nil, &block)
45
+ listener ||= block
46
+ @listeners << listener
47
+ end
48
+
49
+ def filter(filter = nil, &block)
50
+ @filter = filter if filter
51
+ @filter = Filter::new &block if block
52
+ end
53
+
54
+ def patterns(config)
55
+ @patterns.merge! config
56
+ end
57
+
58
+ def parse(input)
59
+ entry = nil
60
+ foreach input do |line|
61
+ try_guess_pattern line unless @patterns[:entry]
62
+ if @patterns[:entry] =~ line
63
+ entry_data = Hash[Regexp.last_match.names.map { |k| [k.to_sym, Regexp.last_match[k]] }]
64
+ notify entry
65
+ entry = Entry::new entry_data
66
+ entry.raw_content = line.chomp
67
+ entry.exception = Regexp.last_match[:exception] if @patterns[:exception] =~ entry.message
68
+ entry = nil unless @filter.accept? entry
69
+ else
70
+ if entry
71
+ if entry.exception? and @patterns[:stacktrace] =~ line
72
+ entry.stacktrace << line.chomp
73
+ else
74
+ entry << line.chomp
75
+ end
76
+ entry.raw_content << $/ << line.chomp
77
+ end
78
+ end
79
+ end
80
+ notify entry
81
+ end
82
+
83
+ private
84
+
85
+ def foreach(input, &block)
86
+ if File.exist? input
87
+ IO.foreach input, &block
88
+ else
89
+ input.each_line &block
90
+ end
91
+ end
92
+
93
+ def notify(entry)
94
+ return unless entry
95
+ @listeners.each do |listener|
96
+ listener.call entry
97
+ end
98
+ end
99
+
100
+ def try_guess_pattern(line)
101
+ key, patterns = Sherlog.loaded_patterns.find do |key, patterns|
102
+ patterns[:entry].match line
103
+ end
104
+ patterns ||= {entry: /(?<message>.+)/}
105
+ @patterns.merge! patterns
106
+ end
107
+
108
+ end
109
+ end
@@ -0,0 +1,49 @@
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
+ class Result
25
+
26
+ def initialize
27
+ @entries = []
28
+ end
29
+
30
+ def <<(entry)
31
+ @entries << entry
32
+ self
33
+ end
34
+
35
+ def entries(params = {})
36
+ return @entries.find_all { |entry| params[:filter].accept? entry } if params[:filter]
37
+ @entries
38
+ end
39
+
40
+ def exceptions
41
+ entries filter: Filter::exceptions
42
+ end
43
+
44
+ def size
45
+ @entries.size
46
+ end
47
+
48
+ end
49
+ end
@@ -1,3 +1,25 @@
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
+
1
23
  module Sherlog
2
- VERSION = '0.1.0'
24
+ VERSION = '0.2.0'
3
25
  end
@@ -22,5 +22,5 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_development_dependency 'bundler', '~> 1.10'
24
24
  spec.add_development_dependency 'rake', '~> 10.0'
25
- spec.add_development_dependency 'test-unit'
25
+ spec.add_development_dependency 'rspec', '~> 3.4.0'
26
26
  end
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.1.0
4
+ version: 0.2.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-04 00:00:00.000000000 Z
11
+ date: 2015-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yummi
@@ -53,19 +53,19 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '10.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: test-unit
56
+ name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 3.4.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: 3.4.0
69
69
  description:
70
70
  email:
71
71
  - ataxexe@devnull.tools
@@ -76,7 +76,9 @@ extra_rdoc_files: []
76
76
  files:
77
77
  - ".gitignore"
78
78
  - ".idea/.name"
79
+ - ".idea/.rakeTasks"
79
80
  - ".idea/compiler.xml"
81
+ - ".idea/copyright/MIT.xml"
80
82
  - ".idea/copyright/profiles_settings.xml"
81
83
  - ".idea/encodings.xml"
82
84
  - ".idea/misc.xml"
@@ -84,15 +86,18 @@ files:
84
86
  - ".idea/sherlog-holmes.iml"
85
87
  - ".idea/uiDesigner.xml"
86
88
  - ".idea/vcs.xml"
89
+ - ".rspec"
87
90
  - Gemfile
88
91
  - LICENSE.txt
89
92
  - README.md
90
93
  - Rakefile
91
94
  - bin/sherlog
95
+ - conf/patterns/jboss.yml
92
96
  - lib/sherlog_holmes.rb
93
- - lib/sherlog_holmes/log_entry.rb
94
- - lib/sherlog_holmes/log_file.rb
95
- - lib/sherlog_holmes/log_filter.rb
97
+ - lib/sherlog_holmes/entry.rb
98
+ - lib/sherlog_holmes/filter.rb
99
+ - lib/sherlog_holmes/parser.rb
100
+ - lib/sherlog_holmes/result.rb
96
101
  - lib/sherlog_holmes/version.rb
97
102
  - sherlog-holmes.gemspec
98
103
  homepage: https://github.com/devnull-tools/sherlog-holmes
@@ -1,37 +0,0 @@
1
- module Sherlog
2
- class LogEntry
3
-
4
- attr_accessor :time, :level, :category, :origin, :message, :exception_class
5
-
6
- def initialize(params = {})
7
- @time = params[:time]
8
- @level = params[:level]
9
- @category = params[:category]
10
- @origin = params[:origin]
11
- @message = params[:message]
12
- @stacktrace = []
13
- data = /(\w+(\.\w+)+(Exception|Error))/.match @message
14
- if data
15
- @exception_class = data[1]
16
- end
17
- end
18
-
19
- def exception?
20
- !@exception_class.nil?
21
- end
22
-
23
- def <<(line)
24
- @stacktrace << line
25
- end
26
-
27
- def to_s
28
- string = if origin
29
- '%s %s [%s] (%s) %s' % [time, level.ljust(7), category, origin, message]
30
- else
31
- '%s %s [%s] %s' % [time, level.ljust(7), category, message]
32
- end
33
- ([string] + @stacktrace).join($/)
34
- end
35
-
36
- end
37
- end
@@ -1,88 +0,0 @@
1
- module Sherlog
2
- class LogFile
3
-
4
- attr_reader :entries, :file
5
-
6
- def initialize(logfile, filter, params = {})
7
- @file = logfile
8
- @params = {
9
- stacktrace: true
10
- }.merge params
11
- @filter = filter
12
- @entries = []
13
- @exceptions = {}
14
- @map = {}
15
- end
16
-
17
- def read
18
- # time level category origin message
19
- regexp = /([0-9,.:]+)\s+(\w+)\s+\[(\S+)\]\s(\(\S+\))?\s?(.+)/
20
- entry = nil
21
- IO.foreach(file) do |line|
22
- data = regexp.match line.chomp
23
- if data
24
- entry = LogEntry::new time: data[1],
25
- level: data[2],
26
- category: data[3],
27
- origin: data[4].to_s[1..-1],
28
- message: data[5]
29
- if @filter.accept? entry
30
- @entries << entry
31
- if entry.exception?
32
- @exceptions[entry.exception_class] ||= []
33
- @exceptions[entry.exception_class] << entry
34
- end
35
- @map[entry.level] ||= {}
36
- @map[entry.level][entry.category] ||= []
37
-
38
- @map[entry.level][entry.category] << entry
39
- end
40
- else
41
- entry << line.chomp if entry and @params[:stacktrace]
42
- end
43
- end
44
- end
45
-
46
- def print_info(target = $stdout)
47
- @map.each do |level, categories|
48
- table = Yummi::Table::new
49
- table.title = 'Entries for %s level by category' % level
50
- table.header = %w(Category Count)
51
- table.colorize :category, with: 'bold.white'
52
- table.colorize :count, with: 'magenta'
53
- categories.sort_by { |k, v| v.size }.each do |category, entries|
54
- table << [category, entries.size]
55
- end
56
- table.print target
57
- target.print $/
58
- end
59
- end
60
-
61
- def print_entries(target = $stdout)
62
- @entries.each do |entry|
63
- target.print entry.to_s + $/
64
- end
65
- end
66
-
67
- def print_exception_entries(target = $stdout)
68
- @entries.each do |entry|
69
- target.print entry.to_s + $/ if entry.exception?
70
- end
71
- end
72
-
73
- def print_exception_info(target = $stdout)
74
- unless @exceptions.empty?
75
- table = Yummi::Table::new
76
- table.title = 'Exceptions by class'
77
- table.header = %w(Class Count)
78
- table.colorize :class, with: 'bold.white'
79
- table.colorize :count, with: 'magenta'
80
- @exceptions.sort_by { |k, v| v.size }.each do |exception_class, entries|
81
- table << [exception_class, entries.size]
82
- end
83
- table.print target
84
- end
85
- end
86
-
87
- end
88
- end
@@ -1,48 +0,0 @@
1
- module Sherlog
2
- class LogFilter
3
-
4
- def initialize
5
- @filters = []
6
- end
7
-
8
- def filter(filter = nil, &block)
9
- @filters << filter if filter
10
- @filters << block if block
11
- end
12
-
13
- def level(expression)
14
- filter do |entry|
15
- /#{expression}/i.match entry.level
16
- end
17
- end
18
-
19
- def category(expression)
20
- filter do |entry|
21
- /#{expression}/.match entry.category
22
- end
23
- end
24
-
25
- def message(expression)
26
- filter do |entry|
27
- /#{expression}/i.match entry.category
28
- end
29
- end
30
-
31
- def exception(expression)
32
- filter do |entry|
33
- /#{expression}/.match entry.category
34
- end
35
- end
36
-
37
- def exceptions
38
- self << lambda do |entry|
39
- entry.exception?
40
- end
41
- end
42
-
43
- def accept?(entry)
44
- @filters.all? { |filter| filter.call entry }
45
- end
46
-
47
- end
48
- end