clogger 0.0.1 → 0.0.2

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.
data/GNUmakefile CHANGED
@@ -32,6 +32,45 @@ test: test-ext test-pure
32
32
  Manifest.txt:
33
33
  git ls-files > $@+
34
34
  cmp $@+ $@ || mv $@+ $@
35
- $(RM) -f $@+
35
+ $(RM) $@+
36
36
 
37
- .PHONY: test doc Manifest.txt
37
+ VERSION := $(shell git describe 2>/dev/null | sed 's/^v//')
38
+
39
+ ifneq ($(VERSION),)
40
+ v := /^v$(VERSION)$$/
41
+ vPREV := $(shell git tag -l 2>/dev/null | sed -n -e '$(v)!h' -e '$(v){x;p;q}')
42
+ release_notes := release_notes-$(VERSION).txt
43
+ release_changes := release_changes-$(VERSION).txt
44
+ $(release_changes): verify
45
+ git diff --stat $(vPREV) v$(VERSION) > $@+
46
+ echo >> $@+
47
+ git log $(vPREV) v$(VERSION) >> $@+
48
+ $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
49
+ $(release_notes): verify package
50
+ gem spec pkg/clogger-$(VERSION).gem description | sed -ne '/\w/p' > $@+
51
+ git cat-file tag v$(VERSION) | awk 'p>1{print $$0}/^$$/{++p}' >> $@+
52
+ $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
53
+ verify:
54
+ @test -n "$(VERSION)" || { echo >&2 VERSION= not defined; exit 1; }
55
+ git rev-parse --verify refs/tags/v$(VERSION)^{}
56
+ @test -n "$(VISUAL)" || { echo >&2 VISUAL= not defined; exit 1; }
57
+
58
+ package: verify
59
+ git diff-index --quiet HEAD^0
60
+ test `git rev-parse --verify HEAD^0` = \
61
+ `git rev-parse --verify refs/tags/v$(VERSION)^{}`
62
+ $(RM) -r pkg
63
+ unset CLOGGER_EXT; rake package VERSION=$(VERSION)
64
+ CLOGGER_EXT=1 rake package VERSION=$(VERSION)
65
+
66
+ # not using Hoe's release system since we release 2 gems but only one tgz
67
+ release: package Manifest.txt $(release_notes) $(release_changes)
68
+ rubyforge add_release -f -n $(release_notes) -c $(release_changes) \
69
+ clogger clogger $(VERSION) pkg/clogger-$(VERSION).gem
70
+ rubyforge add_file \
71
+ clogger clogger $(VERSION) pkg/clogger-$(VERSION).tgz
72
+ rubyforge add_release -f -n $(release_notes) -c $(release_changes) \
73
+ clogger clogger_ext $(VERSION) pkg/clogger_ext-$(VERSION).gem
74
+ endif
75
+
76
+ .PHONY: test doc Manifest.txt release
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ === 0.0.2 / 2009-08-29
2
+
3
+ * 2 bug fixes
4
+
5
+ * support "$request_uri" as a log variable
6
+ * Log bad/invalid app responses as 500 errors
7
+
1
8
  === 0.0.1 / 2009-08-28
2
9
 
3
10
  * 1 major enhancement
@@ -54,7 +54,8 @@ enum clogger_special {
54
54
  CL_SP_request_length,
55
55
  CL_SP_response_length,
56
56
  CL_SP_ip,
57
- CL_SP_pid
57
+ CL_SP_pid,
58
+ CL_SP_request_uri,
58
59
  };
59
60
 
60
61
  struct clogger {
@@ -92,6 +93,7 @@ static VALUE g_HTTP_X_FORWARDED_FOR;
92
93
  static VALUE g_REMOTE_ADDR;
93
94
  static VALUE g_REQUEST_METHOD;
94
95
  static VALUE g_PATH_INFO;
96
+ static VALUE g_REQUEST_URI;
95
97
  static VALUE g_QUERY_STRING;
96
98
  static VALUE g_HTTP_VERSION;
97
99
  static VALUE g_rack_errors;
@@ -102,6 +104,7 @@ static VALUE g_empty;
102
104
  static VALUE g_space;
103
105
  static VALUE g_question_mark;
104
106
  static VALUE g_rack_request_cookie_hash;
107
+ static VALUE g_bad_app_response;
105
108
 
106
109
  #define LOG_BUF_INIT_SIZE 128
107
110
 
@@ -410,30 +413,44 @@ static void append_time_fmt(struct clogger *c, const VALUE *op)
410
413
  append_tv(c, op, &now);
411
414
  }
412
415
 
416
+ static void append_request_uri(struct clogger *c)
417
+ {
418
+ VALUE tmp;
419
+
420
+ tmp = rb_hash_aref(c->env, g_REQUEST_URI);
421
+ if (NIL_P(tmp)) {
422
+ tmp = rb_hash_aref(c->env, g_PATH_INFO);
423
+ if (!NIL_P(tmp))
424
+ rb_str_buf_append(c->log_buf, byte_xs(tmp));
425
+ tmp = rb_hash_aref(c->env, g_QUERY_STRING);
426
+ if (!NIL_P(tmp) && RSTRING_LEN(tmp) != 0) {
427
+ rb_str_buf_append(c->log_buf, g_question_mark);
428
+ rb_str_buf_append(c->log_buf, byte_xs(tmp));
429
+ }
430
+ } else {
431
+ rb_str_buf_append(c->log_buf, byte_xs(tmp));
432
+ }
433
+ }
434
+
413
435
  static void append_request(struct clogger *c)
414
436
  {
415
437
  VALUE tmp;
416
- VALUE env = c->env;
417
438
 
418
439
  /* REQUEST_METHOD doesn't need escaping, Rack::Lint governs it */
419
- tmp = rb_hash_aref(env, g_REQUEST_METHOD);
420
- rb_str_buf_append(c->log_buf, NIL_P(tmp) ? g_empty : tmp);
440
+ tmp = rb_hash_aref(c->env, g_REQUEST_METHOD);
441
+ if (!NIL_P(tmp))
442
+ rb_str_buf_append(c->log_buf, tmp);
443
+
421
444
  rb_str_buf_append(c->log_buf, g_space);
422
445
 
423
- /* broken clients can send " and other questionable URIs */
424
- tmp = rb_hash_aref(env, g_PATH_INFO);
425
- rb_str_buf_append(c->log_buf, NIL_P(tmp) ? g_empty : byte_xs(tmp));
446
+ append_request_uri(c);
426
447
 
427
- tmp = rb_hash_aref(env, g_QUERY_STRING);
428
- if (RSTRING_LEN(tmp) != 0) {
429
- rb_str_buf_append(c->log_buf, g_question_mark);
430
- rb_str_buf_append(c->log_buf, byte_xs(tmp));
431
- }
432
448
  rb_str_buf_append(c->log_buf, g_space);
433
449
 
434
450
  /* HTTP_VERSION can be injected by malicious clients */
435
- tmp = rb_hash_aref(env, g_HTTP_VERSION);
436
- rb_str_buf_append(c->log_buf, NIL_P(tmp) ? g_empty : byte_xs(tmp));
451
+ tmp = rb_hash_aref(c->env, g_HTTP_VERSION);
452
+ if (!NIL_P(tmp))
453
+ rb_str_buf_append(c->log_buf, byte_xs(tmp));
437
454
  }
438
455
 
439
456
  static void append_request_length(struct clogger *c)
@@ -538,6 +555,9 @@ static void special_var(struct clogger *c, enum clogger_special var)
538
555
  break;
539
556
  case CL_SP_pid:
540
557
  append_pid(c);
558
+ break;
559
+ case CL_SP_request_uri:
560
+ append_request_uri(c);
541
561
  }
542
562
  }
543
563
 
@@ -703,10 +723,21 @@ static VALUE clogger_fileno(VALUE self)
703
723
 
704
724
  static void ccall(struct clogger *c, VALUE env)
705
725
  {
726
+ VALUE rv;
727
+
706
728
  gettimeofday(&c->tv_start, NULL);
707
729
  c->env = env;
708
730
  c->cookies = Qfalse;
709
- c->response = rb_funcall(c->app, call_id, 1, env);
731
+ rv = rb_funcall(c->app, call_id, 1, env);
732
+ if (TYPE(rv) == T_ARRAY && RARRAY_LEN(rv) == 3) {
733
+ c->response = rv;
734
+ } else {
735
+ c->response = g_bad_app_response;
736
+ cwrite(c);
737
+ rb_raise(rb_eTypeError,
738
+ "app response not a 3 element Array: %s",
739
+ RSTRING_PTR(rb_inspect(rv)));
740
+ }
710
741
  }
711
742
 
712
743
  /*
@@ -763,6 +794,16 @@ static VALUE clogger_init_copy(VALUE clone, VALUE orig)
763
794
 
764
795
  #define CONST_GLOBAL_STR(val) CONST_GLOBAL_STR2(val, #val)
765
796
 
797
+ static void init_bad_response(void)
798
+ {
799
+ g_bad_app_response = rb_ary_new();
800
+ rb_ary_store(g_bad_app_response, 0, INT2NUM(500));
801
+ rb_ary_store(g_bad_app_response, 1, rb_obj_freeze(rb_hash_new()));
802
+ rb_ary_store(g_bad_app_response, 2, rb_obj_freeze(rb_ary_new()));
803
+ rb_obj_freeze(g_bad_app_response);
804
+ rb_global_variable(&g_bad_app_response);
805
+ }
806
+
766
807
  void Init_clogger_ext(void)
767
808
  {
768
809
  ltlt_id = rb_intern("<<");
@@ -788,6 +829,7 @@ void Init_clogger_ext(void)
788
829
  CONST_GLOBAL_STR(REQUEST_METHOD);
789
830
  CONST_GLOBAL_STR(PATH_INFO);
790
831
  CONST_GLOBAL_STR(QUERY_STRING);
832
+ CONST_GLOBAL_STR(REQUEST_URI);
791
833
  CONST_GLOBAL_STR(HTTP_VERSION);
792
834
  CONST_GLOBAL_STR2(rack_errors, "rack.errors");
793
835
  CONST_GLOBAL_STR2(rack_input, "rack.input");
@@ -797,4 +839,5 @@ void Init_clogger_ext(void)
797
839
  CONST_GLOBAL_STR2(space, " ");
798
840
  CONST_GLOBAL_STR2(question_mark, "?");
799
841
  CONST_GLOBAL_STR2(rack_request_cookie_hash, "rack.request.cookie_hash");
842
+ init_bad_response();
800
843
  }
data/lib/clogger.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: binary -*-
2
2
  class Clogger
3
- VERSION = '0.0.1'
3
+ VERSION = '0.0.2'
4
4
 
5
5
  OP_LITERAL = 0
6
6
  OP_REQUEST = 1
@@ -29,6 +29,7 @@ class Clogger
29
29
  :response_length => 4, # like body_bytes_sent, except "-" instead of "0"
30
30
  :ip => 5, # HTTP_X_FORWARDED_FOR || REMOTE_ADDR || -
31
31
  :pid => 6, # getpid()
32
+ :request_uri => 7
32
33
  }
33
34
 
34
35
  private
data/lib/clogger/pure.rb CHANGED
@@ -16,7 +16,12 @@ class Clogger
16
16
 
17
17
  def call(env)
18
18
  @start = Time.now
19
- status, headers, body = @app.call(env)
19
+ resp = @app.call(env)
20
+ unless resp.instance_of?(Array) && resp.size == 3
21
+ log(env, 500, {})
22
+ raise TypeError, "app response not a 3 element Array: #{resp.inspect}"
23
+ end
24
+ status, headers, body = resp
20
25
  if wrap_body?
21
26
  @reentrant = env['rack.multithread']
22
27
  @env, @status, @headers, @body = env, status, headers, body
@@ -63,6 +68,13 @@ private
63
68
 
64
69
  SPECIAL_RMAP = SPECIAL_VARS.inject([]) { |ary, (k,v)| ary[v] = k; ary }
65
70
 
71
+ def request_uri(env)
72
+ ru = env['REQUEST_URI'] and return byte_xs(ru)
73
+ qs = env['QUERY_STRING']
74
+ qs.empty? or qs = "?#{byte_xs(qs)}"
75
+ "#{byte_xs(env['PATH_INFO'])}#{qs}"
76
+ end
77
+
66
78
  def special_var(special_nr, env, status, headers)
67
79
  case SPECIAL_RMAP[special_nr]
68
80
  when :body_bytes_sent
@@ -74,8 +86,10 @@ private
74
86
  qs = env['QUERY_STRING']
75
87
  qs.empty? or qs = "?#{byte_xs(qs)}"
76
88
  "#{env['REQUEST_METHOD']} " \
77
- "#{byte_xs(env['PATH_INFO'])}#{qs} " \
89
+ "#{request_uri(env)} " \
78
90
  "#{byte_xs(env['HTTP_VERSION'])}"
91
+ when :request_uri
92
+ request_uri(env)
79
93
  when :request_length
80
94
  env['rack.input'].size.to_s
81
95
  when :response_length
data/test/test_clogger.rb CHANGED
@@ -333,6 +333,22 @@ class TestClogger < Test::Unit::TestCase
333
333
  assert_equal expect, str.string
334
334
  end
335
335
 
336
+ def test_request_uri_fallback
337
+ str = StringIO.new
338
+ app = lambda { |env| [ 200, {}, [] ] }
339
+ cl = Clogger.new(app, :logger => str, :format => '$request_uri')
340
+ status, headers, body = cl.call(@req)
341
+ assert_equal "/hello?goodbye=true\n", str.string
342
+ end
343
+
344
+ def test_request_uri_set
345
+ str = StringIO.new
346
+ app = lambda { |env| [ 200, {}, [] ] }
347
+ cl = Clogger.new(app, :logger => str, :format => '$request_uri')
348
+ status, headers, body = cl.call(@req.merge("REQUEST_URI" => '/zzz'))
349
+ assert_equal "/zzz\n", str.string
350
+ end
351
+
336
352
  def test_cookies
337
353
  str = StringIO.new
338
354
  app = lambda { |env|
@@ -346,4 +362,15 @@ class TestClogger < Test::Unit::TestCase
346
362
  status, headers, body = cl.call(req)
347
363
  assert_equal "bar h&m\n", str.string
348
364
  end
365
+
366
+ def test_bogus_app_response
367
+ str = StringIO.new
368
+ app = lambda { |env| 302 }
369
+ cl = Clogger.new(app, :logger => str)
370
+ assert_raise(TypeError) { cl.call(@req) }
371
+ str = str.string
372
+ e = Regexp.quote " \"GET /hello?goodbye=true HTTP/1.0\" 500 -"
373
+ assert_match %r{#{e}$}m, str
374
+ end
375
+
349
376
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clogger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Wong
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-28 00:00:00 -07:00
12
+ date: 2009-08-29 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency