danielsdeleo-teeth 0.0.2 → 0.1.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.
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", "./"