mongoid_traffic 0.2.5 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +88 -91
- data/Rakefile +2 -19
- data/lib/mongoid_traffic.rb +4 -1
- data/lib/mongoid_traffic/log.rb +29 -49
- data/lib/mongoid_traffic/logger.rb +33 -88
- data/lib/mongoid_traffic/version.rb +1 -1
- data/mongoid_traffic.gemspec +10 -10
- metadata +15 -84
- data/lib/mongoid_traffic/controller_additions.rb +0 -31
- data/lib/mongoid_traffic/logger/bots.rb +0 -31
- data/lib/mongoid_traffic/logger/browser.rb +0 -29
- data/lib/mongoid_traffic/logger/geo_ip.rb +0 -20
- data/lib/mongoid_traffic/logger/referer.rb +0 -25
- data/test/mongoid_traffic/controller_additions_test.rb +0 -25
- data/test/mongoid_traffic/log_test.rb +0 -143
- data/test/mongoid_traffic/logger/bots_test.rb +0 -21
- data/test/mongoid_traffic/logger/browser_test.rb +0 -24
- data/test/mongoid_traffic/logger/geoip_test.rb +0 -15
- data/test/mongoid_traffic/logger/referer_test.rb +0 -28
- data/test/mongoid_traffic/logger_test.rb +0 -62
- data/test/support/database_cleaner.rb +0 -10
- data/test/support/mongoid.rb +0 -8
- data/test/test_helper.rb +0 -22
- data/vendor/mongoid_traffic/GeoIP.dat +0 -0
- data/vendor/mongoid_traffic/allagents.xml +0 -22134
@@ -1,123 +1,68 @@
|
|
1
|
-
require 'uri'
|
2
|
-
require 'useragent'
|
3
|
-
|
4
|
-
require_relative './log'
|
5
|
-
require_relative './logger/bots'
|
6
|
-
require_relative './logger/browser'
|
7
|
-
require_relative './logger/geo_ip'
|
8
|
-
require_relative './logger/referer'
|
9
|
-
|
10
1
|
module MongoidTraffic
|
11
2
|
class Logger
|
12
|
-
|
13
|
-
|
14
|
-
|
3
|
+
attr_accessor :log_cls
|
4
|
+
attr_accessor :selector
|
5
|
+
attr_accessor :time_scope
|
6
|
+
attr_accessor :additonal_counters
|
15
7
|
|
16
8
|
def self.log(log_cls, *args)
|
17
9
|
new(log_cls, *args).log
|
18
10
|
end
|
19
11
|
|
20
|
-
|
21
|
-
|
22
|
-
def initialize(log_cls, ip_address: nil, referer: nil, scope: nil, time_scope: %i(month day), unique_id: nil, user_agent: nil)
|
12
|
+
def initialize(log_cls, options = {})
|
23
13
|
@log_cls = log_cls
|
24
|
-
@
|
25
|
-
@
|
26
|
-
@
|
27
|
-
|
28
|
-
|
29
|
-
@user_agent_string = user_agent
|
14
|
+
@selector = log_cls.criteria.selector
|
15
|
+
@time_scope = options.fetch(:time_scope, TIME_SCOPE_OPTIONS.keys)
|
16
|
+
@additonal_counters = options.except(:time_scope, :scope)
|
17
|
+
|
18
|
+
raise "Invalid time scope definition: #{time_scope}" unless time_scope.all? { |ts| TIME_SCOPE_OPTIONS.key?(ts) }
|
30
19
|
end
|
31
20
|
|
32
21
|
def log
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
@log_cls.collection.find(find_query(ts)).update_many(upsert_query, upsert: true)
|
22
|
+
time_scope.each do |ts|
|
23
|
+
log_cls.collection
|
24
|
+
.find(find_query(ts))
|
25
|
+
.update_many(upsert_query(ts), upsert: true)
|
38
26
|
end
|
39
27
|
end
|
40
28
|
|
41
|
-
|
42
|
-
|
43
|
-
def upsert_query
|
44
|
-
{
|
45
|
-
'$inc' => access_count_query
|
46
|
-
.merge(browser_query)
|
47
|
-
.merge(country_query)
|
48
|
-
.merge(referer_query)
|
49
|
-
.merge(unique_id_query),
|
50
|
-
'$set' => { uat: Time.now }
|
51
|
-
}
|
52
|
-
end
|
53
|
-
|
54
|
-
# ---------------------------------------------------------------------
|
55
|
-
|
56
|
-
def access_count_query
|
57
|
-
{ ac: 1 }
|
58
|
-
end
|
59
|
-
|
60
|
-
def browser_query
|
61
|
-
return {} unless browser.present?
|
62
|
-
browser_path = [browser.platform, browser.name, browser.version].map { |s| escape_key(s) }.join('.')
|
63
|
-
{ "b.#{browser_path}" => 1 }
|
64
|
-
end
|
29
|
+
private
|
65
30
|
|
66
|
-
def
|
67
|
-
|
68
|
-
return {} unless country_code2 = GeoIp.country_code2(@ip_address)
|
69
|
-
country_code_key = escape_key(country_code2)
|
70
|
-
{ "c.#{country_code_key}" => 1 }
|
31
|
+
def find_query(ts)
|
32
|
+
time_query(ts).merge(selector)
|
71
33
|
end
|
72
34
|
|
73
|
-
def
|
74
|
-
|
75
|
-
referer_key = escape_key(referer.to_s)
|
76
|
-
{ "r.#{referer_key}" => 1 }
|
77
|
-
end
|
35
|
+
def upsert_query(time_scope)
|
36
|
+
ts = TIME_SCOPE_OPTIONS[time_scope]
|
78
37
|
|
79
|
-
|
80
|
-
|
81
|
-
unique_id_key = escape_key(@unique_id.to_s)
|
82
|
-
{ "u.#{unique_id_key}" => 1 }
|
38
|
+
{ '$inc' => access_count_query.merge(additonal_counters_query),
|
39
|
+
'$set' => { ts: ts, uat: Time.now } }
|
83
40
|
end
|
84
41
|
|
85
|
-
|
86
|
-
|
87
|
-
def escape_key(key)
|
88
|
-
CGI.escape(key).gsub('.', '%2E')
|
42
|
+
def access_count_query
|
43
|
+
{ ac: 1 }
|
89
44
|
end
|
90
45
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
res
|
46
|
+
def additonal_counters_query
|
47
|
+
Array(additonal_counters).each_with_object({}) do |(name, value), res|
|
48
|
+
next unless field = find_field(name)
|
49
|
+
res["#{field.name}.#{value}"] = 1
|
50
|
+
end
|
97
51
|
end
|
98
52
|
|
99
|
-
def
|
100
|
-
|
53
|
+
def find_field(name)
|
54
|
+
log_cls.fields.detect do |field_name, field|
|
55
|
+
field_name == name.to_s || field.options[:as].to_s == name.to_s
|
56
|
+
end.try(:last)
|
101
57
|
end
|
102
58
|
|
103
59
|
def time_query(ts)
|
104
60
|
date = Date.today
|
61
|
+
|
105
62
|
case ts
|
106
63
|
when :day then { df: date, dt: date }
|
107
64
|
else { df: date.send("at_beginning_of_#{ts}"), dt: date.send("at_end_of_#{ts}") }
|
108
65
|
end
|
109
66
|
end
|
110
|
-
|
111
|
-
private # =============================================================
|
112
|
-
|
113
|
-
def browser
|
114
|
-
return unless @user_agent_string.present?
|
115
|
-
@browser ||= Browser.new(@user_agent_string)
|
116
|
-
end
|
117
|
-
|
118
|
-
def referer
|
119
|
-
return unless @referer_string.present?
|
120
|
-
@referer ||= Referer.new(@referer_string)
|
121
|
-
end
|
122
67
|
end
|
123
68
|
end
|
data/mongoid_traffic.gemspec
CHANGED
@@ -6,29 +6,29 @@ require 'mongoid_traffic/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'mongoid_traffic'
|
8
8
|
spec.version = MongoidTraffic::VERSION
|
9
|
-
spec.authors = [
|
9
|
+
spec.authors = ['Tomáš Celizna']
|
10
10
|
spec.email = ['tomas.celizna@gmail.com']
|
11
11
|
spec.description = 'Aggregated traffic logs stored in MongoDB.'
|
12
12
|
spec.summary = 'Aggregated traffic logs stored in MongoDB.'
|
13
13
|
spec.homepage = 'https://github.com/tomasc/mongoid_traffic'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
16
|
-
spec.files
|
17
|
-
|
18
|
-
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
|
20
|
+
spec.bindir = 'exe'
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
22
|
spec.require_paths = ['lib']
|
20
23
|
|
21
|
-
spec.add_dependency 'geoip'
|
22
24
|
spec.add_dependency 'mongoid', '>= 5', '< 8'
|
23
|
-
spec.add_dependency 'nokogiri'
|
24
|
-
spec.add_dependency 'useragent'
|
25
25
|
|
26
|
-
spec.add_development_dependency 'bundler', '~> 1.
|
26
|
+
spec.add_development_dependency 'bundler', '~> 1.12'
|
27
27
|
spec.add_development_dependency 'coveralls'
|
28
28
|
spec.add_development_dependency 'database_cleaner', '~> 1.5.2'
|
29
29
|
spec.add_development_dependency 'guard'
|
30
30
|
spec.add_development_dependency 'guard-minitest'
|
31
|
-
spec.add_development_dependency 'minitest'
|
31
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
32
32
|
spec.add_development_dependency 'minitest-around'
|
33
|
-
spec.add_development_dependency 'rake'
|
33
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
34
34
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid_traffic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomáš Celizna
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: geoip
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: mongoid
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,48 +30,20 @@ dependencies:
|
|
44
30
|
- - "<"
|
45
31
|
- !ruby/object:Gem::Version
|
46
32
|
version: '8'
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: nokogiri
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - ">="
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
54
|
-
type: :runtime
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
requirements:
|
58
|
-
- - ">="
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: '0'
|
61
|
-
- !ruby/object:Gem::Dependency
|
62
|
-
name: useragent
|
63
|
-
requirement: !ruby/object:Gem::Requirement
|
64
|
-
requirements:
|
65
|
-
- - ">="
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: '0'
|
68
|
-
type: :runtime
|
69
|
-
prerelease: false
|
70
|
-
version_requirements: !ruby/object:Gem::Requirement
|
71
|
-
requirements:
|
72
|
-
- - ">="
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
version: '0'
|
75
33
|
- !ruby/object:Gem::Dependency
|
76
34
|
name: bundler
|
77
35
|
requirement: !ruby/object:Gem::Requirement
|
78
36
|
requirements:
|
79
37
|
- - "~>"
|
80
38
|
- !ruby/object:Gem::Version
|
81
|
-
version: '1.
|
39
|
+
version: '1.12'
|
82
40
|
type: :development
|
83
41
|
prerelease: false
|
84
42
|
version_requirements: !ruby/object:Gem::Requirement
|
85
43
|
requirements:
|
86
44
|
- - "~>"
|
87
45
|
- !ruby/object:Gem::Version
|
88
|
-
version: '1.
|
46
|
+
version: '1.12'
|
89
47
|
- !ruby/object:Gem::Dependency
|
90
48
|
name: coveralls
|
91
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -146,16 +104,16 @@ dependencies:
|
|
146
104
|
name: minitest
|
147
105
|
requirement: !ruby/object:Gem::Requirement
|
148
106
|
requirements:
|
149
|
-
- - "
|
107
|
+
- - "~>"
|
150
108
|
- !ruby/object:Gem::Version
|
151
|
-
version: '0'
|
109
|
+
version: '5.0'
|
152
110
|
type: :development
|
153
111
|
prerelease: false
|
154
112
|
version_requirements: !ruby/object:Gem::Requirement
|
155
113
|
requirements:
|
156
|
-
- - "
|
114
|
+
- - "~>"
|
157
115
|
- !ruby/object:Gem::Version
|
158
|
-
version: '0'
|
116
|
+
version: '5.0'
|
159
117
|
- !ruby/object:Gem::Dependency
|
160
118
|
name: minitest-around
|
161
119
|
requirement: !ruby/object:Gem::Requirement
|
@@ -174,16 +132,16 @@ dependencies:
|
|
174
132
|
name: rake
|
175
133
|
requirement: !ruby/object:Gem::Requirement
|
176
134
|
requirements:
|
177
|
-
- - "
|
135
|
+
- - "~>"
|
178
136
|
- !ruby/object:Gem::Version
|
179
|
-
version: '0'
|
137
|
+
version: '10.0'
|
180
138
|
type: :development
|
181
139
|
prerelease: false
|
182
140
|
version_requirements: !ruby/object:Gem::Requirement
|
183
141
|
requirements:
|
184
|
-
- - "
|
142
|
+
- - "~>"
|
185
143
|
- !ruby/object:Gem::Version
|
186
|
-
version: '0'
|
144
|
+
version: '10.0'
|
187
145
|
description: Aggregated traffic logs stored in MongoDB.
|
188
146
|
email:
|
189
147
|
- tomas.celizna@gmail.com
|
@@ -201,27 +159,10 @@ files:
|
|
201
159
|
- README.md
|
202
160
|
- Rakefile
|
203
161
|
- lib/mongoid_traffic.rb
|
204
|
-
- lib/mongoid_traffic/controller_additions.rb
|
205
162
|
- lib/mongoid_traffic/log.rb
|
206
163
|
- lib/mongoid_traffic/logger.rb
|
207
|
-
- lib/mongoid_traffic/logger/bots.rb
|
208
|
-
- lib/mongoid_traffic/logger/browser.rb
|
209
|
-
- lib/mongoid_traffic/logger/geo_ip.rb
|
210
|
-
- lib/mongoid_traffic/logger/referer.rb
|
211
164
|
- lib/mongoid_traffic/version.rb
|
212
165
|
- mongoid_traffic.gemspec
|
213
|
-
- test/mongoid_traffic/controller_additions_test.rb
|
214
|
-
- test/mongoid_traffic/log_test.rb
|
215
|
-
- test/mongoid_traffic/logger/bots_test.rb
|
216
|
-
- test/mongoid_traffic/logger/browser_test.rb
|
217
|
-
- test/mongoid_traffic/logger/geoip_test.rb
|
218
|
-
- test/mongoid_traffic/logger/referer_test.rb
|
219
|
-
- test/mongoid_traffic/logger_test.rb
|
220
|
-
- test/support/database_cleaner.rb
|
221
|
-
- test/support/mongoid.rb
|
222
|
-
- test/test_helper.rb
|
223
|
-
- vendor/mongoid_traffic/GeoIP.dat
|
224
|
-
- vendor/mongoid_traffic/allagents.xml
|
225
166
|
homepage: https://github.com/tomasc/mongoid_traffic
|
226
167
|
licenses:
|
227
168
|
- MIT
|
@@ -242,18 +183,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
242
183
|
version: '0'
|
243
184
|
requirements: []
|
244
185
|
rubyforge_project:
|
245
|
-
rubygems_version: 2.7.
|
186
|
+
rubygems_version: 2.7.6
|
246
187
|
signing_key:
|
247
188
|
specification_version: 4
|
248
189
|
summary: Aggregated traffic logs stored in MongoDB.
|
249
|
-
test_files:
|
250
|
-
- test/mongoid_traffic/controller_additions_test.rb
|
251
|
-
- test/mongoid_traffic/log_test.rb
|
252
|
-
- test/mongoid_traffic/logger/bots_test.rb
|
253
|
-
- test/mongoid_traffic/logger/browser_test.rb
|
254
|
-
- test/mongoid_traffic/logger/geoip_test.rb
|
255
|
-
- test/mongoid_traffic/logger/referer_test.rb
|
256
|
-
- test/mongoid_traffic/logger_test.rb
|
257
|
-
- test/support/database_cleaner.rb
|
258
|
-
- test/support/mongoid.rb
|
259
|
-
- test/test_helper.rb
|
190
|
+
test_files: []
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module MongoidTraffic
|
2
|
-
module ControllerAdditions
|
3
|
-
def log_traffic(log_cls, scope: nil)
|
4
|
-
MongoidTraffic::Logger.log(
|
5
|
-
log_cls,
|
6
|
-
ip_address: request.remote_ip,
|
7
|
-
referer: request.headers['Referer'],
|
8
|
-
unique_id: request.session_options[:id], # FIXME: not sure about this
|
9
|
-
user_agent: request.headers['User-Agent']
|
10
|
-
)
|
11
|
-
end
|
12
|
-
|
13
|
-
def log_scoped_traffic(_log_cls, scope: nil)
|
14
|
-
log_traffic(scope: (scope || request.fullpath.split('?').first))
|
15
|
-
end
|
16
|
-
|
17
|
-
# ---------------------------------------------------------------------
|
18
|
-
|
19
|
-
def self.included(base)
|
20
|
-
base.extend ClassMethods
|
21
|
-
base.helper_method :log_traffic
|
22
|
-
base.helper_method :log_scoped_traffic
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
if defined? ActionController::Base
|
28
|
-
ActionController::Base.class_eval do
|
29
|
-
include MongoidTraffic::ControllerAdditions
|
30
|
-
end
|
31
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
|
3
|
-
# sourced from https://github.com/charlotte-ruby/impressionist/blob/master/lib/impressionist/bots.rb
|
4
|
-
|
5
|
-
module MongoidTraffic
|
6
|
-
class Logger
|
7
|
-
class Bots
|
8
|
-
DATA_URL = 'http://www.user-agents.org/allagents.xml'.freeze
|
9
|
-
FILE_PATH = File.join(File.dirname(__dir__), '..', '..', 'vendor', 'mongoid_traffic', 'allagents.xml')
|
10
|
-
|
11
|
-
class << self
|
12
|
-
def list
|
13
|
-
@list ||= begin
|
14
|
-
response = File.open(FILE_PATH).read
|
15
|
-
doc = Nokogiri::XML(response)
|
16
|
-
doc.xpath('//user-agent').inject([]) do |res, agent|
|
17
|
-
type = agent.xpath('Type').text
|
18
|
-
res << agent.xpath('String').text.gsub('<', '<') if %w(R S).include?(type)
|
19
|
-
res
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def is_a_bot?(referer)
|
25
|
-
return false unless referer.present?
|
26
|
-
list.include?(referer)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'user_agent'
|
2
|
-
|
3
|
-
module MongoidTraffic
|
4
|
-
class Logger
|
5
|
-
class Browser
|
6
|
-
def initialize(user_agent_string)
|
7
|
-
@user_agent_string = user_agent_string
|
8
|
-
end
|
9
|
-
|
10
|
-
def platform
|
11
|
-
user_agent.platform
|
12
|
-
end
|
13
|
-
|
14
|
-
def name
|
15
|
-
user_agent.browser
|
16
|
-
end
|
17
|
-
|
18
|
-
def version
|
19
|
-
user_agent.version.to_s.split('.')[0..1].join('.')
|
20
|
-
end
|
21
|
-
|
22
|
-
private # =============================================================
|
23
|
-
|
24
|
-
def user_agent
|
25
|
-
@user_agent ||= ::UserAgent.parse(@user_agent_string)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|