candies 0.0.2 → 0.0.3

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/README.md CHANGED
@@ -1,36 +1,6 @@
1
- # Candies[![travis-ci](https://secure.travis-ci.org/martinciu/candies.png?branch=master)](http://travis-ci.org/martinciu/candies)
2
- Invisible image based tracing service with Redis backend
3
-
4
- ## Requirements
5
-
6
- Candies uses redis as a datastore.
7
-
8
- Candies only supports redis 2.0 or greater.
9
-
10
- If you're on OS X, Homebrew is the simplest way to install Redis:
11
-
12
- $ brew install redis
13
- $ redis-server /usr/local/etc/redis.conf
14
-
15
- You now have a Redis daemon running on 6379.
16
-
17
- ## Setup
18
-
19
- If you are using bundler add candies to your Gemfile:
20
-
21
- gem 'candies'
22
-
23
- Then run:
24
-
25
- bundle install
26
-
27
- Otherwise install the gem:
28
-
29
- gem install candies
30
-
31
- and require it in your project:
32
-
33
- require 'candies'
1
+ # Candies
2
+ [![travis-ci](https://secure.travis-ci.org/martinciu/candies.png?branch=master)](http://travis-ci.org/martinciu/candies)
3
+ ####Invisible image based tracing service with Redis backend
34
4
 
35
5
  ## Usage
36
6
 
@@ -59,11 +29,11 @@ It will be available under `http://yourapproot.tld/candies` url
59
29
 
60
30
  When you have Candies server deployed you can add tracking payload by including `img` tag in your HTML code:
61
31
 
62
- <a href="http://candies.tld/anyfile.gif?id=tracing-id&foo=bar&baz=foo" />
32
+ <a href="http://candies.tld/trackername.gif?id=tracing-id&foo=bar&baz=foo" />
63
33
 
64
34
  or if you mounted candies in your rails app as `candies` then it will be:
65
35
 
66
- <a href="http://yourapproot.tld/candies/anyfile.gif?id=tracing-id&foo=bar&baz=foo" />
36
+ <a href="http://yourapproot.tld/candies/trackername.gif?id=tracing-id&foo=bar&baz=foo" />
67
37
 
68
38
  Also in rails app you can use `candies_image_tag` helper. To do so you have to set `Candies.url` to point to the candies service url. The best way is to put in `config/initializers/candies.rb` file:
69
39
 
@@ -71,9 +41,70 @@ Also in rails app you can use `candies_image_tag` helper. To do so you have to s
71
41
 
72
42
  Now you can use `candies_image_tag` helper in controller views and in mailer views. Example:
73
43
 
74
- <%= candies_image_tag(:id => "anyone@example.com", :email_type => "hello") %>
44
+ <%= candies_image_tag(:id => "anyone@example.com", :tracker => "t", :email_type => "hello") %>
45
+
46
+ Note that `id` parameter is required. If `tracker` parameter is ommited it will be set "t" as default. Rest of parameters is a tracking payload. In this case redis key will be: `candies:tracker:anyone@example.com:2011-11-10T13:13:09+01:00` and value: `"{\"email_type\":\"hello\"}"`. If you don't specify `id` parameter not value will be stored. Invisible image will by served anyway.
47
+
48
+ ## Results
49
+
50
+ There isn't any dashboard for displaying values. You can review gathered metrics in three ways:
51
+
52
+ ### JSON
53
+
54
+ You can get all data from candies server if you request it using JSON.
55
+
56
+ curl http://localhost:9393/tracker.json?id=10 |jsonpretty
57
+ {
58
+ "tracker:10:2011-11-19T22:39:34+01:00": "{\"foo\":\"99\"}",
59
+ "tracker:10:2011-11-19T22:23:09+01:00": "{\"foo\":\"39\"}",
60
+ "tracker:10:2011-11-19T22:24:26+01:00": "{\"foo\":\"94\"}"
61
+ }
62
+
63
+ Note: `id` parameter is optional.
75
64
 
76
- Note that `id` parameter is required. It will be used to create a redis key under which paload will be stored. In this case redis key will be: `candies:anyone@example.com:2011-11-10T13:13:09+01:00` and value: `"{\"email_type\":\"hello\"}"`. If you don't specify `id` parameter not value will be stored. Invisible image will by served anyway.
65
+ ### redis-cli
66
+
67
+ Just log to your Redis using redis command line interface. Keys started with `candies` so to display all keys from candies type
68
+
69
+ redis 127.0.0.1:6379> keys candies*
70
+ 1) "candies:tracker:10:2011-11-19T22:39:34+01:00"
71
+ 2) "candies:tracker:10:2011-11-19T22:23:09+01:00"
72
+ 3) "candies:tracker:10:2011-11-19T22:24:26+01:00"
73
+
74
+ ### redisplay
75
+
76
+ Use [redisplay](https://github.com/martinciu/redisplay) Simple Rack app for browsing Redis
77
+
78
+ ## Requirements
79
+
80
+ Candies uses redis as a datastore.
81
+
82
+ Candies only supports redis 2.0 or greater.
83
+
84
+ If you're on OS X, Homebrew is the simplest way to install Redis:
85
+
86
+ $ brew install redis
87
+ $ redis-server /usr/local/etc/redis.conf
88
+
89
+ You now have a Redis daemon running on 6379.
90
+
91
+ ## Setup
92
+
93
+ If you are using bundler add candies to your Gemfile:
94
+
95
+ gem 'candies'
96
+
97
+ Then run:
98
+
99
+ bundle install
100
+
101
+ Otherwise install the gem:
102
+
103
+ gem install candies
104
+
105
+ and require it in your project:
106
+
107
+ require 'candies'
77
108
 
78
109
  ## Configuration
79
110
 
@@ -127,10 +158,6 @@ Simply use the `Candies.redis.namespace` accessor:
127
158
  We recommend sticking this in your initializer somewhere after Redis
128
159
  is configured.
129
160
 
130
- ## Results
131
-
132
- There isn't any dashboard for displaying values (yet). You cen review them by logging into `redis-cli`. Sorry.
133
-
134
161
  ## Development
135
162
 
136
163
  Source hosted at [GitHub](http://github.com/martinciu/candies).
@@ -1,7 +1,7 @@
1
1
  module Candies
2
2
  module Helper
3
3
  def candies_image_tag(args)
4
- image_tag("#{Candies.url}/t.gif?#{args.to_query}", :alt => "", :width => 1, :height => 1) if Candies.url
4
+ image_tag("#{Candies.url}/#{args.fetch(:tracker) {|t| "t"}}.gif?#{args.to_query}", :alt => "", :width => 1, :height => 1) if Candies.url
5
5
  end
6
6
  end
7
7
  end
@@ -1,26 +1,14 @@
1
- module Candies
2
- class Server
3
- def call(env)
4
- req = Rack::Request.new(env)
5
- id = req.params.delete("id")
6
- Candies.redis.set([id, Time.now.iso8601].join(":"), req.params.to_json) if !id.nil?
7
- [200, headers, [image]]
8
- end
9
-
10
- private
11
- def headers
12
- {
13
- "Content-Type" => "image/gif",
14
- "Content-Length" => "35",
15
- "Cache-Control" => "no-store, no-cache, must-revalidate, private",
16
- "Pragma" => "no-cache",
17
- "Expires" => "Sat, 25 Nov 2000 05:00:00 GMT"
18
- }
19
- end
1
+ require "candies/server/base"
2
+ require "candies/server/json"
3
+ require "candies/server/gif"
20
4
 
21
- def image
22
- "GIF89a\u0001\u0000\u0001\u0000\x80\xFF\u0000\xFF\xFF\xFF\u0000\u0000\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0002D\u0001\u0000;"
5
+ module Candies
6
+ module Server
7
+ def self.new
8
+ Rack::Builder.new do
9
+ use Rack::ContentLength
10
+ run Candies::Server::Base.new(:gif => Candies::Server::Gif.new, :json => Candies::Server::Json.new)
23
11
  end
24
-
12
+ end
25
13
  end
26
14
  end
@@ -0,0 +1,34 @@
1
+ module Candies
2
+ module Server
3
+ class Base
4
+ attr_accessor :request, :id, :responders
5
+
6
+ def initialize(responders = {})
7
+ @responders = responders
8
+ end
9
+
10
+ def call(env)
11
+ @request = Rack::Request.new(env)
12
+ @responders.fetch(format) {@responders[:json]}.call(env)
13
+ end
14
+
15
+ protected
16
+ def format
17
+ @request.path.split(".").last.to_sym
18
+ end
19
+
20
+ def tracker
21
+ @request.path.match(/^\/(\w+)\.?(\w+$)?/)[1]
22
+ end
23
+
24
+ def id
25
+ @id ||= @request.params.delete("id")
26
+ end
27
+
28
+ def status
29
+ 200
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,30 @@
1
+ module Candies
2
+ module Server
3
+ class Gif < Base
4
+
5
+ def call(env)
6
+ @request = Rack::Request.new(env)
7
+ Candies.redis.set(key, @request.params.to_json) if !id.nil?
8
+ [status, headers, body]
9
+ end
10
+
11
+ protected
12
+ def headers
13
+ {
14
+ "Content-Type" => "image/gif",
15
+ "Cache-Control" => "no-store, no-cache, must-revalidate, private",
16
+ "Pragma" => "no-cache",
17
+ "Expires" => "Sat, 25 Nov 2000 05:00:00 GMT"
18
+ }
19
+ end
20
+
21
+ def body
22
+ ["GIF89a\u0001\u0000\u0001\u0000\x80\xFF\u0000\xFF\xFF\xFF\u0000\u0000\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0002D\u0001\u0000;"]
23
+ end
24
+
25
+ def key
26
+ [tracker, id, Time.now.iso8601].join(":")
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ module Candies
2
+ module Server
3
+ class Json < Base
4
+
5
+ def call(env)
6
+ @request = Rack::Request.new(env)
7
+ [status, headers, body]
8
+ end
9
+
10
+ protected
11
+ def headers
12
+ {
13
+ "Content-Type" => "application/json"
14
+ }
15
+ end
16
+
17
+ def key
18
+ "#{[tracker, id].compact.join(":")}*"
19
+ end
20
+
21
+ def body
22
+ [Candies.redis.keys(key).inject({}) {|body, k| body[k] = Candies.redis.get(k);body }.to_json]
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module Candies
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Candies::Helper do
4
+
5
+ class View
6
+ include Candies::Helper
7
+ end
8
+
9
+ Candies.url = "http://example.com"
10
+
11
+ before do
12
+ @view = View.new
13
+ @args = mock()
14
+ @args.stubs(:to_query).returns("a=10&c=foo")
15
+ end
16
+
17
+ describe "#candies_image_tag" do
18
+ it "call image_tag with tracker param" do
19
+ @args.expects(:fetch).with(:tracker).returns("custom")
20
+ @view.expects(:image_tag).with("http://example.com/custom.gif?a=10&c=foo", :alt => "", :width => 1, :height => 1)
21
+ @view.candies_image_tag(@args)
22
+ end
23
+
24
+ end
25
+ end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Candies::Server do
3
+ describe Candies::Server::Gif do
4
4
  include Rack::Test::Methods
5
5
 
6
6
  before do
@@ -19,7 +19,7 @@ describe Candies::Server do
19
19
  it "get /t.gif?id=info@example.com&foo=bar adds record" do
20
20
  now = Time.now
21
21
  Timecop.freeze(now)
22
- @redis.expects(:set).with(["info@example.com", now.iso8601].join(":"), {:foo => "bar"}.to_json)
22
+ @redis.expects(:set).with(["t", "info@example.com", now.iso8601].join(":"), {:foo => "bar"}.to_json)
23
23
  get '/t.gif?id=info@example.com&foo=bar'
24
24
  last_response.status.must_equal 200
25
25
  last_response['Content-Type'].must_equal 'image/gif'
@@ -37,8 +37,8 @@ describe Candies::Server do
37
37
  it "get /t.gif?id=info@example.com adds record with empty payload" do
38
38
  now = Time.now
39
39
  Timecop.freeze(now)
40
- @redis.expects(:set).with(["info@example.com", now.iso8601].join(":"), {}.to_json)
41
- get '/t.gif?id=info@example.com'
40
+ @redis.expects(:set).with(["tracker", "info@example.com", now.iso8601].join(":"), {}.to_json)
41
+ get '/tracker.gif?id=info@example.com'
42
42
  last_response.status.must_equal 200
43
43
  last_response['Content-Type'].must_equal 'image/gif'
44
44
  end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Candies::Server do
4
+ include Rack::Test::Methods
5
+
6
+ before do
7
+ @redis = mock()
8
+ Candies.stubs(:redis).returns(@redis)
9
+ end
10
+
11
+ def app
12
+ @app ||= Candies::Server.new
13
+ end
14
+
15
+ it "get /t.json returns all records for t metric" do
16
+ values = [:foo, :bar]
17
+ @redis.expects(:get).with(:foo).returns("baz")
18
+ @redis.expects(:get).with(:bar).returns("foo")
19
+
20
+ @redis.expects(:keys).with("t*").returns(values)
21
+ get '/t.json'
22
+ last_response.status.must_equal 200
23
+ last_response['Content-Type'].must_equal 'application/json'
24
+ end
25
+
26
+ it "get /t.gif?&id=foo returns records for id=foo" do
27
+ values = [:foo, :bar]
28
+ @redis.expects(:get).with(:foo).returns("baz")
29
+ @redis.expects(:get).with(:bar).returns("foo")
30
+
31
+ @redis.expects(:keys).with("t:foo*").returns(values)
32
+ get '/t.json?&id=foo'
33
+ last_response.status.must_equal 200
34
+ last_response['Content-Type'].must_equal 'application/json'
35
+ end
36
+
37
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: candies
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-10 00:00:00.000000000 Z
12
+ date: 2011-11-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
16
- requirement: &70237840036260 !ruby/object:Gem::Requirement
16
+ requirement: &70267951013440 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.3.4
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70237840036260
24
+ version_requirements: *70267951013440
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: redis
27
- requirement: &70237840035400 !ruby/object:Gem::Requirement
27
+ requirement: &70267951012480 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 2.2.2
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70237840035400
35
+ version_requirements: *70267951012480
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: redis-namespace
38
- requirement: &70237840034480 !ruby/object:Gem::Requirement
38
+ requirement: &70267951011580 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.0.3
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70237840034480
46
+ version_requirements: *70267951011580
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: json
49
- requirement: &70237840032740 !ruby/object:Gem::Requirement
49
+ requirement: &70267951010600 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.5.3
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70237840032740
57
+ version_requirements: *70267951010600
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rake
60
- requirement: &70237840047340 !ruby/object:Gem::Requirement
60
+ requirement: &70267951009620 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 0.9.2
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70237840047340
68
+ version_requirements: *70267951009620
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: minitest
71
- requirement: &70237840045180 !ruby/object:Gem::Requirement
71
+ requirement: &70267951008760 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 2.7.0
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70237840045180
79
+ version_requirements: *70267951008760
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rack-test
82
- requirement: &70237840042840 !ruby/object:Gem::Requirement
82
+ requirement: &70267951007680 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0.6'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70237840042840
90
+ version_requirements: *70267951007680
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: turn
93
- requirement: &70237840039340 !ruby/object:Gem::Requirement
93
+ requirement: &70267951023220 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: 0.8.3
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70237840039340
101
+ version_requirements: *70267951023220
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: mocha
104
- requirement: &70237840054200 !ruby/object:Gem::Requirement
104
+ requirement: &70267951022460 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ~>
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: 0.10.0
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70237840054200
112
+ version_requirements: *70267951022460
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: timecop
115
- requirement: &70237840052480 !ruby/object:Gem::Requirement
115
+ requirement: &70267951021760 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ~>
@@ -120,7 +120,7 @@ dependencies:
120
120
  version: 0.3.5
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *70237840052480
123
+ version_requirements: *70267951021760
124
124
  description: Invisible image based tracing service with Redis backend
125
125
  email:
126
126
  - marcin.ciunelis@gmail.com
@@ -139,8 +139,13 @@ files:
139
139
  - lib/candies.rb
140
140
  - lib/candies/helper.rb
141
141
  - lib/candies/server.rb
142
+ - lib/candies/server/base.rb
143
+ - lib/candies/server/gif.rb
144
+ - lib/candies/server/json.rb
142
145
  - lib/candies/version.rb
143
- - spec/candies/server_spec.rb
146
+ - spec/candies/helper_spec.rb
147
+ - spec/candies/server/gif_spec.rb
148
+ - spec/candies/server/json_spec.rb
144
149
  - spec/spec_helper.rb
145
150
  homepage: ''
146
151
  licenses: []
@@ -156,7 +161,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
156
161
  version: '0'
157
162
  segments:
158
163
  - 0
159
- hash: -4015693725382346057
164
+ hash: -2058818266629124407
160
165
  required_rubygems_version: !ruby/object:Gem::Requirement
161
166
  none: false
162
167
  requirements:
@@ -165,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
170
  version: '0'
166
171
  segments:
167
172
  - 0
168
- hash: -4015693725382346057
173
+ hash: -2058818266629124407
169
174
  requirements: []
170
175
  rubyforge_project:
171
176
  rubygems_version: 1.8.10
@@ -173,5 +178,7 @@ signing_key:
173
178
  specification_version: 3
174
179
  summary: ''
175
180
  test_files:
176
- - spec/candies/server_spec.rb
181
+ - spec/candies/helper_spec.rb
182
+ - spec/candies/server/gif_spec.rb
183
+ - spec/candies/server/json_spec.rb
177
184
  - spec/spec_helper.rb