gricer 0.0.1

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 (88) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +84 -0
  3. data/Rakefile +49 -0
  4. data/app/assets/images/gricer/fluid/breadcrumb.png +0 -0
  5. data/app/assets/javascripts/gricer.js.coffee +85 -0
  6. data/app/assets/javascripts/gricer_backend_jquery.js.coffee +352 -0
  7. data/app/assets/javascripts/jquery.flot.js +2599 -0
  8. data/app/assets/javascripts/jquery.flot.pie.js +750 -0
  9. data/app/assets/javascripts/jquery.flot.resize.js +60 -0
  10. data/app/assets/javascripts/jquery.flot.symbol.js +70 -0
  11. data/app/assets/javascripts/worldmap.js +146 -0
  12. data/app/assets/stylesheets/gricer/fluid-jquery-ui.css.scss +1298 -0
  13. data/app/assets/stylesheets/gricer/fluid.css.scss +240 -0
  14. data/app/assets/stylesheets/gricer/helpers/css3.css.scss +21 -0
  15. data/app/controllers/gricer/base_controller.rb +141 -0
  16. data/app/controllers/gricer/capture_controller.rb +42 -0
  17. data/app/controllers/gricer/dashboard_controller.rb +18 -0
  18. data/app/controllers/gricer/requests_controller.rb +42 -0
  19. data/app/controllers/gricer/sessions_controller.rb +24 -0
  20. data/app/helpers/gricer/base_helper.rb +22 -0
  21. data/app/models/gricer/agent.rb +789 -0
  22. data/app/models/gricer/request.rb +239 -0
  23. data/app/models/gricer/session.rb +433 -0
  24. data/app/views/gricer/capture/index.html.erb +1 -0
  25. data/app/views/gricer/dashboard/_menu.html.erb +10 -0
  26. data/app/views/gricer/dashboard/_overview.html.erb +33 -0
  27. data/app/views/gricer/dashboard/index.html.erb +19 -0
  28. data/config/routes.rb +51 -0
  29. data/lib/gricer.rb +36 -0
  30. data/lib/gricer/action_controller/base.rb +28 -0
  31. data/lib/gricer/action_controller/track.rb +132 -0
  32. data/lib/gricer/active_model/statistics.rb +167 -0
  33. data/lib/gricer/config.rb +125 -0
  34. data/lib/gricer/engine.rb +9 -0
  35. data/lib/gricer/localization.rb +3 -0
  36. data/lib/tasks/gricer_tasks.rake +92 -0
  37. data/spec/controllers/gricer/base_controller_spec.rb +207 -0
  38. data/spec/controllers/gricer/capture_controller_spec.rb +44 -0
  39. data/spec/controllers/gricer/dashboard_controller_spec.rb +44 -0
  40. data/spec/controllers/gricer/requests_controller_spec.rb +36 -0
  41. data/spec/controllers/gricer/sessions_controller_spec.rb +37 -0
  42. data/spec/dummy/Rakefile +7 -0
  43. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  44. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  45. data/spec/dummy/app/assets/stylesheets/dashboard.css +4 -0
  46. data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
  47. data/spec/dummy/app/assets/stylesheets/sessions.css +4 -0
  48. data/spec/dummy/app/controllers/application_controller.rb +23 -0
  49. data/spec/dummy/app/controllers/dashboard_controller.rb +19 -0
  50. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  51. data/spec/dummy/app/helpers/dashboard_helper.rb +2 -0
  52. data/spec/dummy/app/views/dashboard/index.html.erb +236 -0
  53. data/spec/dummy/app/views/layouts/application.html.erb +16 -0
  54. data/spec/dummy/config.ru +4 -0
  55. data/spec/dummy/config/application.rb +48 -0
  56. data/spec/dummy/config/boot.rb +10 -0
  57. data/spec/dummy/config/cucumber.yml +9 -0
  58. data/spec/dummy/config/database.yml +25 -0
  59. data/spec/dummy/config/environment.rb +5 -0
  60. data/spec/dummy/config/environments/development.rb +27 -0
  61. data/spec/dummy/config/environments/production.rb +51 -0
  62. data/spec/dummy/config/environments/test.rb +39 -0
  63. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  64. data/spec/dummy/config/initializers/inflections.rb +10 -0
  65. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  66. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  67. data/spec/dummy/config/initializers/session_store.rb +8 -0
  68. data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
  69. data/spec/dummy/config/locales/en.yml +5 -0
  70. data/spec/dummy/config/routes.rb +11 -0
  71. data/spec/dummy/db/schema.rb +241 -0
  72. data/spec/dummy/log/development.log +0 -0
  73. data/spec/dummy/public/404.html +26 -0
  74. data/spec/dummy/public/422.html +26 -0
  75. data/spec/dummy/public/500.html +26 -0
  76. data/spec/dummy/public/favicon.ico +0 -0
  77. data/spec/dummy/script/rails +6 -0
  78. data/spec/helpers/gricer/base_helper_spec.rb +28 -0
  79. data/spec/lib/gricer/action_controller/track_spec.rb +63 -0
  80. data/spec/models/gricer/agent_spec.rb +829 -0
  81. data/spec/models/gricer/request_spec.rb +145 -0
  82. data/spec/models/gricer/session_spec.rb +209 -0
  83. data/spec/routing/capture_routes_spec.rb +6 -0
  84. data/spec/routing/dashboard_routes_spec.rb +9 -0
  85. data/spec/routing/requests_routes_spec.rb +90 -0
  86. data/spec/routing/sessions_routes_spec.rb +115 -0
  87. data/spec/spec_helper.rb +23 -0
  88. metadata +185 -0
@@ -0,0 +1,240 @@
1
+ @import 'helpers/css3';
2
+
3
+ .gricer-stat {
4
+ position: absolute;
5
+ top: 0;
6
+ bottom: 0;
7
+ width: 100%;
8
+ overflow: none;
9
+ font-size: 11px;
10
+ line-height: 15px;
11
+ font-family: 'Lucida Grande', 'Arial', 'Helvetica', 'Sans-Serif';
12
+
13
+ #gricer-header {
14
+ background: #000;
15
+ color: #000;
16
+ line-height: 20px;
17
+ height: 20px;
18
+ background: #eee;
19
+ @include gradient(#eee,#ccc);
20
+
21
+ .path {
22
+ a {
23
+ display: block;
24
+ float: left;
25
+ color: #000;
26
+ background: image-url("gricer/fluid/breadcrumb.png") right top no-repeat;
27
+ height: 20px;
28
+ line-height: 20px;
29
+ padding: 0 15px 0 8px;
30
+ text-decoration: none;
31
+ }
32
+
33
+ a:last-child {
34
+ font-weight: bold;
35
+ }
36
+ }
37
+
38
+ .dates {
39
+ padding: 0 7px;
40
+ float: right;
41
+ input {
42
+ width: 8em;
43
+ height: 11px;
44
+ padding: 2px;
45
+ border: none;
46
+ background: transparent;
47
+ }
48
+ #gricer-from-field {
49
+ text-align: right;
50
+ }
51
+ }
52
+ }
53
+
54
+ #gricer-menu {
55
+ position: absolute;
56
+ float: left;
57
+ width: 182px;
58
+ padding: 4px 0;
59
+ background: #dfe4eb;
60
+ border-right: 1px solid #b4b4b4;
61
+ top: 20px;
62
+
63
+ bottom: 0;
64
+ overflow: auto;
65
+
66
+ a, span {
67
+ display: block;
68
+ text-decoration: none;
69
+ color: #000;
70
+ border-top: 1px solid transparent;
71
+ padding: 2px 8px;
72
+ &.active {
73
+ border-top: 1px solid #a3b1cc;
74
+ background: #94a6c5;
75
+ @include gradient(#b0bed7, #8195b8);
76
+ color: #fff;
77
+ }
78
+ }
79
+
80
+ span {
81
+ color: #999;
82
+ font-weight: bold;
83
+ }
84
+
85
+ div a {
86
+ padding-left: 16px;
87
+ }
88
+ }
89
+
90
+ #gricer-container
91
+ {
92
+ position: absolute;
93
+ float: left;
94
+ left: 183px;
95
+ top: 20px;
96
+ right: 0;
97
+ bottom: 0;
98
+ }
99
+
100
+
101
+ #gricer-container {
102
+
103
+ .overview {
104
+ position: absolute;
105
+ top: 0;
106
+ bottom: 0;
107
+ width: 100%;
108
+ overflow: auto;
109
+ padding: 4px 8px;
110
+ font-size: 30px;
111
+ line-height: 45px;
112
+ }
113
+
114
+ .flot-chart {
115
+ position: absolute;
116
+ background: #666f83;
117
+ color: #999;
118
+ top: 0;
119
+ left: 0;
120
+ right: 0;
121
+ padding: 0 2.5%;
122
+ height: 250px;
123
+ #flot-line-chart, #flot-pie-chart {
124
+ width: 100%;
125
+ height: 250px;
126
+ }
127
+
128
+ }
129
+
130
+ .type-selector {
131
+ position: absolute;
132
+ right: 4px;
133
+ top: 4px;
134
+
135
+ span, a {
136
+ padding: 2px 4px;
137
+ background: #ccc;
138
+ @include gradient(#ddd, #bbb);
139
+ border-right: 1px solid #b4b4b4;
140
+ color: #000;
141
+ text-decoration: none;
142
+ }
143
+
144
+ span {
145
+ background: #666;
146
+ @include gradient(#555, #777);
147
+ color: #fff;
148
+ }
149
+
150
+ span:first-child,
151
+ a:first-child {
152
+ @include border-radius(9px 0 0 9px);
153
+ padding-left: 9px;
154
+ }
155
+
156
+ span:last-child,
157
+ a:last-child {
158
+ @include border-radius(0 9px 9px 0);
159
+ border-right: none;
160
+ padding-right: 9px;
161
+ }
162
+ }
163
+
164
+ .data {
165
+ position: absolute;
166
+ top: 250px;
167
+ bottom: 0;
168
+ width: 100%;
169
+ overflow: auto;
170
+ }
171
+ table {
172
+ width: 100%;
173
+ padding: 0;
174
+ border-spacing: 0;
175
+ empty-cells: show;
176
+
177
+ th, td {
178
+ width: auto;
179
+ padding: 2px 4px;
180
+ font-size: 11px;
181
+
182
+ a {
183
+ color: #009;
184
+ text-decoration: none;
185
+ }
186
+
187
+ .badge {
188
+ float: left;
189
+ display: block;
190
+ @include border-radius(5px);
191
+ margin: 3px;
192
+ width: 10px;
193
+ height: 10px;
194
+ }
195
+ }
196
+
197
+ tr:nth-child(even) {
198
+ th, td {
199
+ background-color: #f3f5fa;
200
+ white-space: nowrap;
201
+ }
202
+ }
203
+
204
+ tr:first-child {
205
+ th {
206
+ background: #eee;
207
+ @include gradient(#ccc,#eee);
208
+ border-bottom: 1px solid #b4b4b4;
209
+ border-right: 1px solid #b4b4b4;
210
+ overflow: hidden;
211
+ white-space: nowrap;
212
+ }
213
+ }
214
+
215
+ th.number,
216
+ td.number {
217
+ text-align: right;
218
+ }
219
+
220
+ th.boolean,
221
+ td.boolean {
222
+ max-width: 30px;
223
+ }
224
+
225
+ td.boolean {
226
+ text-align: center;
227
+ }
228
+
229
+ &.process {
230
+ tr:nth-child(1) {
231
+ th {
232
+ text-align: center;
233
+ font-size: 9px;
234
+ lin-height: 11px;
235
+ }
236
+ }
237
+ }
238
+ }
239
+ }
240
+ }
@@ -0,0 +1,21 @@
1
+ @mixin border-radius($radius) {
2
+ -webkit-border-radius: $radius;
3
+ -moz-border-radius: $radius;
4
+ -o-border-radius: $radius;
5
+ -ms-border-radius: $radius;
6
+ -khtml-border-radius: $radius;
7
+ border-radius: $radius;
8
+ }
9
+
10
+ @mixin gradient($from, $to) {
11
+ background-image: -webkit-gradient(linear, left top, left bottom, from($from), to($to));
12
+ background-image: -moz-linear-gradient($from, $to);
13
+ background-image: linear-gradient($from, $to);
14
+ }
15
+
16
+ @mixin rotate($degree: -90deg) {
17
+ -moz-transform:rotate($degree);
18
+ -webkit-transform:rotate($degree);
19
+ -o-transform:rotate($degree);
20
+ transform:rotate($degree);
21
+ }
@@ -0,0 +1,141 @@
1
+ module Gricer
2
+ # This is the base controller which is used by Gricer's basic statistics controllers
3
+ #
4
+ # You can use this to make your own statistics controllers from a scaffold.
5
+ class BaseController < ::ApplicationController
6
+ before_filter :guess_from_thru
7
+ helper BaseHelper
8
+
9
+ layout ::Gricer.config.admin_layout if ::Gricer.config.admin_layout
10
+
11
+ # This action generates a JSON for a process statistics.
12
+ def process_stats
13
+ @items = basic_collection
14
+
15
+ handle_special_fields
16
+
17
+ data = {
18
+ alternatives: [
19
+ {
20
+ type: 'spread',
21
+ uri: url_for(action: "spread_stats", field: params[:field], filters: params[:filters], only_path: true)
22
+ },
23
+ {
24
+ type: 'process'
25
+ }
26
+ ],
27
+ from: @stat_from.to_time.utc.to_i * 1000,
28
+ thru: @stat_thru.to_time.utc.to_i * 1000,
29
+ step: @stat_step.to_i * 1000,
30
+ data: @items.stat(params[:field], @stat_from, @stat_thru, @stat_step)
31
+ }
32
+
33
+ if further_details.keys.include? params[:field]
34
+ filters = (params[:filters] || {})
35
+ filters[params[:field]] = '%{self}'
36
+
37
+ data[:detail_uri] = url_for(action: "process_stats", field: further_details[params[:field]], filters: filters, only_path: true)
38
+ end
39
+
40
+ render json: data
41
+ end
42
+
43
+ # This action generates a JSON for a spread statistics.
44
+ def spread_stats
45
+ @items = basic_collection.between_dates(@stat_from, @stat_thru)
46
+
47
+ handle_special_fields
48
+
49
+ data = {
50
+ alternatives: [
51
+ {
52
+ type: 'spread'
53
+ },
54
+ {
55
+ type: 'process',
56
+ uri: url_for(action: "process_stats", field: params[:field], filters: params[:filters], only_path: true)
57
+ }
58
+ ],
59
+ from: @stat_from.to_time.utc.to_i * 1000,
60
+ thru: @stat_thru.to_time.utc.to_i * 1000,
61
+ total: @items.count(:id),
62
+ data: @items.count_by(params[:field])
63
+ }
64
+
65
+ if further_details.keys.include? params[:field]
66
+ filters = (params[:filters] || {})
67
+ filters[params[:field]] = '%{self}'
68
+
69
+ data[:detail_uri] = url_for(action: "spread_stats", field: further_details[params[:field]], filters: filters, only_path: true)
70
+ end
71
+
72
+ render json: data
73
+ end
74
+
75
+ private
76
+ # @abstract
77
+ # Define which is the basic collection to be processed by the controller.
78
+ # This value has to be overwritten to use the process_stats or spread_stats actions.
79
+ def basic_collection
80
+ raise 'basic_collection must be defined'
81
+ end
82
+
83
+ # Define how to handle special fields
84
+ def handle_special_fields
85
+ if params[:filters]
86
+ params[:filters].each do |filter_attr, filter_value|
87
+ @items = @items.filter_by(filter_attr, filter_value)
88
+ end
89
+ end
90
+ end
91
+
92
+ # Define how to handle further details
93
+ def further_details
94
+ {}
95
+ end
96
+
97
+ # Guess for which time range to display statistics
98
+ def guess_from_thru
99
+ begin
100
+ @stat_thru = Time.parse(params[:thru]).to_date
101
+ rescue
102
+ end
103
+
104
+ begin
105
+ @stat_from = Time.parse(params[:from]).to_date
106
+ rescue
107
+ end
108
+
109
+ if @stat_from.nil?
110
+ if @stat_thru.nil?
111
+ @stat_thru = Time.now.localtime.to_date - 1.day
112
+ end
113
+ @stat_from = @stat_thru - 1.week + 1.day
114
+ else
115
+ if @stat_thru.nil?
116
+ @stat_thru = @stat_from + 1.week - 1.day
117
+ end
118
+ end
119
+
120
+ @stat_step = 1.day
121
+
122
+ duration = @stat_thru - @stat_from
123
+
124
+ if duration < 90
125
+ @stat_step = 12.hours
126
+ end
127
+
128
+ if duration < 30
129
+ @stat_step = 6.hour
130
+ end
131
+
132
+ if duration < 10
133
+ @stat_step = 1.hour
134
+ end
135
+
136
+ #if @stat_thru - @stat_from > 12.month
137
+ # @stat_step = 4.week
138
+ #end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,42 @@
1
+ module Gricer
2
+ # This is the controller to capture additional values from the Javascript track tag.
3
+ #
4
+ # @see Gricer::TrackHelper#gricer_track_tag
5
+ class CaptureController < ::ApplicationController
6
+ # This action stores the data submitted by the Javascript.
7
+ def index
8
+ gricer_request = Request.find_by_id(params[:id])
9
+ gricer_session = Session.find_by_id(session[:gricer_session])
10
+
11
+ if gricer_session
12
+ gricer_session.javascript = true
13
+ gricer_session.java = params[:j]
14
+ gricer_session.flash_version = params[:f] unless params[:f] == 'false'
15
+ gricer_session.silverlight_version = params[:sl] unless params[:sl] == 'false'
16
+ gricer_session.screen_width = params[:sx]
17
+ gricer_session.screen_height = params[:sy]
18
+ gricer_session.screen_size = "#{params[:sx]}x#{params[:sy]}" unless params[:sx].blank? or params[:sy].blank?
19
+ gricer_session.screen_depth = params[:sd]
20
+ gricer_session.save
21
+
22
+ if gricer_request and gricer_request.session == gricer_session
23
+
24
+ gricer_request.javascript = true
25
+ gricer_request.window_width = params[:wx]
26
+ gricer_request.window_height = params[:wy]
27
+
28
+ if gricer_request.save
29
+ render text: 'ok'
30
+ else
31
+ render text: 'session only', status: 500
32
+ end
33
+ return
34
+ else
35
+ render text: 'session only'
36
+ return
37
+ end
38
+ end
39
+ render text: 'failed', status: 500
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,18 @@
1
+ module Gricer
2
+ # This controller contains the dashboard for the administration view
3
+ class DashboardController < BaseController
4
+ # This action renders the frame for the statistics tool
5
+ def index
6
+ @sessions = Session.browsers.between_dates(@stat_from, @stat_thru)
7
+ @requests = Request.browsers.between_dates(@stat_from, @stat_thru)
8
+ end
9
+
10
+ # This action renderes the overview of some data in the statistics tool
11
+ def overview
12
+ @sessions = Session.browsers.between_dates(@stat_from, @stat_thru)
13
+ @requests = Request.browsers.between_dates(@stat_from, @stat_thru)
14
+
15
+ render partial: 'overview.html', locals: {sessions: @sessions, requests: @requests}
16
+ end
17
+ end
18
+ end