danielsdeleo-teeth 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/LICENSE +11 -0
  2. data/README.rdoc +107 -10
  3. data/Rakefile +47 -31
  4. data/VERSION.yml +4 -0
  5. data/doc/classes/String.html +182 -0
  6. data/doc/classes/Teeth/DuplicateDefinitionError.html +113 -0
  7. data/doc/classes/Teeth/DuplicateRuleError.html +113 -0
  8. data/doc/classes/Teeth/InvalidDefaultDefinitionName.html +113 -0
  9. data/doc/classes/Teeth/InvalidExtensionDirectory.html +113 -0
  10. data/doc/classes/Teeth/RuleStatement.html +291 -0
  11. data/doc/classes/Teeth/RuleStatementGroup.html +195 -0
  12. data/doc/classes/Teeth/Scanner.html +535 -0
  13. data/doc/classes/Teeth/ScannerDefinition.html +253 -0
  14. data/doc/classes/Teeth/ScannerDefinitionArgumentError.html +113 -0
  15. data/doc/classes/Teeth/ScannerDefinitionGroup.html +269 -0
  16. data/doc/classes/Teeth/ScannerError.html +111 -0
  17. data/doc/classes/Teeth.html +129 -0
  18. data/doc/created.rid +1 -0
  19. data/doc/files/README_rdoc.html +314 -0
  20. data/doc/files/ext/scan_apache_logs/scan_apache_logs_yy_c.html +101 -0
  21. data/doc/files/ext/scan_rails_logs/scan_rails_logs_yy_c.html +101 -0
  22. data/doc/files/lib/rule_statement_rb.html +101 -0
  23. data/doc/files/lib/scanner_definition_rb.html +101 -0
  24. data/doc/files/lib/scanner_rb.html +108 -0
  25. data/doc/files/lib/teeth_rb.html +111 -0
  26. data/doc/fr_class_index.html +39 -0
  27. data/doc/fr_file_index.html +33 -0
  28. data/doc/fr_method_index.html +60 -0
  29. data/doc/index.html +24 -0
  30. data/doc/rdoc-style.css +208 -0
  31. data/ext/scan_apache_logs/Makefile +158 -0
  32. data/ext/scan_apache_logs/extconf.rb +3 -0
  33. data/ext/scan_apache_logs/scan_apache_logs.yy +267 -0
  34. data/ext/scan_apache_logs/scan_apache_logs.yy.c +8355 -0
  35. data/ext/scan_rails_logs/Makefile +158 -0
  36. data/ext/scan_rails_logs/extconf.rb +3 -0
  37. data/ext/scan_rails_logs/scan_rails_logs.yy +376 -0
  38. data/ext/scan_rails_logs/scan_rails_logs.yy.c +11127 -0
  39. data/lib/rule_statement.rb +61 -0
  40. data/lib/scanner.rb +98 -0
  41. data/lib/scanner_definition.rb +116 -0
  42. data/lib/teeth.rb +5 -1
  43. data/scanners/scan_apache_logs.rb +27 -0
  44. data/scanners/scan_rails_logs.rb +70 -0
  45. data/spec/fixtures/rails_1x.log +59 -0
  46. data/spec/fixtures/rails_22.log +12 -0
  47. data/spec/fixtures/rails_22_cached.log +10 -0
  48. data/spec/fixtures/rails_unordered.log +24 -0
  49. data/spec/playground/show_apache_processing.rb +13 -0
  50. data/spec/spec_helper.rb +6 -1
  51. data/spec/unit/rule_statement_spec.rb +60 -0
  52. data/spec/unit/{tokenize_apache_spec.rb → scan_apache_spec.rb} +16 -11
  53. data/spec/unit/scan_rails_logs_spec.rb +90 -0
  54. data/spec/unit/scaner_definition_spec.rb +65 -0
  55. data/spec/unit/scanner_spec.rb +109 -0
  56. data/teeth.gemspec +31 -0
  57. data/templates/tokenizer.yy.erb +168 -0
  58. metadata +60 -15
  59. data/ext/extconf.rb +0 -4
  60. data/ext/tokenize_apache_logs.yy +0 -215
  61. data/ext/tokenize_apache_logs.yy.c +0 -12067
@@ -0,0 +1,90 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require "teeth/scan_rails_logs"
3
+ # special shout out to Willem van Bergen, author of request-log-analyzer:
4
+ # http://github.com/wvanbergen/request-log-analyzer/
5
+ # Thanks for the log samples!
6
+
7
+ describe "Rails Request Log Lexer", "when lexing Rails 1.x logs" do
8
+
9
+ it "should extract the Controller, action, IP, timestamp and HTTP verb from a ``Processing'' line" do
10
+ line = %q{Processing PageController#demo (for 127.0.0.1 at 2008-12-10 16:28:09) [GET]}
11
+ result = line.scan_rails_logs
12
+ result[:teaser].first.should == "Processing"
13
+ result[:controller_action].first.should == "PageController#demo"
14
+ result[:ipv4_addr].first.should == "127.0.0.1"
15
+ result[:http_method].first.should == "GET"
16
+ result[:datetime].first.should == "2008-12-10 16:28:09"
17
+ end
18
+
19
+ it "should give a hash with :cache_hit => not falsy value for a cache hit" do
20
+ cache_hit = %q{Filter chain halted as [#<ActionController::Caching::Actions::ActionCacheFilter:0x2a999ad620 @check=nil, @options={:store_options=>{}, :layout=>nil, :cache_path=>#<Proc:0x0000002a999b8890@/app/controllers/cached_controller.rb:8>}>] rendered_or_redirected.}
21
+ cache_hit.scan_rails_logs[:cache_hit].should be_true
22
+ cache_hit.scan_rails_logs[:teaser].first.should == "Filter chain halted"
23
+ end
24
+
25
+ it "should extract an error, error_message, line of code, source code file, and stack_trace from a ``RuntimeError'' line" do
26
+ line = %q{RuntimeError (Cannot destroy employee): /app/models/employee.rb:198:in `before_destroy' }
27
+ result = line.scan_rails_logs
28
+ puts "###\n" + result.inspect
29
+ result[:error].first.should == "RuntimeError"
30
+ result[:error_message].first.should == "Cannot destroy employee"
31
+ result[:file_and_line].first.should == "/app/models/employee.rb:198"
32
+ end
33
+
34
+ it "should extract the duration, view duration, db duration, HTTP status code, and url from a ``Completed'' line for Rails 1.x" do
35
+ rails_1x = %q{Completed in 0.21665 (4 reqs/sec) | Rendering: 0.00926 (4%) | DB: 0.00000 (0%) | 200 OK [http://demo.nu/employees]}
36
+ result = rails_1x.scan_rails_logs
37
+ puts "\n==completed (1.x): " + result.inspect
38
+ result[:teaser].first.should == "Completed in"
39
+ result[:duration_s].first.should == "0.21665"
40
+ result[:view_s].first.should == "0.00926"
41
+ result[:db_s].first.should == "0.00000"
42
+ result[:http_response].first.should == "200"
43
+ result[:url].first.should == "http://demo.nu/employees"
44
+ end
45
+
46
+ it "should extract the relevant components from a ``Completed'' line for Rails 2.x" do
47
+ rails_2x = %q{Completed in 614ms (View: 120, DB: 31) | 200 OK [http://floorplanner.local/demo]}
48
+ result = rails_2x.scan_rails_logs
49
+ puts "\n==completed (2.x): " + result.inspect
50
+ result[:teaser].first.should == "Completed in"
51
+ result[:duration_ms].first.should == "614"
52
+ result[:view_ms].first.should == "120"
53
+ result[:db_ms].first.should == "31"
54
+ result[:http_response].first.should == "200"
55
+ result[:url].first.should == "http://floorplanner.local/demo"
56
+ end
57
+
58
+ it "should extract the duration and partial from a ``Rendered'' line for rails 2.x" do
59
+ rendered_2x = "Rendered shared/_analytics (0.2ms)"
60
+ #puts "(rendered 2.x): " + rendered_2x.scan_rails_logs.inspect
61
+ rendered_2x.scan_rails_logs[:partial].first.should == "shared/_analytics"
62
+ rendered_2x.scan_rails_logs[:render_duration_ms].first.should == "0.2"
63
+ end
64
+
65
+ it "should extract the duration and partial from a ``Rendered'' line for rails 1.x" do
66
+ rendered_1x = "Rendered layouts/_doc_type (0.00001)"
67
+ #puts "(rendered 1.x): " + rendered_1x.scan_rails_logs.inspect
68
+ rendered_1x.scan_rails_logs[:partial].first.should == "layouts/_doc_type"
69
+ rendered_1x.scan_rails_logs[:render_duration_s].first.should == "0.00001"
70
+ end
71
+
72
+ it "should skip session id lines" do
73
+ session_id = %q{Session ID: BAh7CToMcmVmZXJlciIbL3ByaXNjaWxsYS9wZW9wbGUvMjM1MCIKZmxhc2hJ}
74
+ session_id.scan_rails_logs.keys.map { |k| k.to_s}.sort.should == ["id", "message"]
75
+ end
76
+
77
+ it "should not return a teaser for session id continuation lines" do
78
+ session_id_contd = "ZWR7ADoNbGFuZ3VhZ2VvOhNMb2NhbGU6Ok9iamVjdBI6CUB3aW4wOg1AY291"
79
+ session_id_contd.scan_rails_logs[:teaser].should be_nil
80
+ end
81
+
82
+ it "should give a non falsy value for :end_session_id at for the last line of a session id" do
83
+ session_id_end_1 = "bmxfTkw6DEBzY3JpcHQwOg5AZmFsbGJhY2sw--48cbe3788ef27f6005f8e999610a42af6e90ffb3"
84
+ session_id_end_1.scan_rails_logs[:end_session_id].should_not be_nil
85
+ session_id_end_2 = "X2lkaQIyBw==--3ad1948559448522a49d289a2a89dc7ccbe8847a"
86
+ session_id_end_2.scan_rails_logs[:end_session_id].should_not be_nil
87
+ end
88
+
89
+
90
+ end
@@ -0,0 +1,65 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+
5
+ describe ScannerDefinition do
6
+
7
+ it "should generate text for flex definitions" do
8
+ defn = ScannerDefinition.new "IP4_OCTET", "[0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]"
9
+ defn.scanner_code.should == "IP4_OCTET [0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]"
10
+ end
11
+
12
+ it "should complain if given a :start_condition option and a regex" do
13
+ fail = lambda {ScannerDefinition.new "FAIL", "FAIL", :start_condition => :inclusive}
14
+ fail.should raise_error ScannerDefinitionArgumentError
15
+ end
16
+
17
+ it "should add %s to the beginning of the definition for option :start_condition => :inclusive" do
18
+ defn = ScannerDefinition.new "SPECIAL_STATE", :start_condition => :inclusive
19
+ defn.scanner_code.should == "%s SPECIAL_STATE"
20
+ end
21
+
22
+ end
23
+
24
+ describe ScannerDefinitionGroup do
25
+ before(:each) do
26
+ @defn_group = ScannerDefinitionGroup.new
27
+ end
28
+
29
+ it "should hold multiple definitions" do
30
+ @defn_group.add "IP4_OCTET", "[0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]"
31
+ @defn_group.add "WDAY", "mon|tue|wed|thu|fri|sat|sun"
32
+ @defn_group.should have(2).definitions
33
+ end
34
+
35
+ it "should use method missing magic for sugary definitions" do
36
+ @defn_group.IP4_OCTET "[0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]"
37
+ @defn_group.scanner_defns.first.scanner_code.should == "IP4_OCTET [0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]"
38
+ end
39
+
40
+ it "should reject duplicate definitions" do
41
+ @defn_group.add("WS", '[\000-\s]')
42
+ lambda { @defn_group.add("WS", '[\000-\s]') }.should raise_error DuplicateDefinitionError
43
+ end
44
+
45
+ it "should add a default set of definitions" do
46
+ @defn_group.defaults_for(:whitespace, :ip)
47
+ @defn_group.defn_names.should == ["WS", "NON_WS", "IP4_OCT", "HOST"]
48
+ end
49
+
50
+ it "should explode if requested to add default definitions that don't exist" do
51
+ lambda { @defn_group.defaults_for(:foobarbaz) }.should raise_error InvalidDefaultDefinitionName
52
+ end
53
+
54
+ it "should not error if conflicting user definitions exist when loading defaults" do
55
+ @defn_group.add "WS", '[\000-\s]'
56
+ lambda {@defn_group.load_default_definitions_for(:whitespace)}.should_not raise_error
57
+ end
58
+
59
+ it "should not override user definitions when loading defaults" do
60
+ @defn_group.add "WS", "a-telltale-sign"
61
+ @defn_group.load_default_definitions_for(:whitespace)
62
+ @defn_group.reject { |defn| defn.name != "WS" }.first.regex.should == "a-telltale-sign"
63
+ end
64
+
65
+ end
@@ -0,0 +1,109 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require "fileutils"
3
+ include FileUtils
4
+ describe Scanner do
5
+ TEST_EXT_DIR = File.dirname(__FILE__) + "/test_ext_dir"
6
+
7
+ IPV4_ACTION_TEXT =
8
+ %q|{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT} {
9
+ KVPAIR ipv4_addr = {"ipv4_addr", yytext};
10
+ return ipv4_addr;
11
+ }|
12
+
13
+ def clean_test_scanner_dir
14
+ rm_rf TEST_EXT_DIR
15
+ end
16
+
17
+ before(:all) do
18
+ clean_test_scanner_dir
19
+ end
20
+
21
+ before(:each) do
22
+ @scanner = Scanner.new(:rspec_awesome)
23
+ end
24
+
25
+ after(:all) do
26
+ clean_test_scanner_dir
27
+ end
28
+
29
+ it "should generate the code for an extconf file" do
30
+ expected = 'require "mkmf"' + "\n" + '$CFLAGS += " -Wall"' + "\n" +
31
+ 'create_makefile "teeth/scan_rspec_awesome", "./"' + "\n"
32
+ @scanner.extconf.should == expected
33
+ end
34
+
35
+ it "should create a new directory for the extension" do
36
+ scanner = Scanner.new(:rspec_awesomeness, TEST_EXT_DIR)
37
+ File.exist?(TEST_EXT_DIR).should be_true
38
+ end
39
+
40
+ it "should initialize with a name for for the tokenizer function and method" do
41
+ scanner = Scanner.new(:rails_dev_logs)
42
+ scanner.scanner_name.should == "scan_rails_dev_logs"
43
+ scanner.main_function_name.should == "t_scan_rails_dev_logs"
44
+ scanner.init_function_name.should == "Init_scan_rails_dev_logs"
45
+ scanner.function_prefix.should == "rails_dev_logs_yy"
46
+ scanner.entry_point.should == "scan_rails_dev_logs"
47
+ end
48
+
49
+ it "should format rdoc for the C function which corresponds to the ruby method" do
50
+ @scanner.rdoc = <<-RDOC
51
+ Premature optimization
52
+ is the root of
53
+ all evil.
54
+ RDOC
55
+ @scanner.rdoc.should == "/* Premature optimization\n * is the root of\n * all evil. */"
56
+ end
57
+
58
+ it "should accept a ``global'' option to include UUID generation or not"
59
+
60
+ it "should store scanner definitions" do
61
+ @scanner.define "IP4_OCTET", "[0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]"
62
+ @scanner.scanner_defns.should have(1).definition
63
+ end
64
+
65
+ it "should accept definitions in a block" do
66
+ @scanner.definitions do |d|
67
+ d.add "IP4_OCTET", "[0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]"
68
+ d.add "WDAY", "mon|tue|wed|thu|fri|sat|sun"
69
+ end
70
+ @scanner.scanner_defns.should have(2).definitions
71
+ end
72
+
73
+ it "should generate scanner rule statements, defaulting to returning a KVPAIR of rule name, yytext" do
74
+ @scanner.rule :ipv4_addr, '{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT}'
75
+ @scanner.scanner_rules.first.scanner_code.should == IPV4_ACTION_TEXT
76
+ end
77
+
78
+ it "should accept rule statments in a block" do
79
+ @scanner.rules do |rules|
80
+ rules.add :ipv4_addr, '{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT}'
81
+ end
82
+ #@scanner.scanner_rules.first.scanner_code.should == IPV4_ACTION_TEXT
83
+ @scanner.scanner_rules.should have(1).scanner_rule
84
+ end
85
+
86
+ it "should render a scanner scanner from the template" do
87
+ @scanner.load_default_definitions_for(:whitespace, :ip, :web)
88
+ @scanner.rules do |rule|
89
+ rule.ipv4_addr '{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT}'
90
+ rule.relative_url '{REL_URL}'
91
+ end
92
+ result = @scanner.generate
93
+ # real test is if scanner compiles and passes its own tests
94
+ result.should_not match(Regexp.new(Regexp.quote '<%='))
95
+ end
96
+
97
+ it "should write the scanner and extconf files in the ext directory" do
98
+ scanner = Scanner.new(:rspec_awesomeness, TEST_EXT_DIR)
99
+ scanner.load_default_definitions_for(:whitespace, :ip, :web)
100
+ scanner.rules do |rule|
101
+ rule.ipv4_addr '{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT}'
102
+ rule.relative_url '{REL_URL}'
103
+ end
104
+ scanner.write!
105
+ File.exist?(TEST_EXT_DIR + "/extconf.rb").should be_true
106
+ File.exist?(TEST_EXT_DIR + "/scan_rspec_awesomeness.yy").should be_true
107
+ end
108
+
109
+ end
data/teeth.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{teeth}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Daniel DeLeo"]
9
+ s.date = %q{2009-03-29}
10
+ s.description = %q{Fast log file parsing in Ruby}
11
+ s.email = %q{ddeleo@basecommander.net}
12
+ s.extensions = ["ext/scan_apache_logs/extconf.rb", "ext/scan_rails_logs/extconf.rb"]
13
+ s.extra_rdoc_files = ["README.rdoc"]
14
+ s.files = ["LICENSE", "README.rdoc", "Rakefile", "VERSION.yml", "doc/classes/String.html", "doc/classes/Teeth.html", "doc/classes/Teeth/DuplicateDefinitionError.html", "doc/classes/Teeth/DuplicateRuleError.html", "doc/classes/Teeth/InvalidDefaultDefinitionName.html", "doc/classes/Teeth/InvalidExtensionDirectory.html", "doc/classes/Teeth/RuleStatement.html", "doc/classes/Teeth/RuleStatementGroup.html", "doc/classes/Teeth/Scanner.html", "doc/classes/Teeth/ScannerDefinition.html", "doc/classes/Teeth/ScannerDefinitionArgumentError.html", "doc/classes/Teeth/ScannerDefinitionGroup.html", "doc/classes/Teeth/ScannerError.html", "doc/created.rid", "doc/files/README_rdoc.html", "doc/files/ext/scan_apache_logs/scan_apache_logs_yy_c.html", "doc/files/ext/scan_rails_logs/scan_rails_logs_yy_c.html", "doc/files/lib/rule_statement_rb.html", "doc/files/lib/scanner_definition_rb.html", "doc/files/lib/scanner_rb.html", "doc/files/lib/teeth_rb.html", "doc/fr_class_index.html", "doc/fr_file_index.html", "doc/fr_method_index.html", "doc/index.html", "doc/rdoc-style.css", "ext/scan_apache_logs/Makefile", "ext/scan_apache_logs/extconf.rb", "ext/scan_apache_logs/scan_apache_logs.yy", "ext/scan_apache_logs/scan_apache_logs.yy.c", "ext/scan_rails_logs/Makefile", "ext/scan_rails_logs/extconf.rb", "ext/scan_rails_logs/scan_rails_logs.yy", "ext/scan_rails_logs/scan_rails_logs.yy.c", "lib/rule_statement.rb", "lib/scanner.rb", "lib/scanner_definition.rb", "lib/teeth.rb", "scanners/scan_apache_logs.rb", "scanners/scan_rails_logs.rb", "spec/fixtures/rails_1x.log", "spec/fixtures/rails_22.log", "spec/fixtures/rails_22_cached.log", "spec/fixtures/rails_unordered.log", "spec/playground/show_apache_processing.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/rule_statement_spec.rb", "spec/unit/scan_apache_spec.rb", "spec/unit/scan_rails_logs_spec.rb", "spec/unit/scaner_definition_spec.rb", "spec/unit/scanner_spec.rb", "teeth.gemspec", "templates/tokenizer.yy.erb"]
15
+ s.has_rdoc = true
16
+ s.homepage = %q{http://github.com/danielsdeleo/teeth}
17
+ s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
18
+ s.require_paths = [["lib"]]
19
+ s.rubygems_version = %q{1.3.1}
20
+ s.summary = %q{Fast log file parsing in Ruby}
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 2
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ else
28
+ end
29
+ else
30
+ end
31
+ end
@@ -0,0 +1,168 @@
1
+ %option prefix="<%= scanner.function_prefix %>"
2
+ %option full
3
+ %option never-interactive
4
+ %option read
5
+ %option nounput
6
+ %option noyywrap noreject noyymore nodefault
7
+ %{
8
+ #include <ruby.h>
9
+ #include <uuid/uuid.h>
10
+ /* Data types */
11
+ typedef struct {
12
+ char *key;
13
+ char *value;
14
+ } KVPAIR;
15
+ const KVPAIR EOF_KVPAIR = {"EOF", "EOF"};
16
+ /* prototypes */
17
+ char *strip_ends(char *);
18
+ VALUE <%= scanner.main_function_name %>(VALUE);
19
+ void new_uuid(char *str_ptr);
20
+ void raise_error_for_string_too_long(VALUE string);
21
+ void include_message_in_token_hash(VALUE message, VALUE token_hash);
22
+ void add_uuid_to_token_hash(VALUE token_hash);
23
+ void push_kv_pair_to_hash(KVPAIR key_value, VALUE token_hash);
24
+ void concat_word_to_string(KVPAIR key_value, VALUE token_hash);
25
+ /* Set the scanner name, and return type */
26
+ #define YY_DECL KVPAIR <%= scanner.entry_point %>(void)
27
+ #define yyterminate() return EOF_KVPAIR
28
+ /* Ruby 1.8 and 1.9 compatibility */
29
+ #if !defined(RSTRING_LEN)
30
+ # define RSTRING_LEN(x) (RSTRING(x)->len)
31
+ # define RSTRING_PTR(x) (RSTRING(x)->ptr)
32
+ #endif
33
+
34
+ %}
35
+
36
+ /* Definitions */
37
+
38
+ CATCHALL (.|"\n")
39
+
40
+ <% scanner.scanner_defns.each do |scanner_defn| %>
41
+ <%= scanner_defn.scanner_code %>
42
+ <% end %>
43
+
44
+ %%
45
+ /*
46
+ Actions
47
+ */
48
+
49
+ <% scanner.scanner_rules.each do |scanner_rule| %>
50
+ <%= scanner_rule.scanner_code %>
51
+ <% end %>
52
+ {CATCHALL} /* ignore */
53
+ %%
54
+
55
+ char *strip_ends(char *string) {
56
+ string[yyleng-1] = '\0';
57
+ ++string;
58
+ return string;
59
+ }
60
+
61
+ void uuid_unparse_upper_sans_dash(const uuid_t uu, char *out)
62
+ {
63
+ sprintf(out,
64
+ "%02X%02X%02X%02X"
65
+ "%02X%02X"
66
+ "%02X%02X"
67
+ "%02X%02X"
68
+ "%02X%02X%02X%02X%02X%02X",
69
+ uu[0], uu[1], uu[2], uu[3],
70
+ uu[4], uu[5],
71
+ uu[6], uu[7],
72
+ uu[8], uu[9],
73
+ uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
74
+ }
75
+
76
+ void new_uuid(char *str_ptr){
77
+ uuid_t new_uuid;
78
+ uuid_generate_time(new_uuid);
79
+ uuid_unparse_upper_sans_dash(new_uuid, str_ptr);
80
+ }
81
+
82
+ void raise_error_for_string_too_long(VALUE string){
83
+ if( RSTRING_LEN(string) > 1000000){
84
+ rb_raise(rb_eArgError, "string too long for <%=scanner.scanner_name %>! max length is 1,000,000 chars");
85
+ }
86
+ }
87
+
88
+ <%= scanner.rdoc %>
89
+ VALUE <%= scanner.main_function_name %>(VALUE self) {
90
+ KVPAIR kv_result;
91
+ int scan_complete = 0;
92
+ int building_words_to_string = 0;
93
+ VALUE token_hash = rb_hash_new();
94
+
95
+ BEGIN(INITIAL);
96
+
97
+ /* error out on absurdly large strings */
98
+ raise_error_for_string_too_long(self);
99
+ /* {:message => self()} */
100
+ include_message_in_token_hash(self, token_hash);
101
+ /* {:id => UUID} */
102
+ add_uuid_to_token_hash(token_hash);
103
+ yy_scan_string(RSTRING_PTR(self));
104
+ while (scan_complete == 0) {
105
+ kv_result = <%= scanner.entry_point %>();
106
+ if (kv_result.key == "EOF"){
107
+ scan_complete = 1;
108
+ }
109
+ else if (kv_result.key == "strings"){
110
+ /* build a string until we get a non-word */
111
+ if (building_words_to_string == 0){
112
+ building_words_to_string = 1;
113
+ push_kv_pair_to_hash(kv_result, token_hash);
114
+ }
115
+ else{
116
+ concat_word_to_string(kv_result, token_hash);
117
+ }
118
+ }
119
+ else {
120
+ building_words_to_string = 0;
121
+ push_kv_pair_to_hash(kv_result, token_hash);
122
+ }
123
+ }
124
+ yy_delete_buffer(YY_CURRENT_BUFFER);
125
+ return rb_obj_dup(token_hash);
126
+ }
127
+
128
+ void add_uuid_to_token_hash(VALUE token_hash) {
129
+ char new_uuid_str[33];
130
+ new_uuid(new_uuid_str);
131
+ VALUE hsh_key_id = ID2SYM(rb_intern("id"));
132
+ VALUE hsh_val_id = rb_tainted_str_new2(new_uuid_str);
133
+ rb_hash_aset(token_hash, hsh_key_id, hsh_val_id);
134
+ }
135
+
136
+ void include_message_in_token_hash(VALUE message, VALUE token_hash) {
137
+ /* {:message => self()} */
138
+ VALUE hsh_key_msg = ID2SYM(rb_intern("message"));
139
+ rb_hash_aset(token_hash, hsh_key_msg, message);
140
+ }
141
+
142
+ void concat_word_to_string(KVPAIR key_value, VALUE token_hash) {
143
+ char * space = " ";
144
+ VALUE hsh_key = ID2SYM(rb_intern(key_value.key));
145
+ VALUE hsh_value = rb_hash_aref(token_hash, hsh_key);
146
+ VALUE string = rb_ary_entry(hsh_value, -1);
147
+ rb_str_cat(string, space, 1);
148
+ rb_str_cat(string, key_value.value, yyleng);
149
+ }
150
+
151
+ void push_kv_pair_to_hash(KVPAIR key_value, VALUE token_hash) {
152
+ VALUE hsh_key = ID2SYM(rb_intern(key_value.key));
153
+ VALUE hsh_value = rb_hash_aref(token_hash, hsh_key);
154
+ VALUE ary_for_token_type = rb_ary_new();
155
+ switch (TYPE(hsh_value)) {
156
+ case T_NIL:
157
+ rb_ary_push(ary_for_token_type, rb_tainted_str_new2(key_value.value));
158
+ rb_hash_aset(token_hash, hsh_key, ary_for_token_type);
159
+ break;
160
+ case T_ARRAY:
161
+ rb_ary_push(hsh_value, rb_tainted_str_new2(key_value.value));
162
+ break;
163
+ }
164
+ }
165
+
166
+ void <%=scanner.init_function_name %>() {
167
+ rb_define_method(rb_cString, "<%= scanner.scanner_name %>", <%= scanner.main_function_name %>, 0);
168
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: danielsdeleo-teeth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel DeLeo
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-21 00:00:00 -07:00
12
+ date: 2009-03-29 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -18,24 +18,69 @@ email: ddeleo@basecommander.net
18
18
  executables: []
19
19
 
20
20
  extensions:
21
- - ext/extconf.rb
21
+ - ext/scan_apache_logs/extconf.rb
22
+ - ext/scan_rails_logs/extconf.rb
22
23
  extra_rdoc_files:
23
24
  - README.rdoc
24
25
  files:
26
+ - LICENSE
25
27
  - README.rdoc
26
28
  - Rakefile
27
- - ext/extconf.rb
28
- - ext/tokenize_apache_logs.yy
29
- - ext/tokenize_apache_logs.yy.c
29
+ - VERSION.yml
30
+ - doc/classes/String.html
31
+ - doc/classes/Teeth.html
32
+ - doc/classes/Teeth/DuplicateDefinitionError.html
33
+ - doc/classes/Teeth/DuplicateRuleError.html
34
+ - doc/classes/Teeth/InvalidDefaultDefinitionName.html
35
+ - doc/classes/Teeth/InvalidExtensionDirectory.html
36
+ - doc/classes/Teeth/RuleStatement.html
37
+ - doc/classes/Teeth/RuleStatementGroup.html
38
+ - doc/classes/Teeth/Scanner.html
39
+ - doc/classes/Teeth/ScannerDefinition.html
40
+ - doc/classes/Teeth/ScannerDefinitionArgumentError.html
41
+ - doc/classes/Teeth/ScannerDefinitionGroup.html
42
+ - doc/classes/Teeth/ScannerError.html
43
+ - doc/created.rid
44
+ - doc/files/README_rdoc.html
45
+ - doc/files/ext/scan_apache_logs/scan_apache_logs_yy_c.html
46
+ - doc/files/ext/scan_rails_logs/scan_rails_logs_yy_c.html
47
+ - doc/files/lib/rule_statement_rb.html
48
+ - doc/files/lib/scanner_definition_rb.html
49
+ - doc/files/lib/scanner_rb.html
50
+ - doc/files/lib/teeth_rb.html
51
+ - doc/fr_class_index.html
52
+ - doc/fr_file_index.html
53
+ - doc/fr_method_index.html
54
+ - doc/index.html
55
+ - doc/rdoc-style.css
56
+ - ext/scan_apache_logs/Makefile
57
+ - ext/scan_apache_logs/extconf.rb
58
+ - ext/scan_apache_logs/scan_apache_logs.yy
59
+ - ext/scan_apache_logs/scan_apache_logs.yy.c
60
+ - ext/scan_rails_logs/Makefile
61
+ - ext/scan_rails_logs/extconf.rb
62
+ - ext/scan_rails_logs/scan_rails_logs.yy
63
+ - ext/scan_rails_logs/scan_rails_logs.yy.c
64
+ - lib/rule_statement.rb
65
+ - lib/scanner.rb
66
+ - lib/scanner_definition.rb
30
67
  - lib/teeth.rb
31
- - spec/fixtures/access.log
32
- - spec/fixtures/big-access.log
33
- - spec/fixtures/big-error.log
34
- - spec/fixtures/error.log
35
- - spec/fixtures/med-error.log
68
+ - scanners/scan_apache_logs.rb
69
+ - scanners/scan_rails_logs.rb
70
+ - spec/fixtures/rails_1x.log
71
+ - spec/fixtures/rails_22.log
72
+ - spec/fixtures/rails_22_cached.log
73
+ - spec/fixtures/rails_unordered.log
74
+ - spec/playground/show_apache_processing.rb
36
75
  - spec/spec.opts
37
76
  - spec/spec_helper.rb
38
- - spec/unit/tokenize_apache_spec.rb
77
+ - spec/unit/rule_statement_spec.rb
78
+ - spec/unit/scan_apache_spec.rb
79
+ - spec/unit/scan_rails_logs_spec.rb
80
+ - spec/unit/scaner_definition_spec.rb
81
+ - spec/unit/scanner_spec.rb
82
+ - teeth.gemspec
83
+ - templates/tokenizer.yy.erb
39
84
  has_rdoc: true
40
85
  homepage: http://github.com/danielsdeleo/teeth
41
86
  post_install_message:
@@ -46,9 +91,9 @@ require_paths:
46
91
  - - lib
47
92
  required_ruby_version: !ruby/object:Gem::Requirement
48
93
  requirements:
49
- - - <=
94
+ - - ">="
50
95
  - !ruby/object:Gem::Version
51
- version: 1.9.0
96
+ version: "0"
52
97
  version:
53
98
  required_rubygems_version: !ruby/object:Gem::Requirement
54
99
  requirements:
@@ -58,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
103
  version:
59
104
  requirements: []
60
105
 
61
- rubyforge_project: bloomfilter
106
+ rubyforge_project:
62
107
  rubygems_version: 1.2.0
63
108
  signing_key:
64
109
  specification_version: 2
data/ext/extconf.rb DELETED
@@ -1,4 +0,0 @@
1
- require 'mkmf'
2
- $CFLAGS += " -Wall"
3
- $LDFLAGS += " -lfl"
4
- create_makefile "teeth/tokenize_apache_logs", "./"