indy 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +18 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/History.txt +11 -0
- data/README.md +132 -0
- data/Rakefile +68 -0
- data/autotest/discover.rb +2 -0
- data/cucumber.yml +6 -0
- data/features/after_time.feature +41 -0
- data/features/application.feature +33 -0
- data/features/around_time.feature +34 -0
- data/features/before_time.feature +34 -0
- data/features/custom_pattern.feature +52 -0
- data/features/exact_log_level.feature +35 -0
- data/features/exact_message.feature +33 -0
- data/features/exact_mulitple_fields.feature +38 -0
- data/features/exact_time.feature +28 -0
- data/features/file.feature +30 -0
- data/features/log_levels.feature +40 -0
- data/features/message.feature +39 -0
- data/features/multiple_fields.feature +38 -0
- data/features/step_definitions/find_by.steps.rb +55 -0
- data/features/step_definitions/log_file.steps.rb +8 -0
- data/features/step_definitions/support/env.rb +1 -0
- data/features/step_definitions/support/transforms.rb +28 -0
- data/features/step_definitions/test_setup.steps.rb +4 -0
- data/features/step_definitions/test_teardown.steps.rb +0 -0
- data/features/step_definitions/time.steps.rb +29 -0
- data/features/within_time.feature +41 -0
- data/indy.gemspec +61 -0
- data/lib/indy.rb +5 -0
- data/lib/indy/indy.rb +463 -0
- data/lib/indy/result_set.rb +8 -0
- data/performance/helper.rb +5 -0
- data/performance/profile_spec.rb +35 -0
- data/spec/data.log +2 -0
- data/spec/helper.rb +4 -0
- data/spec/indy_spec.rb +212 -0
- data/spec/result_set_spec.rb +9 -0
- data/spec/search_spec.rb +97 -0
- data/spec/time_spec.rb +80 -0
- metadata +126 -0
data/.autotest
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
begin
|
2
|
+
require 'autotest/growl'
|
3
|
+
rescue Exception
|
4
|
+
puts %{
|
5
|
+
Autotest/Autospec can use Growl (growl.info|growlforwindows.com) to assist with reporting errors.
|
6
|
+
This would require Growl for the appropriate platform (MAC|Windows) and the Ruby gem 'karl-autotest-growl'
|
7
|
+
}
|
8
|
+
sleep 4
|
9
|
+
end
|
10
|
+
|
11
|
+
Autotest.add_hook(:initialize) {|at|
|
12
|
+
at.add_exception %r{^\.git} # ignore Version Control System
|
13
|
+
at.add_exception %r{^./tmp} # ignore temp files, lest autotest will run again, and again...
|
14
|
+
at.add_mapping(%r{^lib/.*\.rb$}) {|f, _|
|
15
|
+
Dir['spec/**/*.rb']
|
16
|
+
}
|
17
|
+
nil
|
18
|
+
}
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/History.txt
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
=== 0.1.1 / 2011-01-13
|
2
|
+
|
3
|
+
* Scope search by time (after, before, around, or within)
|
4
|
+
* Explicit format string can be provided to parse non-standard log times
|
5
|
+
* Reopen (or rewind) source for each #search
|
6
|
+
* Source parameter creates an IO object (StringIO, File, or Process)
|
7
|
+
|
8
|
+
=== 0.1.0 / 2010-12-13
|
9
|
+
|
10
|
+
* Search by exact match or regular expression
|
11
|
+
* Search with custom pattern
|
data/README.md
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
Indy: A Log Archaeology Tool
|
2
|
+
====================================
|
3
|
+
|
4
|
+
Synopsis
|
5
|
+
--------
|
6
|
+
|
7
|
+
Log files are often searched for particular strings but it does not often treat the logs themselves as data structures. Indy attempts to deliver logs with more powerful features by allowing the ability: to collect segments of a log from particular time; find a particular event; or monitor/reflect on a log to see if a particular event occurred (or not occurred).
|
8
|
+
|
9
|
+
Installation
|
10
|
+
------------
|
11
|
+
|
12
|
+
To install Indy use the following command:
|
13
|
+
|
14
|
+
$ gem install indy
|
15
|
+
|
16
|
+
(Add `sudo` if you're installing under a POSIX system as root)
|
17
|
+
|
18
|
+
Usage
|
19
|
+
-----
|
20
|
+
|
21
|
+
## Require Indy
|
22
|
+
|
23
|
+
require 'indy'
|
24
|
+
|
25
|
+
## Specify your Source
|
26
|
+
|
27
|
+
### As a process or command
|
28
|
+
|
29
|
+
Indy.search( {:cmd => 'ssh user@system "bash --login -c \"cat /var/log/standard.log\" "'} ).for(:severity => 'INFO')
|
30
|
+
|
31
|
+
### As a file
|
32
|
+
|
33
|
+
Indy.search('logpath/output.log').for(:application => 'MyApp')
|
34
|
+
|
35
|
+
### As a string
|
36
|
+
|
37
|
+
log_string = %{
|
38
|
+
2000-09-07 14:07:41 INFO MyApp - Entering application.
|
39
|
+
2000-09-07 14:07:41 INFO MyApp - Exiting application. }
|
40
|
+
|
41
|
+
Indy.search(log_string).for(:message => 'Entering application')
|
42
|
+
|
43
|
+
## Specify your Pattern
|
44
|
+
|
45
|
+
The default search pattern resembles something you might find:
|
46
|
+
|
47
|
+
YYYY-MM-DD HH:MM:SS SEVERITY APPLICATION_NAME - MESSAGE
|
48
|
+
|
49
|
+
### Default Log Pattern
|
50
|
+
|
51
|
+
Indy.search(source).for(:severity => 'INFO')
|
52
|
+
Indy.search(source).for(:application => 'MyApp', :severity => 'DEBUG')
|
53
|
+
|
54
|
+
### Custom Log Pattern
|
55
|
+
|
56
|
+
If the default pattern is obviously not strong enough for you, brew your own.
|
57
|
+
To do so, specify a pattern and each of the match with their symbolic name.
|
58
|
+
|
59
|
+
# HH:MM:SS SEVERITY APPLICATION#METHOD - MESSAGE
|
60
|
+
custom_pattern = "^(\d{2}:\d{2}:\d{2})\s*(INFO|DEBUG|WARN|ERROR)\s*([^#]+)#([^\s]+)\s*-\s*(.+)$"
|
61
|
+
|
62
|
+
Indy.search(source).with(custom_pattern,:time,:severity,:application,:method,:message).for(:severity => 'INFO', :method => 'allocate')
|
63
|
+
|
64
|
+
### Explicit Time Format
|
65
|
+
|
66
|
+
By default, Indy tries to guess your time format (courtesy of DateTime#parse). If you supply an explicit time format, it will use DateTime#strptime, as well as try to guess.
|
67
|
+
|
68
|
+
This is required when log data uses a non-standard date format, e.g.: U.S. format 12-31-2000
|
69
|
+
|
70
|
+
# 12-31-2011 23:59:59
|
71
|
+
Indy.new(:time_format => '%m-%d-%Y %H:%M:%S', :source => LOG_FILE).for(:all)
|
72
|
+
|
73
|
+
## Match Criteria
|
74
|
+
|
75
|
+
### Exact Match
|
76
|
+
|
77
|
+
Indy.search(source).for(:message => 'Entering Application')
|
78
|
+
Indy.search(source).for(:severity => 'INFO')
|
79
|
+
|
80
|
+
### Exact Match with multiple parameters
|
81
|
+
|
82
|
+
Indy.search(source).for(:message => 'Entering Application', :application => 'MyApp')
|
83
|
+
Indy.search(source).for(:severity => 'INFO', :application => 'MyApp')
|
84
|
+
|
85
|
+
### Time Scope
|
86
|
+
|
87
|
+
Indy.search(source).after(:time => '2011-01-13 13:40:00').for(:all)
|
88
|
+
Indy.search(source).before(:time => '2010-12-31 23:59:59').for(:all)
|
89
|
+
Indy.search(source).around(:time => '2011-01-01 00:00:00', :span => 2).for(:all) # 2 minutes around New Year's Eve
|
90
|
+
Indy.search(source).within(:time => ['2011-01-01 00:00:00','2011-02-01 00:00:00']).for(:severity => 'ERROR', :application => 'MyApp')
|
91
|
+
|
92
|
+
### Partial Match
|
93
|
+
|
94
|
+
Indy.search(source).like(:message => 'Memory')
|
95
|
+
|
96
|
+
### Partial Match with multiple parameters
|
97
|
+
|
98
|
+
Indy.search(source).like(:severity => '(?:INFO|DEBUG)', :message => 'Memory')
|
99
|
+
|
100
|
+
## Process the Results
|
101
|
+
|
102
|
+
entries = Indy.search(source).for(:message => 'Entering Application')
|
103
|
+
|
104
|
+
Indy.search(source).for(:message => 'Entering Application').each do |entry|
|
105
|
+
puts entry
|
106
|
+
end
|
107
|
+
|
108
|
+
LICENSE
|
109
|
+
-------
|
110
|
+
|
111
|
+
(The MIT License)
|
112
|
+
|
113
|
+
Copyright (c) 2010 Franklin Webber
|
114
|
+
|
115
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
116
|
+
a copy of this software and associated documentation files (the
|
117
|
+
'Software'), to deal in the Software without restriction, including
|
118
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
119
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
120
|
+
permit persons to whom the Software is furnished to do so, subject to
|
121
|
+
the following conditions:
|
122
|
+
|
123
|
+
The above copyright notice and this permission notice shall be
|
124
|
+
included in all copies or substantial portions of the Software.
|
125
|
+
|
126
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
127
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
128
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
129
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
130
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
131
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
132
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rspec/core'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
require "cucumber/rake/task"
|
5
|
+
require "yard"
|
6
|
+
require "city"
|
7
|
+
|
8
|
+
desc 'Default: run tests'
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
desc "Run specs"
|
12
|
+
RSpec::Core::RakeTask.new do |t|
|
13
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
14
|
+
# Put spec opts in a file named .rspec in root
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Run performance specs"
|
18
|
+
RSpec::Core::RakeTask.new(:perf) do |t|
|
19
|
+
t.pattern = "./performance/**/*_spec.rb"
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Run features"
|
23
|
+
Cucumber::Rake::Task.new(:features) do |task|
|
24
|
+
task.cucumber_opts = ["features", "-f progress"]
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Run all reports, specs and features"
|
28
|
+
task :all do
|
29
|
+
puts "\nProfiling report"
|
30
|
+
Rake::Task['perf'].invoke
|
31
|
+
puts "\nCode Coverage report"
|
32
|
+
Rake::Task['coverage'].invoke
|
33
|
+
puts "\nFlog results"
|
34
|
+
Rake::Task['flog'].invoke
|
35
|
+
puts "\nSpec Tests"
|
36
|
+
Rake::Task['spec'].invoke
|
37
|
+
puts "\nCucumber features"
|
38
|
+
Rake::Task['features'].invoke
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "Run tests"
|
42
|
+
task :test do
|
43
|
+
Rake::Task['spec'].invoke
|
44
|
+
Rake::Task['features'].invoke
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Flog the code! (*nix only)"
|
48
|
+
task :flog do
|
49
|
+
system('find lib -name \*.rb | xargs flog')
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "Detailed Flog report! (*nix only)"
|
53
|
+
task :flog_detail do
|
54
|
+
system('find lib -name \*.rb | xargs flog -d')
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "Generate code coverage"
|
58
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
59
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
60
|
+
t.rcov = true
|
61
|
+
t.rcov_opts = ['--exclude', 'spec', '--exclude', 'gems', '-T']
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
YARD::Rake::CitydocTask.new do |t|
|
66
|
+
t.files = ['features/**/*', 'lib/**/*.rb']
|
67
|
+
t.options = ['--private']
|
68
|
+
end
|
data/cucumber.yml
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
@time @after
|
2
|
+
Feature: Finding log messages after a particular time
|
3
|
+
As an Indy user I am able to find all log messages that have happened after a specified time
|
4
|
+
|
5
|
+
Background:
|
6
|
+
Given the following log:
|
7
|
+
"""
|
8
|
+
2000-09-07 14:07:41 INFO MyApp - Entering application.
|
9
|
+
2000-09-07 14:07:42 DEBUG MyApp - Focusing application.
|
10
|
+
2000-09-07 14:07:43 DEBUG MyApp - Blurring application.
|
11
|
+
2000-09-07 14:07:44 WARN MyApp - Low on Memory.
|
12
|
+
2000-09-07 14:07:45 ERROR MyApp - Out of Memory.
|
13
|
+
2000-09-07 14:07:46 INFO MyApp - Exiting application.
|
14
|
+
"""
|
15
|
+
|
16
|
+
|
17
|
+
Scenario: Count of entries after a specified time
|
18
|
+
When searching the log for all entries after the time 2000-09-07 14:07:44
|
19
|
+
Then I expect to have found 2 log entries
|
20
|
+
|
21
|
+
Scenario: Count of entries after and including a specified time
|
22
|
+
When searching the log for all entries after and including the time 2000-09-07 14:07:44
|
23
|
+
Then I expect to have found 3 log entries
|
24
|
+
|
25
|
+
|
26
|
+
Scenario: Count of entries after a specified time
|
27
|
+
When searching the log for all entries after the time 2000-09-07 14:07:40
|
28
|
+
Then I expect to have found 6 log entries
|
29
|
+
|
30
|
+
|
31
|
+
Scenario: Particular entry after the specified time
|
32
|
+
When searching the log for all entries after the time 2000-09-07 14:07:41
|
33
|
+
Then I expect the first entry to be:
|
34
|
+
"""
|
35
|
+
2000-09-07 14:07:42 DEBUG MyApp - Focusing application.
|
36
|
+
"""
|
37
|
+
|
38
|
+
|
39
|
+
Scenario: No entries after the specified time
|
40
|
+
When searching the log for all entries after the time 2000-09-07 14:07:50
|
41
|
+
Then I expect to have found no log entries
|
@@ -0,0 +1,33 @@
|
|
1
|
+
@application
|
2
|
+
Feature: Finding log entries by application
|
3
|
+
As an Indy user I am able to create an instance and find all logs related to a particular application.
|
4
|
+
|
5
|
+
Background:
|
6
|
+
Given the following log:
|
7
|
+
"""
|
8
|
+
2000-09-07 14:07:41 INFO MyApp - Entering application.
|
9
|
+
|
10
|
+
2000-09-07 14:07:41 INFO MyApp - Exiting application.
|
11
|
+
"""
|
12
|
+
|
13
|
+
|
14
|
+
Scenario: Count of entries for a specific application
|
15
|
+
When searching the log for the application 'MyApp'
|
16
|
+
Then I expect to have found 2 log entries
|
17
|
+
|
18
|
+
|
19
|
+
Scenario: Particular entry for a specific application
|
20
|
+
When searching the log for the application 'MyApp'
|
21
|
+
Then I expect the first entry to be:
|
22
|
+
"""
|
23
|
+
2000-09-07 14:07:41 INFO MyApp - Entering application.
|
24
|
+
"""
|
25
|
+
Then I expect the last entry to be:
|
26
|
+
"""
|
27
|
+
2000-09-07 14:07:41 INFO MyApp - Exiting application.
|
28
|
+
"""
|
29
|
+
|
30
|
+
|
31
|
+
Scenario: No entries for a specific application
|
32
|
+
When searching the log for the application 'YourApp'
|
33
|
+
Then I expect to have found no log entries
|
@@ -0,0 +1,34 @@
|
|
1
|
+
@time @around
|
2
|
+
Feature: Finding log messages around a particular time
|
3
|
+
As an Indy user I am able to find all log messages that have happened around a specified time
|
4
|
+
|
5
|
+
Background:
|
6
|
+
Given the following log:
|
7
|
+
"""
|
8
|
+
2000-09-07 14:07:41 INFO MyApp - Entering application.
|
9
|
+
2000-09-07 14:17:43 DEBUG MyApp - Focusing application.
|
10
|
+
2000-09-07 14:27:43 DEBUG MyApp - Blurring application.
|
11
|
+
2000-09-07 14:37:43 WARN MyApp - Low on Memory.
|
12
|
+
2000-09-07 14:47:43 ERROR MyApp - Out of Memory.
|
13
|
+
2000-09-07 14:57:46 INFO MyApp - Exiting application.
|
14
|
+
"""
|
15
|
+
|
16
|
+
Scenario: Count of entries for a time span around a specified time
|
17
|
+
When searching the log for all entries 31 minutes around the time 2000-09-07 14:27:43
|
18
|
+
Then I expect to have found 3 log entries
|
19
|
+
|
20
|
+
Scenario: Count of entries for a time span before a specified time
|
21
|
+
When searching the log for all entries 11 minutes before the time 2000-09-07 14:27:43
|
22
|
+
Then I expect to have found 1 log entries
|
23
|
+
|
24
|
+
Scenario: Count of entries for a time span after a specified time
|
25
|
+
When searching the log for all entries 31 minutes after the time 2000-09-07 14:27:43
|
26
|
+
Then I expect to have found 3 log entries
|
27
|
+
|
28
|
+
Scenario: Count of entries for a time span before and including a specified time
|
29
|
+
When searching the log for all entries 11 minutes before and including the time 2000-09-07 14:47:43
|
30
|
+
Then I expect to have found 2 log entries
|
31
|
+
|
32
|
+
Scenario: Count of entries for a time span after and including a specified time
|
33
|
+
When searching the log for all entries 31 minutes after and including the time 2000-09-07 14:17:43
|
34
|
+
Then I expect to have found 3 log entries
|
@@ -0,0 +1,34 @@
|
|
1
|
+
@time @before
|
2
|
+
Feature: Finding log messages before a particular time
|
3
|
+
As an Indy user I am able to find all log messages that have happened before a specified time
|
4
|
+
|
5
|
+
Background:
|
6
|
+
Given the following log:
|
7
|
+
"""
|
8
|
+
2000-09-07 14:07:41 INFO MyApp - Entering application.
|
9
|
+
2000-09-07 14:07:42 DEBUG MyApp - Focusing application.
|
10
|
+
2000-09-07 14:07:43 DEBUG MyApp - Blurring application.
|
11
|
+
2000-09-07 14:07:44 WARN MyApp - Low on Memory.
|
12
|
+
2000-09-07 14:07:45 ERROR MyApp - Out of Memory.
|
13
|
+
2000-09-07 14:07:46 INFO MyApp - Exiting application.
|
14
|
+
"""
|
15
|
+
|
16
|
+
|
17
|
+
Scenario: Count of entries before a specifed time
|
18
|
+
When searching the log for all entries before the time 2000-09-07 14:07:44
|
19
|
+
Then I expect to have found 3 log entries
|
20
|
+
|
21
|
+
Scenario: Count of entries before and including a specifed time
|
22
|
+
When searching the log for all entries before and including the time 2000-09-07 14:07:44
|
23
|
+
Then I expect to have found 4 log entries
|
24
|
+
|
25
|
+
Scenario: Particular entry before the specified time
|
26
|
+
When searching the log for all entries before the time 2000-09-07 14:07:43
|
27
|
+
Then I expect the last entry to be:
|
28
|
+
"""
|
29
|
+
2000-09-07 14:07:42 DEBUG MyApp - Focusing application.
|
30
|
+
"""
|
31
|
+
|
32
|
+
Scenario: No entries before the specified time
|
33
|
+
When searching the log for all entries before the time 2000-09-07 14:07:40
|
34
|
+
Then I expect to have found no log entries
|
@@ -0,0 +1,52 @@
|
|
1
|
+
@log_level
|
2
|
+
Feature: Finding log entries with a custom pattern
|
3
|
+
As an Indy user I am able to find all log entries that match my custom log pattern
|
4
|
+
|
5
|
+
Background:
|
6
|
+
Given the following log:
|
7
|
+
"""
|
8
|
+
14:07:41 INFO MyApp#initialize - Entering application.
|
9
|
+
14:07:42 DEBUG MyApp#panel - Focusing application.
|
10
|
+
14:07:43 DEBUG MyApp#panel - Blurring application.
|
11
|
+
14:07:44 WARN MyApp#allocate - Low on Memory.
|
12
|
+
14:07:45 ERROR MyApp#allocate - Out of Memory.
|
13
|
+
14:07:46 INFO MyApp#exit - Exiting application.
|
14
|
+
"""
|
15
|
+
And the custom pattern (time,severity,application,method,message):
|
16
|
+
"""
|
17
|
+
^(\d{2}:\d{2}:\d{2})\s*(INFO|DEBUG|WARN|ERROR)\s*([^#]+)#([^\s]+)\s*-\s*(.+)$
|
18
|
+
"""
|
19
|
+
|
20
|
+
Scenario: Count of entries at specified log level
|
21
|
+
When searching the log for the log severity INFO
|
22
|
+
Then I expect to have found 2 log entries
|
23
|
+
|
24
|
+
|
25
|
+
Scenario: Particular entry at the specified log level
|
26
|
+
When searching the log for the log severity INFO
|
27
|
+
Then I expect the first entry to be:
|
28
|
+
"""
|
29
|
+
14:07:41 INFO MyApp#initialize - Entering application.
|
30
|
+
"""
|
31
|
+
And I expect the last entry to be:
|
32
|
+
"""
|
33
|
+
14:07:46 INFO MyApp#exit - Exiting application.
|
34
|
+
"""
|
35
|
+
|
36
|
+
|
37
|
+
Scenario: No entries at the specified log level
|
38
|
+
When searching the log for the log severity SEVERE
|
39
|
+
Then I expect to have found no log entries
|
40
|
+
|
41
|
+
|
42
|
+
Scenario: Find entries at the custom field
|
43
|
+
When searching the log for the exact match of custom field method "allocate"
|
44
|
+
Then I expect to have found 2 log entries
|
45
|
+
Then I expect the first entry to be:
|
46
|
+
"""
|
47
|
+
14:07:44 WARN MyApp#allocate - Low on Memory.
|
48
|
+
"""
|
49
|
+
And I expect the last entry to be:
|
50
|
+
"""
|
51
|
+
14:07:45 ERROR MyApp#allocate - Out of Memory.
|
52
|
+
"""
|