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,158 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = ./
7
+ topdir = /opt/local/lib/ruby/1.8/i686-darwin8.11.1
8
+ hdrdir = $(topdir)
9
+ VPATH = $(srcdir):$(topdir):$(hdrdir)
10
+ exec_prefix = $(prefix)
11
+ prefix = $(DESTDIR)/opt/local
12
+ sharedstatedir = $(prefix)/com
13
+ mandir = $(DESTDIR)/opt/local/share/man
14
+ psdir = $(docdir)
15
+ oldincludedir = $(DESTDIR)/usr/include
16
+ localedir = $(datarootdir)/locale
17
+ bindir = $(exec_prefix)/bin
18
+ libexecdir = $(exec_prefix)/libexec
19
+ sitedir = $(libdir)/ruby/site_ruby
20
+ htmldir = $(docdir)
21
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
22
+ includedir = $(prefix)/include
23
+ infodir = $(datarootdir)/info
24
+ vendorlibdir = $(vendordir)/$(ruby_version)
25
+ sysconfdir = $(prefix)/etc
26
+ libdir = $(exec_prefix)/lib
27
+ sbindir = $(exec_prefix)/sbin
28
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
29
+ docdir = $(datarootdir)/doc/$(PACKAGE)
30
+ dvidir = $(docdir)
31
+ vendordir = $(DESTDIR)/opt/local/lib/ruby/vendor_ruby
32
+ datarootdir = $(prefix)/share
33
+ pdfdir = $(docdir)
34
+ archdir = $(rubylibdir)/$(arch)
35
+ sitearchdir = $(sitelibdir)/$(sitearch)
36
+ datadir = $(datarootdir)
37
+ localstatedir = $(prefix)/var
38
+ sitelibdir = $(sitedir)/$(ruby_version)
39
+
40
+ CC = /usr/bin/gcc-4.0
41
+ LIBRUBY = $(LIBRUBY_SO)
42
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
43
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
44
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
45
+
46
+ RUBY_EXTCONF_H =
47
+ CFLAGS = -fno-common -O2 -fno-common -pipe -fno-common $(cflags) -Wall
48
+ INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
49
+ DEFS =
50
+ CPPFLAGS = -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags)
51
+ CXXFLAGS = $(CFLAGS)
52
+ ldflags = -L. -L/opt/local/lib
53
+ dldflags =
54
+ archflag =
55
+ DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
56
+ LDSHARED = cc -dynamic -bundle -undefined suppress -flat_namespace
57
+ AR = ar
58
+ EXEEXT =
59
+
60
+ RUBY_INSTALL_NAME = ruby
61
+ RUBY_SO_NAME = ruby
62
+ arch = i686-darwin8.11.1
63
+ sitearch = i686-darwin8.11.1
64
+ vendorarch = i686-darwin8.11.1
65
+ ruby_version = 1.8
66
+ ruby = /opt/local/bin/ruby
67
+ RUBY = $(ruby)
68
+ RM = rm -f
69
+ MAKEDIRS = mkdir -p
70
+ INSTALL = /usr/bin/install
71
+ INSTALL_PROG = $(INSTALL) -m 0755
72
+ INSTALL_DATA = $(INSTALL) -m 644
73
+ COPY = cp
74
+
75
+ #### End of system configuration section. ####
76
+
77
+ preload =
78
+
79
+ libpath = . $(libdir)
80
+ LIBPATH = -L. -L$(libdir)
81
+ DEFFILE =
82
+
83
+ CLEANFILES = mkmf.log
84
+ DISTCLEANFILES =
85
+
86
+ extout =
87
+ extout_prefix =
88
+ target_prefix = /teeth
89
+ LOCAL_LIBS =
90
+ LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl -lobjc
91
+ SRCS = scan_rails_logs.yy.c
92
+ OBJS = scan_rails_logs.yy.o
93
+ TARGET = scan_rails_logs
94
+ DLLIB = $(TARGET).bundle
95
+ EXTSTATIC =
96
+ STATIC_LIB =
97
+
98
+ BINDIR = $(bindir)
99
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
100
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
101
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
102
+
103
+ TARGET_SO = $(DLLIB)
104
+ CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
105
+ CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
106
+
107
+ all: $(DLLIB)
108
+ static: $(STATIC_LIB)
109
+
110
+ clean:
111
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
112
+
113
+ distclean: clean
114
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
115
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
116
+
117
+ realclean: distclean
118
+ install: install-so install-rb
119
+
120
+ install-so: $(RUBYARCHDIR)
121
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
122
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
123
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
124
+ install-rb: pre-install-rb install-rb-default
125
+ install-rb-default: pre-install-rb-default
126
+ pre-install-rb: Makefile
127
+ pre-install-rb-default: Makefile
128
+ $(RUBYARCHDIR):
129
+ $(MAKEDIRS) $@
130
+
131
+ site-install: site-install-so site-install-rb
132
+ site-install-so: install-so
133
+ site-install-rb: install-rb
134
+
135
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
136
+
137
+ .cc.o:
138
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
139
+
140
+ .cxx.o:
141
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
142
+
143
+ .cpp.o:
144
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
145
+
146
+ .C.o:
147
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
148
+
149
+ .c.o:
150
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
151
+
152
+ $(DLLIB): $(OBJS)
153
+ @-$(RM) $@
154
+ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
155
+
156
+
157
+
158
+ $(OBJS): ruby.h defines.h
@@ -0,0 +1,3 @@
1
+ require "mkmf"
2
+ $CFLAGS += " -Wall"
3
+ create_makefile "teeth/scan_rails_logs", "./"
@@ -0,0 +1,376 @@
1
+ %option prefix="rails_logs_yy"
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 t_scan_rails_logs(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 scan_rails_logs(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
+
41
+ WS [[:space:]]
42
+
43
+ NON_WS ([a-z]|[0-9]|[:punct:])
44
+
45
+ IP4_OCT [0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]
46
+
47
+ HOST [a-z0-9][a-z0-9\-]*\.[a-z0-9][a-z0-9\-]*.[a-z0-9][a-z0-9\-\.]*[a-z]+(\:[0-9]+)?
48
+
49
+ WDAY mon|tue|wed|thu|fri|sat|sun
50
+
51
+ MON jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec
52
+
53
+ MONTH_NUM 0[1-9]|1[0-2]
54
+
55
+ MDAY 3[0-1]|[1-2][0-9]|0[1-9]
56
+
57
+ HOUR 2[0-3]|[0-1][0-9]
58
+
59
+ MINSEC [0-5][0-9]|60
60
+
61
+ YEAR [0-9][0-9][0-9][0-9]
62
+
63
+ PLUSMINUS (\+|\-)
64
+
65
+ REL_URL (\/|\\|\.)[a-z0-9\._\~\-\/\?&;#=\%\:\+\[\]\\]*
66
+
67
+ PROTO (http:|https:)
68
+
69
+ ERR_LVL (emerg|alert|crit|err|error|warn|warning|notice|info|debug)
70
+
71
+ HTTP_VERS HTTP\/(1.0|1.1)
72
+
73
+ HTTP_VERB (get|head|put|post|delete|trace|connect)
74
+
75
+ HTTPCODE (100|101|20[0-6]|30[0-5]|307|40[0-9]|41[0-7]|50[0-5])
76
+
77
+ BROWSER_STR \"(moz|msie|lynx).+\"
78
+
79
+ RAILS_TEASER (processing|filter\ chain\ halted|rendered)
80
+
81
+ CONTROLLER_ACTION [a-z0-9]+#[a-z0-9]+
82
+
83
+ RAILS_SKIP_LINES (session\ id)
84
+
85
+ CACHE_HIT actioncontroller"::"caching"::"actions"::"actioncachefilter":"0x[0-9a-f]+
86
+
87
+ PARTIAL_SESSION_ID ^([a-z0-9]+"="*"-"+[a-z0-9]+)
88
+
89
+ RAILS_ERROR_CLASS ([a-z]+\:\:)*[a-z]+error
90
+
91
+ %x REQUEST_COMPLETED
92
+
93
+ %x COMPLETED_REQ_VIEW_STATS
94
+
95
+ %x COMPLETED_REQ_DB_STATS
96
+
97
+
98
+ %%
99
+ /*
100
+ Actions
101
+ */
102
+
103
+
104
+ {RAILS_TEASER} {
105
+ KVPAIR teaser = {"teaser", yytext};
106
+ return teaser;
107
+ }
108
+
109
+ {CONTROLLER_ACTION} {
110
+ KVPAIR controller_action = {"controller_action", yytext};
111
+ return controller_action;
112
+ }
113
+
114
+ {IP4_OCT}"."{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT} {
115
+ KVPAIR ipv4_addr = {"ipv4_addr", yytext};
116
+ return ipv4_addr;
117
+ }
118
+
119
+ {YEAR}"-"{MONTH_NUM}"-"{MDAY}{WS}{HOUR}":"{MINSEC}":"{MINSEC} {
120
+ KVPAIR datetime = {"datetime", yytext};
121
+ return datetime;
122
+ }
123
+
124
+ {HTTP_VERB} {
125
+ KVPAIR http_method = {"http_method", yytext};
126
+ return http_method;
127
+ }
128
+
129
+ {RAILS_SKIP_LINES} {
130
+ return EOF_KVPAIR;
131
+ }
132
+
133
+ {PARTIAL_SESSION_ID} {
134
+ KVPAIR end_session_id = {"end_session_id", yytext};
135
+ return end_session_id;
136
+ }
137
+
138
+ {RAILS_ERROR_CLASS} {
139
+ KVPAIR error = {"error", yytext};
140
+ return error;
141
+ }
142
+
143
+ \(({WS}|{NON_WS})+\) {
144
+ KVPAIR error_message = {"error_message", strip_ends(yytext)};
145
+ return error_message;
146
+ }
147
+
148
+ "#"[0-9]+{WS} {
149
+ KVPAIR line_number = {"line_number", strip_ends(yytext)};
150
+ return line_number;
151
+ }
152
+
153
+ {WS}{REL_URL}":" {
154
+ KVPAIR file_and_line = {"file_and_line", strip_ends(yytext)};
155
+ return file_and_line;
156
+ }
157
+
158
+ {CACHE_HIT} {
159
+ KVPAIR cache_hit = {"cache_hit", yytext};
160
+ return cache_hit;
161
+ }
162
+
163
+ [a-z0-9]+{REL_URL}/\ \( {
164
+ KVPAIR partial = {"partial", yytext};
165
+ return partial;
166
+ }
167
+
168
+ [0-9\.]+/ms\) {
169
+ KVPAIR render_duration_ms = {"render_duration_ms", yytext};
170
+ return render_duration_ms;
171
+ }
172
+
173
+ \([0-9\.]+\) {
174
+ KVPAIR render_duration_s = {"render_duration_s", strip_ends(yytext)};
175
+ return render_duration_s;
176
+ }
177
+
178
+ completed\ in {
179
+ BEGIN(REQUEST_COMPLETED);
180
+ KVPAIR teaser = {"teaser", yytext};
181
+ return teaser;
182
+ }
183
+
184
+ <REQUEST_COMPLETED>[0-9]+\.[0-9]+ {
185
+ KVPAIR duration_s = {"duration_s", yytext};
186
+ return duration_s;
187
+ }
188
+
189
+ <REQUEST_COMPLETED>[0-9]+/ms {
190
+ KVPAIR duration_ms = {"duration_ms", yytext};
191
+ return duration_ms;
192
+ }
193
+
194
+ <REQUEST_COMPLETED>(View":"|Rendering":") {
195
+ BEGIN(COMPLETED_REQ_VIEW_STATS);
196
+ KVPAIR start_view_stats = {"start_view_stats", yytext};
197
+ return start_view_stats;
198
+ }
199
+
200
+ <COMPLETED_REQ_VIEW_STATS>([0-9]+\.[0-9]+) {
201
+ BEGIN(REQUEST_COMPLETED);
202
+ KVPAIR view_s = {"view_s", yytext};
203
+ return view_s;
204
+ }
205
+
206
+ <COMPLETED_REQ_VIEW_STATS>[0-9]+ {
207
+ BEGIN(REQUEST_COMPLETED);
208
+ KVPAIR view_ms = {"view_ms", yytext};
209
+ return view_ms;
210
+ }
211
+
212
+ <COMPLETED_REQ_VIEW_STATS>{CATCHALL}
213
+
214
+ <REQUEST_COMPLETED>DB":" {
215
+ BEGIN(COMPLETED_REQ_DB_STATS);
216
+ KVPAIR start_db_stats = {"start_db_stats", yytext};
217
+ return start_db_stats;
218
+ }
219
+
220
+ <COMPLETED_REQ_DB_STATS>[0-9]+\.[0-9]+ {
221
+ BEGIN(REQUEST_COMPLETED);
222
+ KVPAIR db_s = {"db_s", yytext};
223
+ return db_s;
224
+ }
225
+
226
+ <COMPLETED_REQ_DB_STATS>[0-9]+ {
227
+ BEGIN(REQUEST_COMPLETED);
228
+ KVPAIR db_ms = {"db_ms", yytext};
229
+ return db_ms;
230
+ }
231
+
232
+ <COMPLETED_REQ_DB_STATS>{CATCHALL}
233
+
234
+ <REQUEST_COMPLETED>\[{PROTO}"\/\/"({HOST}|{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT}"."{IP4_OCT})({REL_URL}|"\/")?\] {
235
+ KVPAIR url = {"url", strip_ends(yytext)};
236
+ return url;
237
+ }
238
+
239
+ <REQUEST_COMPLETED>{HTTPCODE} {
240
+ KVPAIR http_response = {"http_response", yytext};
241
+ return http_response;
242
+ }
243
+
244
+ <REQUEST_COMPLETED>{NON_WS}{NON_WS}* {
245
+ KVPAIR strings = {"strings", yytext};
246
+ return strings;
247
+ }
248
+
249
+ <REQUEST_COMPLETED>{CATCHALL}
250
+
251
+ {NON_WS}{NON_WS}* {
252
+ KVPAIR strings = {"strings", yytext};
253
+ return strings;
254
+ }
255
+
256
+ {CATCHALL} /* ignore */
257
+ %%
258
+
259
+ char *strip_ends(char *string) {
260
+ string[yyleng-1] = '\0';
261
+ ++string;
262
+ return string;
263
+ }
264
+
265
+ void uuid_unparse_upper_sans_dash(const uuid_t uu, char *out)
266
+ {
267
+ sprintf(out,
268
+ "%02X%02X%02X%02X"
269
+ "%02X%02X"
270
+ "%02X%02X"
271
+ "%02X%02X"
272
+ "%02X%02X%02X%02X%02X%02X",
273
+ uu[0], uu[1], uu[2], uu[3],
274
+ uu[4], uu[5],
275
+ uu[6], uu[7],
276
+ uu[8], uu[9],
277
+ uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
278
+ }
279
+
280
+ void new_uuid(char *str_ptr){
281
+ uuid_t new_uuid;
282
+ uuid_generate_time(new_uuid);
283
+ uuid_unparse_upper_sans_dash(new_uuid, str_ptr);
284
+ }
285
+
286
+ void raise_error_for_string_too_long(VALUE string){
287
+ if( RSTRING_LEN(string) > 1000000){
288
+ rb_raise(rb_eArgError, "string too long for scan_rails_logs! max length is 1,000,000 chars");
289
+ }
290
+ }
291
+
292
+ /* Scans self, which is expected to be a line from a Rails production or dev log,
293
+ * and returns a Hash of the significant features in the log message, including
294
+ * the IP address of the client, the Controller and Action, any partials rendered,
295
+ * and the time spent rendering them, the duration of the DB request(s), the HTTP
296
+ * verb, etc. */
297
+ VALUE t_scan_rails_logs(VALUE self) {
298
+ KVPAIR kv_result;
299
+ int scan_complete = 0;
300
+ int building_words_to_string = 0;
301
+ VALUE token_hash = rb_hash_new();
302
+
303
+ BEGIN(INITIAL);
304
+
305
+ /* error out on absurdly large strings */
306
+ raise_error_for_string_too_long(self);
307
+ /* {:message => self()} */
308
+ include_message_in_token_hash(self, token_hash);
309
+ /* {:id => UUID} */
310
+ add_uuid_to_token_hash(token_hash);
311
+ yy_scan_string(RSTRING_PTR(self));
312
+ while (scan_complete == 0) {
313
+ kv_result = scan_rails_logs();
314
+ if (kv_result.key == "EOF"){
315
+ scan_complete = 1;
316
+ }
317
+ else if (kv_result.key == "strings"){
318
+ /* build a string until we get a non-word */
319
+ if (building_words_to_string == 0){
320
+ building_words_to_string = 1;
321
+ push_kv_pair_to_hash(kv_result, token_hash);
322
+ }
323
+ else{
324
+ concat_word_to_string(kv_result, token_hash);
325
+ }
326
+ }
327
+ else {
328
+ building_words_to_string = 0;
329
+ push_kv_pair_to_hash(kv_result, token_hash);
330
+ }
331
+ }
332
+ yy_delete_buffer(YY_CURRENT_BUFFER);
333
+ return rb_obj_dup(token_hash);
334
+ }
335
+
336
+ void add_uuid_to_token_hash(VALUE token_hash) {
337
+ char new_uuid_str[33];
338
+ new_uuid(new_uuid_str);
339
+ VALUE hsh_key_id = ID2SYM(rb_intern("id"));
340
+ VALUE hsh_val_id = rb_tainted_str_new2(new_uuid_str);
341
+ rb_hash_aset(token_hash, hsh_key_id, hsh_val_id);
342
+ }
343
+
344
+ void include_message_in_token_hash(VALUE message, VALUE token_hash) {
345
+ /* {:message => self()} */
346
+ VALUE hsh_key_msg = ID2SYM(rb_intern("message"));
347
+ rb_hash_aset(token_hash, hsh_key_msg, message);
348
+ }
349
+
350
+ void concat_word_to_string(KVPAIR key_value, VALUE token_hash) {
351
+ char * space = " ";
352
+ VALUE hsh_key = ID2SYM(rb_intern(key_value.key));
353
+ VALUE hsh_value = rb_hash_aref(token_hash, hsh_key);
354
+ VALUE string = rb_ary_entry(hsh_value, -1);
355
+ rb_str_cat(string, space, 1);
356
+ rb_str_cat(string, key_value.value, yyleng);
357
+ }
358
+
359
+ void push_kv_pair_to_hash(KVPAIR key_value, VALUE token_hash) {
360
+ VALUE hsh_key = ID2SYM(rb_intern(key_value.key));
361
+ VALUE hsh_value = rb_hash_aref(token_hash, hsh_key);
362
+ VALUE ary_for_token_type = rb_ary_new();
363
+ switch (TYPE(hsh_value)) {
364
+ case T_NIL:
365
+ rb_ary_push(ary_for_token_type, rb_tainted_str_new2(key_value.value));
366
+ rb_hash_aset(token_hash, hsh_key, ary_for_token_type);
367
+ break;
368
+ case T_ARRAY:
369
+ rb_ary_push(hsh_value, rb_tainted_str_new2(key_value.value));
370
+ break;
371
+ }
372
+ }
373
+
374
+ void Init_scan_rails_logs() {
375
+ rb_define_method(rb_cString, "scan_rails_logs", t_scan_rails_logs, 0);
376
+ }