simple_events_redis 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +15 -0
  2. data/README.md +41 -0
  3. data/lib/events.rb +348 -0
  4. metadata +46 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MzRlMWU0MjUxNGIxYmFiZTBiN2YzMDYyZjdkN2Q1NTA3ZDdhYzFlOQ==
5
+ data.tar.gz: !binary |-
6
+ NzFlOGMwOWVhNWZkMDdmNWFkNDA1MDJhOTYxMjAxYWI5MDViZGM1ZA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ YzQ0ZjgyZGE0NGVhZWQwYjgxZjBjMmFiOThlYTFiZjZjZTVlZWFlZGRjOGRi
10
+ MzdjMzUwOGRkYTI5NzZiMTVjMTNmMjIyMTkwZjE5ZWRlNDk2ODVmN2IzYjM4
11
+ ZDZhYjI2NmE0MTczYjBiOWM5YTRkMDZlNWJiZmM5NjA0MGRlYzA=
12
+ data.tar.gz: !binary |-
13
+ YjdjOTBhNWRmMDNlZTQ0OTViMGNlOTQzMDViMzZkZDU5ODk4ODVkNmYyMzkx
14
+ ZjU0ODNiNDU1N2E5MDA0ODk4NGM3OWYyODliNWExYzM2M2VlMTVmMDk2NmNi
15
+ ZTA1MTdjNTI2NmMzOGNiNjNhYmJkYWI5MTk2MmRlODVhNzRhMTA=
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Simple tracking of custom events
2
+
3
+
4
+ Library to store custom data in lists by days in Redis.
5
+ Old data is automatically removed.
6
+ Useful for debugging and tracking different events in application.
7
+
8
+
9
+ ## Overview
10
+ Data is stored in Redis in lists with names:
11
+ <<YOUR_SITE_NAME>> : lists : <list_name> : <day> - Redis list
12
+
13
+ for example,
14
+
15
+ mysite:lists:mylist:20130407 - list for day April 04, 2013
16
+
17
+
18
+ ## Installation
19
+
20
+ It uses gem 'redis' and relies on $redis global variable to access Redis server.
21
+
22
+ in Rails application:
23
+
24
+ gem 'redis'
25
+ gem 'lists_by_days_redis'
26
+
27
+
28
+
29
+ Setup:
30
+
31
+ initializer:
32
+
33
+ ListsByDaysRedis::List::SITE_NAME = 'mysite'
34
+ ListsByDaysRedis::List::EXPIRE_DAYS = 7
35
+
36
+
37
+
38
+ ## Add new item to list
39
+
40
+
41
+
data/lib/events.rb ADDED
@@ -0,0 +1,348 @@
1
+ module SimpleEventsRedis
2
+
3
+ require 'redis'
4
+
5
+ class Events
6
+ # static data
7
+ #PROCESSES = ['effects']
8
+ SITE_NAME = ''
9
+
10
+ EXPIRE_DAYS = 7
11
+
12
+
13
+ @@redis = nil
14
+
15
+ # redis object to access Redis server
16
+ def self.redis
17
+ return @@redis unless @redis.nil?
18
+
19
+ # init by global object
20
+ unless $redis.nil?
21
+ @@redis = $redis
22
+ return @@redis
23
+ end
24
+
25
+
26
+ # default
27
+ @@redis = Redis.new(:host => 'localhost', :port => 6379)
28
+
29
+ @@redis
30
+ end
31
+
32
+ # methods for any log_type add_<<ANY_LOG_TYPE>>
33
+ def self.method_missing(method_name, *args, &block)
34
+ if method_name.to_s =~ /^log_(.+)$/
35
+ self.log($1, *args)
36
+ else
37
+ super
38
+ end
39
+ end
40
+
41
+
42
+ # logging
43
+
44
+ def self.log(log_name, data={})
45
+ t = Time.now.utc.to_i
46
+ rkey = self.redis_key_log log_name
47
+
48
+ #
49
+ hash = {:created=>t}
50
+ if data.is_a?(Hash)
51
+ data.each_pair { |k,v| hash["#{k}"] = v }
52
+ elsif data.is_a?(String)
53
+ hash["msg"] = data
54
+ else
55
+ hash["msg"] = "#{data.inspect}"
56
+ end
57
+
58
+ #
59
+ require 'json'
60
+ s = JSON.generate(hash)
61
+
62
+ redis.rpush rkey, s
63
+ redis.expireat rkey, t+EXPIRE_DAYS*24*60*60
64
+
65
+ return true
66
+ end
67
+
68
+
69
+ def self.log_event(log_name, event_name, msg, data={})
70
+ data['event'] = event_name
71
+ data['msg'] = msg
72
+ return self.log log_name, data
73
+ end
74
+
75
+ #
76
+ def self.debug(event_name, msg, data={})
77
+ data['event'] = event_name
78
+ data['msg'] = msg
79
+ return self.log 'debug', data
80
+ end
81
+
82
+
83
+
84
+ def self.get_logs(log_name, n_days_back=-1, filter={})
85
+ all_keys = redis.keys(self.redis_key_log_prefix + "#{log_name}:" +'*')
86
+
87
+ return [] if all_keys.nil?
88
+
89
+ require 'json'
90
+
91
+ tnow = Time.now.utc.to_i
92
+ rows = []
93
+ all_keys.each do |rkey|
94
+ day = self.parse_date rkey
95
+
96
+ # if cannot parse key
97
+ next if day.nil?
98
+
99
+ # if not too old day
100
+ if n_days_back>0
101
+ next if tnow - day.to_i > n_days_back * (60*60*24)
102
+ end
103
+
104
+ # get all items from the list
105
+ values = redis.lrange rkey, 0, 100000
106
+
107
+ values.each do |v|
108
+ #r = Marshal.load v
109
+ r = JSON.parse(v)
110
+
111
+ # filter
112
+ is_good = true
113
+
114
+ unless filter.nil? && filter.is_a?(Hash)
115
+ filter.each_pair do |field_name, field_value|
116
+ if r[field_name].nil?
117
+ is_good = false
118
+ break
119
+ end
120
+ if r[field_name] != field_value
121
+ is_good = false
122
+ break
123
+ end
124
+ end
125
+ end
126
+
127
+ # add to result
128
+ if is_good
129
+ rows << r
130
+ end
131
+ end
132
+
133
+ end
134
+
135
+ rows
136
+ end
137
+
138
+
139
+
140
+
141
+
142
+ # status
143
+ def self.status_set(event_name)
144
+ redis.hset self.redis_key_status, event_name, Time.now.utc.to_i
145
+
146
+ return true
147
+ end
148
+
149
+ def self.get_status(event_name, v_def=nil)
150
+ v = redis.hget self.redis_key_status, event_name
151
+ v ||= v_def
152
+ v
153
+ end
154
+
155
+ def self.get_statuses(pattern='*')
156
+ # event_names like 'name*'
157
+
158
+ rows = []
159
+
160
+ all_values = redis.hgetall self.redis_key_status
161
+
162
+ all_values.each do |event, v|
163
+ rows << {:site=>SITE_NAME, :event=>event, :v=>v}
164
+ end
165
+
166
+ rows
167
+ end
168
+
169
+
170
+
171
+ # counters
172
+
173
+ def self.stat_add(event_name, n=1)
174
+ redis.hincrby self.redis_key_stat, event_name, n
175
+
176
+ return true
177
+ end
178
+
179
+ def self.stat_add_perf(event_name, duration_secs, n=1)
180
+ redis.hincrby self.redis_key_stat, event_name+'_time', (duration_secs*1000).floor
181
+ redis.hincrby self.redis_key_stat, event_name+'_n', 1
182
+
183
+ return 1
184
+ end
185
+
186
+
187
+ def self.get_stats(n_days_back=1)
188
+ rows = []
189
+
190
+ self.stat_walk(n_days_back, 0) do |key, day|
191
+ all_values = redis.hgetall key
192
+
193
+ all_values.each do |event, v|
194
+ rows << {:site=>SITE_NAME, :created=>day.to_i, :event=>event, :amount=>v.to_i}
195
+ end
196
+ end
197
+
198
+ rows
199
+ end
200
+
201
+
202
+
203
+
204
+ # helper methods
205
+
206
+ def self.redis_key_prefix
207
+ "#{SITE_NAME=='' ? '' : SITE_NAME+':'}"
208
+ end
209
+
210
+ def self.key_day(d=nil)
211
+ d ||= DateTime.now.new_offset(0)
212
+
213
+ d.strftime("%Y%m%d")
214
+ end
215
+
216
+
217
+ # redis keys for log
218
+ def self.redis_key_log_prefix
219
+ self.redis_key_prefix + "log:"
220
+ end
221
+
222
+ def self.redis_key_log(name)
223
+ self.redis_key_log_prefix + "#{name}:" + self.key_day
224
+ end
225
+
226
+
227
+ # redis keys for status
228
+
229
+ def self.redis_key_status
230
+ self.redis_key_prefix + 'status'
231
+ end
232
+
233
+
234
+ # redis keys for stat
235
+
236
+ def self.redis_key_stat_prefix
237
+ self.redis_key_prefix + 'stat:'
238
+ end
239
+
240
+ def self.redis_key_stat
241
+ self.redis_key_stat_prefix + self.key_day
242
+ end
243
+
244
+
245
+ #
246
+ def self.parse_date(s)
247
+ # parse key
248
+ mm = s.scan(/(\d\d\d\d)(\d\d)(\d\d)$/i)
249
+
250
+ return nil if mm.nil? || mm[0].nil?
251
+
252
+ y, m, d = mm[0].map{|v| v.to_i}
253
+
254
+ Time.utc(y,m,d)
255
+ end
256
+
257
+
258
+
259
+ # clear data
260
+
261
+ def self.clear_logs_all
262
+ keys = redis.keys self.redis_key_log_prefix + '*'
263
+ return if keys.empty?
264
+ redis.del keys
265
+ end
266
+
267
+ def self.clear_logs(name)
268
+ keys = redis.keys self.redis_key_log_prefix+"#{name}:*"
269
+ return if keys.empty?
270
+ redis.del keys
271
+ end
272
+
273
+ # TODO:
274
+ def self.clear_logs_old(name)
275
+
276
+ end
277
+
278
+
279
+ # clear status
280
+
281
+ def self.clear_status_all
282
+ rkey = self.redis_key_status
283
+
284
+ redis.del rkey
285
+ end
286
+
287
+
288
+
289
+ # clear stats
290
+
291
+ def self.clear_stats_all
292
+ keys = redis.keys self.redis_key_stat_prefix+"*"
293
+ return if keys.empty?
294
+ redis.del keys
295
+ end
296
+
297
+
298
+ # clear data older than n_days_back
299
+ def self.clear_stats_old(n_days_back=1)
300
+ rows = []
301
+
302
+ # all days older than N days
303
+ self.stat_walk(-1, n_days_back) do |key, day|
304
+ redis.del key
305
+ end
306
+
307
+ rows
308
+ end
309
+
310
+
311
+ def self.stat_walk(n_days_back_from, n_days_back_to)
312
+
313
+ tnow = Time.now.utc_to_i
314
+
315
+ key_prefix = self.redis_key_stat_prefix
316
+ keys = redis.keys key_prefix + "*"
317
+
318
+ keys.each do |key|
319
+ # parse key
320
+ mm = key.scan(/#{key_prefix}:(\d+)$/i)
321
+
322
+ next if mm.nil? || mm[0].nil?
323
+
324
+ day = self.parse_date(mm[0][0])
325
+
326
+ next if day.nil?
327
+
328
+ # too old
329
+ if n_days_back_from>=0
330
+ next if tnow - day.to_i > n_days_back_from * (60*60*24)
331
+ end
332
+
333
+ # too fresh
334
+ if n_days_back_to>=0
335
+ next if tnow - day.to_i < n_days_back_to * (60*60*24)
336
+ end
337
+
338
+ # do the work
339
+ yield(key, day)
340
+
341
+ end
342
+ end
343
+
344
+ end
345
+
346
+
347
+ end
348
+
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_events_redis
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - ! 'Max Ivak '
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-04-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: ''
14
+ email:
15
+ - maxivak@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/events.rb
21
+ - README.md
22
+ homepage: https://github.com/maxivak/simple_events_redis/
23
+ licenses: []
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubyforge_project:
41
+ rubygems_version: 2.0.3
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: ! 'Library to track events: counters of events, logging, state monitoring.
45
+ Data is stored in Redis'
46
+ test_files: []