sherlog-holmes 0.1.0 → 0.2.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: 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