CoScale - Version 0.11.1

Version Notes

The CoScale module is still under development. All feedback is welcome.

Download this release

Release Info

Developer CoScale Developer
Extension CoScale
Version 0.11.1
Comparing to
See all releases


Version 0.11.1

Files changed (28) hide show
  1. app/code/community/CoScale/Monitor/Helper/Data.php +14 -0
  2. app/code/community/CoScale/Monitor/Model/Cronjob.php +23 -0
  3. app/code/community/CoScale/Monitor/Model/Event.php +292 -0
  4. app/code/community/CoScale/Monitor/Model/Event/Cache.php +169 -0
  5. app/code/community/CoScale/Monitor/Model/Event/Reindex.php +43 -0
  6. app/code/community/CoScale/Monitor/Model/Event/Store.php +38 -0
  7. app/code/community/CoScale/Monitor/Model/Metric.php +148 -0
  8. app/code/community/CoScale/Monitor/Model/Metric/Abstract.php +87 -0
  9. app/code/community/CoScale/Monitor/Model/Metric/Customer.php +91 -0
  10. app/code/community/CoScale/Monitor/Model/Metric/File.php +56 -0
  11. app/code/community/CoScale/Monitor/Model/Metric/Order.php +469 -0
  12. app/code/community/CoScale/Monitor/Model/Metric/Product.php +200 -0
  13. app/code/community/CoScale/Monitor/Model/Metric/Rewrite.php +41 -0
  14. app/code/community/CoScale/Monitor/Model/Resource/Event.php +49 -0
  15. app/code/community/CoScale/Monitor/Model/Resource/Event/Collection.php +21 -0
  16. app/code/community/CoScale/Monitor/Model/Resource/Metric.php +50 -0
  17. app/code/community/CoScale/Monitor/Model/Resource/Metric/Collection.php +20 -0
  18. app/code/community/CoScale/Monitor/etc/config.xml +233 -0
  19. app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/install-0.1.0.php +175 -0
  20. app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/upgrade-0.1.0-0.2.0.php +18 -0
  21. app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/upgrade-0.2.0-0.3.0.php +20 -0
  22. app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/upgrade-0.3.0-0.4.0.php +25 -0
  23. app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/upgrade-0.4.0-0.5.0.php +24 -0
  24. app/design/frontend/base/default/layout/coscale_monitor.xml +12 -0
  25. app/design/frontend/base/default/template/coscale_monitor/rum.phtml +1 -0
  26. app/etc/modules/CoScale_Monitor.xml +9 -0
  27. package.xml +18 -0
  28. shell/coscale.php +197 -0
app/code/community/CoScale/Monitor/Helper/Data.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CoScale module helper
5
+ *
6
+ * @package CoScale_Monitor
7
+ * @author Rian Orie <rian.orie@supportdesk.nu>
8
+ * @created 2015-07-03
9
+ * @version 1.0
10
+ */
11
+ class CoScale_Monitor_Helper_Data extends Mage_Core_Helper_Abstract
12
+ {
13
+
14
+ }
app/code/community/CoScale/Monitor/Model/Cronjob.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Cronjob director to run daily metric data reset/generation
4
+ *
5
+ * @package CoScale_Monitor
6
+ * @author Vladimir Kerkhoff <v.kerkhoff@genmato.com>
7
+ * @version 1.0
8
+ * @created 2015-08-18
9
+ */
10
+
11
+ class CoScale_Monitor_Model_Cronjob
12
+ {
13
+ /**
14
+ * Daily cronjob to update daily values
15
+ */
16
+
17
+ public function dailyCron()
18
+ {
19
+ // Customer metric data
20
+ Mage::getSingleton('coscale_monitor/metric_customer')->dailyCron();
21
+ Mage::getSingleton('coscale_monitor/metric_product')->dailyCron();
22
+ }
23
+ }
app/code/community/CoScale/Monitor/Model/Event.php ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CoScale Event interaction model
5
+ *
6
+ * @package CoScale_Monitor
7
+ * @author Rian Orie <rian.orie@supportdesk.nu>
8
+ * @created 2015-07-03
9
+ * @version 1.0
10
+ *
11
+ * @method $this setId(int $eventId)
12
+ * @method $this setName(string $name)
13
+ * @method $this setDescription(string $description)
14
+ * @method $this setSource(string $source)
15
+ * @method $this setVersion(int $version)
16
+ * @method $this setDuration(int $duration)
17
+ * @method $this setTimestampStart(int $timestamp)
18
+ * @method $this setTimestampEnd(int $timestamp)
19
+ * @method $this setUpdatedAt(string $date)
20
+ * @method int getId()
21
+ * @method string getName()
22
+ * @method string getDescription()
23
+ * @method string getType()
24
+ * @method string getSource()
25
+ * @method int getState()
26
+ * @method int getTimestampStart()
27
+ * @method int getTimestampEnd()
28
+ * @method int getDuration()
29
+ * @method string getUpdatedAt()
30
+ */
31
+ class CoScale_Monitor_Model_Event extends Mage_Core_Model_Abstract
32
+ {
33
+ /**
34
+ * Disabled state for events
35
+ */
36
+ const STATE_DISABLED = -1;
37
+
38
+ /**
39
+ * Inactive state for events
40
+ */
41
+ const STATE_INACTIVE = 0;
42
+
43
+ /**
44
+ * Enabled/active state for events
45
+ */
46
+ const STATE_ENABLED = 1;
47
+
48
+ const GROUP_ADMIN = 'Admin actions';
49
+ const GROUP_CRON = 'Cron Jobs';
50
+
51
+ /**
52
+ * Event type for adding stores
53
+ */
54
+ const TYPE_STORE_ADD = 'STORE_ADD';
55
+
56
+ /**
57
+ * Event type for flushing the page cache
58
+ */
59
+ const TYPE_FLUSH_SYSTEM_CACHE = 'FLUSH_SYSTEM_CACHE';
60
+ const TYPE_FLUSH_ALL_CACHE = 'FLUSH_ALL_CACHE';
61
+ const TYPE_MASS_REFRESH_CACHE = 'MASS_REFRESH_CACHE';
62
+
63
+ /**
64
+ * Event for flushing the asset cache
65
+ */
66
+ const TYPE_FLUSH_ASSET_CACHE = 'FLUSH_ASSET_CACHE';
67
+
68
+ /**
69
+ * Event for flushing the image cache
70
+ */
71
+ const TYPE_FLUSH_IMAGE_CACHE = 'FLUSH_IMAGE_CACHE';
72
+
73
+ /**
74
+ * Event for the reindexing
75
+ */
76
+ const TYPE_REINDEX = 'REINDEX';
77
+
78
+ /**
79
+ * Construct the event model
80
+ */
81
+ protected function _construct()
82
+ {
83
+ $this->_init('coscale_monitor/event');
84
+ }
85
+
86
+ /**
87
+ * Make sure the version is always an integer, even when it's null
88
+ *
89
+ * @return int
90
+ */
91
+ public function getVersion()
92
+ {
93
+ if (is_null($this->getData('version'))) {
94
+ return 0;
95
+ }
96
+
97
+ return $this->getData('version');
98
+ }
99
+
100
+ /**
101
+ * Return the event data as an array, rather than the json string
102
+ *
103
+ * @return array
104
+ */
105
+ public function getEventData()
106
+ {
107
+ return json_decode($this->getData('event_data'), true);
108
+ }
109
+
110
+ /**
111
+ * Set the state for an event
112
+ *
113
+ * @param int $state Set the state to one of the predefined states in the system
114
+ *
115
+ * @return $this
116
+ * @throws Exception
117
+ */
118
+ public function setState($state)
119
+ {
120
+ if (!in_array($state, array(self::STATE_DISABLED, self::STATE_ENABLED, self::STATE_INACTIVE))) {
121
+ throw new Exception('State must be one of the predefined state levels.');
122
+ }
123
+
124
+ return $this->setData('state', $state);
125
+ }
126
+
127
+ /**
128
+ * Set the event type
129
+ *
130
+ * @param string $type Set the type of the event to one of the predefined types
131
+ *
132
+ * @return $this
133
+ *
134
+ * @throws Exception
135
+ */
136
+ public function setType($type)
137
+ {
138
+ if (!in_array($type, $this->getTypes())) {
139
+ throw new Exception('Only predefined types can be used.');
140
+ }
141
+
142
+ return $this->setData('type', $type);
143
+ }
144
+
145
+ /**
146
+ * Store the event data as a json string rather than a raw array
147
+ *
148
+ * @param array $data An array of data to expose to CoScale
149
+ *
150
+ * @return $this
151
+ */
152
+ public function setEventData(array $data)
153
+ {
154
+ return $this->setData('event_data', json_encode($data));
155
+ }
156
+
157
+ /**
158
+ * Shorthand for adding new events
159
+ *
160
+ * @param string $type The event type as predefined in this model
161
+ * @param string $name Short name for the event
162
+ * @param string $description Description of the event
163
+ * @param array $data An array of data to expose to CoScale
164
+ * @param string $source The causer of the event, logged in user, etc
165
+ * @param int $state The state of the event
166
+ *
167
+ * @return $this
168
+ */
169
+ public function addEvent($type, $name, $description, array $data, $source, $state = null)
170
+ {
171
+ $this->setType($type)
172
+ ->setName($name)
173
+ ->setDescription($description)
174
+ ->setEventData(serialize($data))
175
+ ->setDuration(0)
176
+ ->setTimestampStart(time())
177
+ ->setSource($source)
178
+ ->setState($state);
179
+
180
+ // By default we're assuming events don't do much and we're simply logging them
181
+ // if an event takes longer, the enabled state needs to be defined in the call
182
+ if (is_null($state)) {
183
+ $this->setState(self::STATE_INACTIVE)
184
+ ->setTimestampEnd(time());
185
+ }
186
+
187
+ try {
188
+ $this->save();
189
+ } catch (Exception $ex) {
190
+ Mage::log($ex->getMessage(), null, 'coscale.log', true);
191
+ }
192
+
193
+ return $this;
194
+ }
195
+
196
+ /**
197
+ * Shorthand to update an event
198
+ *
199
+ * @param string $type The predefined type to load the event by
200
+ * @param int $state The state of the event
201
+ * @param string $source Source of the event, who triggered it
202
+ * @param array $data Event data to store
203
+ *
204
+ * @throws Exception
205
+ */
206
+ public function updateEvent($type, $state, $source = null, array $data = null)
207
+ {
208
+ $this->loadLastByType($type);
209
+ $this->setTimestampEnd(time())
210
+ ->setState($state);
211
+
212
+ if (!is_null($source)) {
213
+ $this->setSource($source);
214
+ }
215
+
216
+ if (!is_null($data)) {
217
+ $this->setEventData($data);
218
+ }
219
+
220
+ try {
221
+ $this->save();
222
+ } catch (Exception $ex) {
223
+ Mage::log($ex->getMessage(), null, 'coscale.log', true);
224
+ }
225
+ }
226
+
227
+ /**
228
+ * Load an event by it's type
229
+ *
230
+ * @param string $type The predefined type to load the event by
231
+ *
232
+ * @return $this
233
+ *
234
+ * @throws Exception
235
+ */
236
+ public function loadLastByType($type)
237
+ {
238
+ if (!in_array($type, $this->getTypes())) {
239
+ throw new Exception('Type should be one of the predefined keys');
240
+ }
241
+
242
+ $this->_getResource()->loadByType($this, $type);
243
+ return $this;
244
+ }
245
+
246
+ /**
247
+ * Type groups for the reporting and grouping of types
248
+ *
249
+ * @return string
250
+ */
251
+ public function getTypeGroup()
252
+ {
253
+ switch ($this->getType()) {
254
+ case self::TYPE_STORE_ADD:
255
+ case self::TYPE_MASS_REFRESH_CACHE:
256
+ case self::TYPE_FLUSH_ASSET_CACHE:
257
+ case self::TYPE_FLUSH_IMAGE_CACHE:
258
+ case self::TYPE_FLUSH_SYSTEM_CACHE:
259
+ case self::TYPE_FLUSH_ALL_CACHE:
260
+ case self::TYPE_REINDEX:
261
+ return self::GROUP_ADMIN;
262
+ }
263
+ }
264
+
265
+ /**
266
+ * Set some defaults before saving an event to the database
267
+ *
268
+ * @return $this
269
+ */
270
+ protected function _beforeSave()
271
+ {
272
+ $date = Mage::getModel('core/date');
273
+
274
+ $this->setUpdatedAt($date->date())
275
+ ->setVersion($this->getVersion() + 1);
276
+
277
+ return $this;
278
+ }
279
+
280
+ /**
281
+ * Retrieve the available types as an array
282
+ *
283
+ * @return array
284
+ */
285
+ protected function getTypes()
286
+ {
287
+ return array(self::TYPE_REINDEX, self::TYPE_STORE_ADD,
288
+ self::TYPE_FLUSH_ASSET_CACHE, self::TYPE_FLUSH_IMAGE_CACHE,
289
+ self::TYPE_MASS_REFRESH_CACHE, self::TYPE_FLUSH_SYSTEM_CACHE,
290
+ self::TYPE_FLUSH_ALL_CACHE);
291
+ }
292
+ }
app/code/community/CoScale/Monitor/Model/Event/Cache.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Event observer for reindexing related features
5
+ *
6
+ * @package Coscale_Monitor
7
+ * @author Rian Orie <rian.orie@supportdesk.nu>
8
+ * @created 2015-07-06
9
+ * @version 1.0
10
+ */
11
+ class CoScale_Monitor_Model_Event_Cache
12
+ {
13
+ /**
14
+ * Trigger adding an event at the start of the flush system cache process
15
+ *
16
+ * @param Varien_Event_Observer $event
17
+ */
18
+ public function startFlushSystem(Varien_Event_Observer $event)
19
+ {
20
+ /** @var CoScale_Monitor_Model_Event $coscale */
21
+ $coscale = Mage::getModel('coscale_monitor/event');
22
+ $coscale->addEvent(
23
+ $coscale::TYPE_FLUSH_SYSTEM_CACHE,
24
+ 'Cache',
25
+ 'Flush System Cache!',
26
+ array(),
27
+ Mage::getSingleton('admin/session')->getUser()->getUsername(),
28
+ $coscale::STATE_ENABLED
29
+ );
30
+ }
31
+
32
+ /**
33
+ * Trigger ending an event at the end of the flush system cache process
34
+ *
35
+ * @param Varien_Event_Observer $event
36
+ */
37
+ public function endFlushSystem(Varien_Event_Observer $event)
38
+ {
39
+ /** @var CoScale_Monitor_Model_Event $coscale */
40
+ $coscale = Mage::getModel('coscale_monitor/event');
41
+ $coscale->updateEvent($coscale::TYPE_FLUSH_SYSTEM_CACHE, $coscale::STATE_INACTIVE);
42
+ }
43
+
44
+ /**
45
+ * Trigger adding an event at the start of the flush all cache process
46
+ *
47
+ * @param Varien_Event_Observer $event
48
+ */
49
+ public function startFlushAll(Varien_Event_Observer $event)
50
+ {
51
+ /** @var CoScale_Monitor_Model_Event $coscale */
52
+ $coscale = Mage::getModel('coscale_monitor/event');
53
+ $coscale->addEvent(
54
+ $coscale::TYPE_FLUSH_ALL_CACHE,
55
+ 'Cache',
56
+ 'Flush All Cache!',
57
+ array(),
58
+ Mage::getSingleton('admin/session')->getUser()->getUsername(),
59
+ $coscale::STATE_ENABLED
60
+ );
61
+ }
62
+
63
+ /**
64
+ * Trigger ending an event at the end of the flush all cache process
65
+ *
66
+ * @param Varien_Event_Observer $event
67
+ */
68
+ public function endFlushAll(Varien_Event_Observer $event)
69
+ {
70
+ /** @var CoScale_Monitor_Model_Event $coscale */
71
+ $coscale = Mage::getModel('coscale_monitor/event');
72
+ $coscale->updateEvent($coscale::TYPE_FLUSH_ALL_CACHE, $coscale::STATE_INACTIVE);
73
+ }
74
+
75
+ /**
76
+ * Trigger adding an event at the start of the flush Image cache process
77
+ *
78
+ * @param Varien_Event_Observer $event
79
+ */
80
+ public function startCleanImages(Varien_Event_Observer $event)
81
+ {
82
+ /** @var CoScale_Monitor_Model_Event $coscale */
83
+ $coscale = Mage::getModel('coscale_monitor/event');
84
+ $coscale->addEvent(
85
+ $coscale::TYPE_FLUSH_IMAGE_CACHE,
86
+ 'Cache',
87
+ 'Flush Image Cache!',
88
+ array(),
89
+ Mage::getSingleton('admin/session')->getUser()->getUsername(),
90
+ $coscale::STATE_ENABLED
91
+ );
92
+ }
93
+
94
+ /**
95
+ * Trigger ending an event at the end of the flush Image cache process
96
+ *
97
+ * @param Varien_Event_Observer $event
98
+ */
99
+ public function endCleanImages(Varien_Event_Observer $event)
100
+ {
101
+ /** @var CoScale_Monitor_Model_Event $coscale */
102
+ $coscale = Mage::getModel('coscale_monitor/event');
103
+ $coscale->updateEvent($coscale::TYPE_FLUSH_IMAGE_CACHE, $coscale::STATE_INACTIVE);
104
+ }
105
+
106
+ /**
107
+ * Trigger adding an event at the start of the flush css/js cache process
108
+ *
109
+ * @param Varien_Event_Observer $event
110
+ */
111
+ public function startCleanAssets(Varien_Event_Observer $event)
112
+ {
113
+ /** @var CoScale_Monitor_Model_Event $coscale */
114
+ $coscale = Mage::getModel('coscale_monitor/event');
115
+ $coscale->addEvent(
116
+ $coscale::TYPE_FLUSH_ASSET_CACHE,
117
+ 'Cache',
118
+ 'Flush Asset (CSS/JS) Cache!',
119
+ array(),
120
+ Mage::getSingleton('admin/session')->getUser()->getUsername(),
121
+ $coscale::STATE_ENABLED
122
+ );
123
+ }
124
+
125
+ /**
126
+ * Trigger ending an event at the end of the flush css/js cache process
127
+ *
128
+ * @param Varien_Event_Observer $event
129
+ */
130
+ public function endCleanAssets(Varien_Event_Observer $event)
131
+ {
132
+ /** @var CoScale_Monitor_Model_Event $coscale */
133
+ $coscale = Mage::getModel('coscale_monitor/event');
134
+ $coscale->updateEvent($coscale::TYPE_FLUSH_ASSET_CACHE, $coscale::STATE_INACTIVE);
135
+ }
136
+
137
+ /**
138
+ * Trigger adding an event at the start of the mass refresh cache process
139
+ *
140
+ * @param Varien_Event_Observer $event
141
+ */
142
+ public function startMassRefresh(Varien_Event_Observer $event)
143
+ {
144
+ $types = Mage::app()->getRequest()->getPost('types', array());
145
+
146
+ /** @var CoScale_Monitor_Model_Event $coscale */
147
+ $coscale = Mage::getModel('coscale_monitor/event');
148
+ $coscale->addEvent(
149
+ $coscale::TYPE_MASS_REFRESH_CACHE,
150
+ 'Cache',
151
+ 'Mass Cache Refresh!',
152
+ array('types'=>$types),
153
+ Mage::getSingleton('admin/session')->getUser()->getUsername(),
154
+ $coscale::STATE_ENABLED
155
+ );
156
+ }
157
+
158
+ /**
159
+ * Trigger ending an event at the end of the mass refresh cache process
160
+ *
161
+ * @param Varien_Event_Observer $event
162
+ */
163
+ public function endMassRefresh(Varien_Event_Observer $event)
164
+ {
165
+ /** @var CoScale_Monitor_Model_Event $coscale */
166
+ $coscale = Mage::getModel('coscale_monitor/event');
167
+ $coscale->updateEvent($coscale::TYPE_MASS_REFRESH_CACHE, $coscale::STATE_INACTIVE);
168
+ }
169
+ }
app/code/community/CoScale/Monitor/Model/Event/Reindex.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Event observer for reindexing related features
5
+ *
6
+ * @package Coscale_Monitor
7
+ * @author Rian Orie <rian.orie@supportdesk.nu>
8
+ * @created 2015-07-06
9
+ * @version 1.0
10
+ */
11
+ class CoScale_Monitor_Model_Event_Reindex
12
+ {
13
+ /**
14
+ * Trigger adding an event at the start of the reindexing process
15
+ *
16
+ * @param Varien_Event_Observer $event
17
+ */
18
+ public function startIndex(Varien_Event_Observer $event)
19
+ {
20
+ /** @var CoScale_Monitor_Model_Event $coscale */
21
+ $coscale = Mage::getModel('coscale_monitor/event');
22
+ $coscale->addEvent(
23
+ $coscale::TYPE_REINDEX,
24
+ 'Reindexing',
25
+ 'Reindexing the indexes!',
26
+ array(),
27
+ Mage::getSingleton('admin/session')->getUser()->getUsername(),
28
+ $coscale::STATE_ENABLED
29
+ );
30
+ }
31
+
32
+ /**
33
+ * Trigger ending an event at the end of the reindexing process
34
+ *
35
+ * @param Varien_Event_Observer $event
36
+ */
37
+ public function endIndex(Varien_Event_Observer $event)
38
+ {
39
+ /** @var CoScale_Monitor_Model_Event $coscale */
40
+ $coscale = Mage::getModel('coscale_monitor/event');
41
+ $coscale->updateEvent($coscale::TYPE_REINDEX, $coscale::STATE_INACTIVE);
42
+ }
43
+ }
app/code/community/CoScale/Monitor/Model/Event/Store.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CoScale Event interaction model
5
+ *
6
+ * @package CoScale_Monitor
7
+ * @author Rian Orie <rian.orie@supportdesk.nu>
8
+ * @created 2015-07-03
9
+ * @version 1.0
10
+ */
11
+ class CoScale_Monitor_Model_Event_Store
12
+ {
13
+ /**
14
+ * Track the adding of a new store
15
+ *
16
+ * @param Varien_Event_Observer $event
17
+ */
18
+ public function addNew(Varien_Event_Observer $event)
19
+ {
20
+ /** @var Mage_Core_Model_Store $store */
21
+ $store = $event->getStore();
22
+
23
+ $event = Mage::getModel('coscale_monitor/event');
24
+ $event->addEvent(
25
+ $event::TYPE_STORE_ADD,
26
+ 'Store added',
27
+ 'A new store was added',
28
+ array(
29
+ 'id' => $store->getId(),
30
+ 'name' => $store->getName(),
31
+ 'code' => $store->getCode(),
32
+ 'website' => $store->getWebsiteId()
33
+ ),
34
+ Mage::getSingleton('admin/session')->getUser()->getUsername()
35
+ );
36
+
37
+ }
38
+ }
app/code/community/CoScale/Monitor/Model/Metric.php ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CoScale metric interaction model
5
+ *
6
+ * @package CoScale_Monitor
7
+ * @author Rian Orie <rian.orie@supportdesk.nu>
8
+ * @created 2015-07-03
9
+ * @version 1.0
10
+ *
11
+ * @method $this setKey(int $metricId)
12
+ * @method $this setStoreId(int $store)
13
+ * @method $this setName(string $name)
14
+ * @method $this setDescription(string $description)
15
+ * @method $this setType(int $type)
16
+ * @method $this setValue(string $value)
17
+ * @method $this setUnit(string $unit)
18
+ * @method $this setTimestamp(int $timestamp)
19
+ * @method $this setUpdatedAt(string $date)
20
+ * @method int getKey()
21
+ * @method int getStoreId()
22
+ * @method int getType()
23
+ * @method string getName()
24
+ * @method string getDescription()
25
+ * @method mixed getValue()
26
+ * @method string getUnit()
27
+ * @method int getTimestamp()
28
+ * @method string getUpdatedAt()
29
+ */
30
+ class CoScale_Monitor_Model_Metric extends Mage_Core_Model_Abstract
31
+ {
32
+ /**
33
+ * Type for server-based metrics
34
+ */
35
+ const TYPE_SERVER = 1;
36
+
37
+ /**
38
+ * Type for application-based metrics
39
+ */
40
+ const TYPE_APPLICATION = 2;
41
+
42
+ /**
43
+ * Construct the metric model
44
+ */
45
+ protected function _construct()
46
+ {
47
+ $this->_init('coscale_monitor/metric');
48
+ }
49
+
50
+ /**
51
+ * Shorthand to add or update a metric to the system
52
+ *
53
+ * @param int $key A key as predefined in this model
54
+ * @param int $store The store id
55
+ * @param int $type A predefined type for the metric
56
+ * @param string $name The name of the metric
57
+ * @param string $description A longer description of the metric
58
+ * @param mixed $value The value to set
59
+ * @param string $unit The unit the value is saved in
60
+ *
61
+ * @throws Exception
62
+ */
63
+ public function updateMetric($key, $store, $type, $name, $description, $value, $unit)
64
+ {
65
+ $this->loadByKey($key, $store);
66
+
67
+ $this->setKey($key)
68
+ ->setStoreId($store)
69
+ ->setType($type)
70
+ ->setName($name)
71
+ ->setDescription($description)
72
+ ->setValue($value)
73
+ ->setUnit($unit);
74
+
75
+ try {
76
+ $this->save();
77
+ } catch (Exception $ex) {
78
+ Mage::log($ex->getMessage(), null, 'coscale.log', true);
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Shorthand to add or increment a numerical metric in the system
84
+ *
85
+ * @param int $key A key as predefined in this model
86
+ * @param int $store The store the metric belongs to
87
+ * @param string $type A predefined type for the metric
88
+ * @param string $name The name of the metric
89
+ * @param string $description A longer description of the metric
90
+ * @param mixed $value The value to set
91
+ * @param string $unit The unit the value is saved in
92
+ */
93
+ public function incrementMetric($key, $store, $type, $name, $description, $value, $unit)
94
+ {
95
+ $this->loadByKey($key, $store);
96
+
97
+ $this->updateMetric($key, $store, $type, $name, $description, ($this->getValue() + $value), $unit);
98
+ }
99
+
100
+ /**
101
+ * Return the textual version of the metric type
102
+ *
103
+ * @return string
104
+ */
105
+ public function getTypeText()
106
+ {
107
+ switch ($this->getType()) {
108
+ case self::TYPE_SERVER:
109
+ return 'S';
110
+ break;
111
+ case self::TYPE_APPLICATION:
112
+ return 'A';
113
+ break;
114
+
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Load a metric by it's key
120
+ *
121
+ * @param int $key The predefined key to load the metric from
122
+ * @param int $store The store to load the metric for
123
+ *
124
+ * @return $this
125
+ *
126
+ * @throws Exception
127
+ */
128
+ public function loadByKey($key, $store)
129
+ {
130
+ $this->_getResource()->loadByKey($this, $key, $store);
131
+ return $this;
132
+ }
133
+
134
+ /**
135
+ * Set some defaults before saving an event to the database
136
+ *
137
+ * @return $this
138
+ */
139
+ protected function _beforeSave()
140
+ {
141
+ $date = Mage::getModel('core/date');
142
+
143
+ $this->setTimestamp($date->timestamp())
144
+ ->setUpdatedAt($date->date());
145
+
146
+ return $this;
147
+ }
148
+ }
app/code/community/CoScale/Monitor/Model/Metric/Abstract.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Abstract class for processing metric data
4
+ *
5
+ * @package CoScale_Monitor
6
+ * @author Vladimir Kerkhoff <v.kerkhoff@genmato.com>
7
+ * @version 1.0
8
+ * @created 2015-08-18
9
+ */
10
+ class CoScale_Monitor_Model_Metric_Abstract
11
+ {
12
+ protected $_metric = false;
13
+ protected $_metricData = array();
14
+
15
+ protected $_metricType = CoScale_Monitor_Model_Metric::TYPE_APPLICATION;
16
+
17
+ const ACTION_UPDATE = 1;
18
+ const ACTION_INCREMENT=2;
19
+
20
+ public function __construct()
21
+ {
22
+ $this->_metric = Mage::getModel('coscale_monitor/metric');
23
+ $this->_contruct();
24
+ }
25
+
26
+ /**
27
+ * Public contructor
28
+ */
29
+ public function _contruct()
30
+ {
31
+
32
+ }
33
+
34
+ /**
35
+ * Shorthand to add/update or increment a metric to the system
36
+ *
37
+ * @param int $action Specify action
38
+ * @param int $key A key as predefined in this model
39
+ * @param int $store The store id
40
+ * @param int|bool $type A predefined type for the metric
41
+ * @param string|bool $name The name of the metric
42
+ * @param string|bool $descr A longer description of the metric
43
+ * @param mixed $value The value to set
44
+ * @param string|bool $unit The unit the value is saved in
45
+ *
46
+ * @throws Exception
47
+ */
48
+ protected function setMetric($action, $key, $store, $value, $unit = false, $type = false, $name = false, $descr = false)
49
+ {
50
+ if (!$type) {
51
+ $type = $this->_metricType;
52
+ }
53
+
54
+ if (!$name && isset($this->_metricData[$key]['name'])) {
55
+ $name = $this->_metricData[$key]['name'];
56
+ }
57
+
58
+ if (!$descr && isset($this->_metricData[$key]['description'])) {
59
+ $descr = $this->_metricData[$key]['description'];
60
+ }
61
+
62
+ if (!$unit && isset($this->_metricData[$key]['unit'])) {
63
+ $unit = $this->_metricData[$key]['unit'];
64
+ }
65
+
66
+ if (!$name || !$descr || !$unit) {
67
+ throw new Exception('Invalid metric data supplied');
68
+ }
69
+
70
+ if ($action == self::ACTION_UPDATE) {
71
+ $this->_metric->updateMetric($key, $store, $type, $name, $descr, $value, $unit);
72
+ } else {
73
+ $this->_metric->incrementMetric($key, $store, $type, $name, $descr, $value, $unit);
74
+ }
75
+ }
76
+
77
+ protected function getMetric($key, $store)
78
+ {
79
+ $data = $this->_metric->loadByKey($key, $store);
80
+
81
+ if (!$data->getId()) {
82
+ return 0;
83
+ }
84
+ return $data->getValue();
85
+ }
86
+
87
+ }
app/code/community/CoScale/Monitor/Model/Metric/Customer.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Observer for the metrics related to customers
5
+ *
6
+ * @package CoScale_Monitor
7
+ * @author Rian Orie <rian.orie@supportdesk.nu>
8
+ * @version 1.0
9
+ * @created 2015-07-03
10
+ */
11
+ class CoScale_Monitor_Model_Metric_Customer extends CoScale_Monitor_Model_Metric_Abstract
12
+ {
13
+ /**
14
+ * Identifier for the total number of customers in the system
15
+ */
16
+ const KEY_CUSTOMER_TOTAL = 1000;
17
+ /**
18
+ * Identifier for the total number of customers in the system
19
+ */
20
+ const KEY_CUSTOMER_TODAY = 1001;
21
+
22
+ /**
23
+ * Public contructor function
24
+ */
25
+ public function _contruct()
26
+ {
27
+ $this->_metricData[self::KEY_CUSTOMER_TOTAL] = array(
28
+ 'name' => 'Customers',
29
+ 'description' => 'The total number of customers in the system',
30
+ 'unit' => 'customers'
31
+ );
32
+ }
33
+
34
+ /**
35
+ * Observe the adding of new customers to the system
36
+ *
37
+ * @param Varien_Event_Observer $observer
38
+ */
39
+ public function addNew(Varien_Event_Observer $observer)
40
+ {
41
+ /** @var Mage_Customer_Model_Customer $customer */
42
+ $customer = $observer->getEvent()->getCustomer();
43
+
44
+ if ($customer->getOrigData('entity_id') == $customer->getId()) {
45
+ return;
46
+ }
47
+
48
+ $this->setMetric(
49
+ self::ACTION_INCREMENT,
50
+ self::KEY_CUSTOMER_TOTAL,
51
+ $customer->getStore()->getId(),
52
+ 1
53
+ );
54
+ }
55
+
56
+ /**
57
+ * Cronjob to update the total number of customers
58
+ */
59
+ public function dailyCron()
60
+ {
61
+ $this->updateTotalCount();
62
+ }
63
+
64
+ /**
65
+ * Daily update full numbers of customers
66
+ */
67
+ public function updateTotalCount()
68
+ {
69
+ $collection = Mage::getResourceModel('customer/customer_collection');
70
+ if (!is_object($collection)) {
71
+ return;
72
+ }
73
+ $collection->getSelect()
74
+ ->reset('columns')
75
+ ->columns(array('website_id' => 'e.website_id',
76
+ 'customer_count' => 'COUNT(*)'))
77
+ ->group('e.website_id');
78
+
79
+ foreach ($collection as $customer) {
80
+ $storeIds = Mage::app()->getWebsite($customer->getWebsiteId())->getStoreIds();
81
+ foreach ($storeIds as $storeId) {
82
+ $this->setMetric(
83
+ self::ACTION_UPDATE,
84
+ self::KEY_CUSTOMER_TOTAL,
85
+ $storeId,
86
+ $customer->getCustomerCount()
87
+ );
88
+ }
89
+ }
90
+ }
91
+ }
app/code/community/CoScale/Monitor/Model/Metric/File.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Metrics related to files
4
+ *
5
+ * @package CoScale_Monitor
6
+ * @author Vladimir Kerkhoff <v.kerkhoff@genmato.com>
7
+ * @version 1.0
8
+ * @created 2015-08-18
9
+ */
10
+ class CoScale_Monitor_Model_Metric_File extends CoScale_Monitor_Model_Metric_Abstract
11
+ {
12
+
13
+ /**
14
+ * Get amount of reports in var/report
15
+ * @return array
16
+ */
17
+ public function getErrorReports()
18
+ {
19
+ $dir = Mage::getBaseDir('var') . DS . 'report';
20
+
21
+ $contents = scandir($dir);
22
+
23
+ return array(
24
+ 'name' => 'Files in var/report/',
25
+ 'unit' => 'files',
26
+ 'value' => (count($contents)-2),
27
+ 'store_id' => 0,
28
+ 'type' => 'S'
29
+ );
30
+ }
31
+
32
+ /**
33
+ * Get details of logfiles in var/log
34
+ * @return array
35
+ */
36
+ public function getLogFiles()
37
+ {
38
+ $dir = Mage::getBaseDir('var') . DS . 'log';
39
+
40
+ $contents = scandir($dir);
41
+ $output = array();
42
+ foreach ($contents as $logfile) {
43
+ if ($logfile == '.' || $logfile=='..') {
44
+ continue;
45
+ }
46
+ $output[] = array(
47
+ 'name' => 'Logfile var/log/' . $logfile,
48
+ 'unit' => 'bytes',
49
+ 'value' => filesize($dir . DS . $logfile),
50
+ 'store_id' => 0,
51
+ 'type' => 'S'
52
+ );
53
+ }
54
+ return $output;
55
+ }
56
+ }
app/code/community/CoScale/Monitor/Model/Metric/Order.php ADDED
@@ -0,0 +1,469 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Observer for the metrics related to orders
5
+ *
6
+ * @package CoScale_Monitor
7
+ * @author Rian Orie <rian.orie@supportdesk.nu>
8
+ * @version 1.0
9
+ * @created 2015-07-07
10
+ */
11
+ class CoScale_Monitor_Model_Metric_Order extends CoScale_Monitor_Model_Metric_Abstract
12
+ {
13
+
14
+ /**
15
+ * Identifier for total orders
16
+ */
17
+ const KEY_ORDER_TOTAL = 2000;
18
+ const KEY_ORDER_TOTAL_TODAY = 2001;
19
+ const KEY_ORDER_TOTAL_NEW = 2002;
20
+
21
+ /**
22
+ * Identifier for order amount average and total
23
+ */
24
+ const KEY_ORDER_AMOUNT_AVERAGE = 2010;
25
+ const KEY_ORDER_SIZE_TOTAL = 2011;
26
+ const KEY_ORDER_AMOUNT_AVERAGE_NEW = 2012;
27
+ const KEY_ORDER_SIZE_TOTAL_NEW = 2013;
28
+
29
+ /**
30
+ * Identifier for order size average and total
31
+ */
32
+ const KEY_ORDER_SIZE_AVERAGE = 2020;
33
+ const KEY_ORDER_AMOUNT_TOTAL = 2021;
34
+ const KEY_ORDER_SIZE_AVERAGE_NEW = 2022;
35
+ const KEY_ORDER_AMOUNT_TOTAL_NEW = 2023;
36
+
37
+ /**
38
+ * Identifier for order state processing/completed
39
+ */
40
+ const KEY_ORDER_STATE_NEW = 2030;
41
+ const KEY_ORDER_STATE_PROCESSING = 2031;
42
+ const KEY_ORDER_STATE_COMPLETED = 2032;
43
+
44
+ /**
45
+ * Public contructor function
46
+ */
47
+ public function _contruct()
48
+ {
49
+ $this->_metricData[self::KEY_ORDER_SIZE_TOTAL_NEW] = array(
50
+ 'name' => 'New Order size total',
51
+ 'description' => 'The total size of orders since last collect for this store',
52
+ 'unit' => 'items'
53
+ );
54
+
55
+ $this->_metricData[self::KEY_ORDER_SIZE_AVERAGE_NEW] = array(
56
+ 'name' => 'Order size average',
57
+ 'description' => 'The average size of orders since last collect for this store',
58
+ 'unit' => 'items'
59
+ );
60
+
61
+ $this->_metricData[self::KEY_ORDER_AMOUNT_TOTAL_NEW] = array(
62
+ 'name' => 'New Order amount total',
63
+ 'description' => 'The total amount of orders since last collect for this store',
64
+ 'unit' => 'Amount'
65
+ );
66
+
67
+ $this->_metricData[self::KEY_ORDER_AMOUNT_AVERAGE_NEW] = array(
68
+ 'name' => 'Order amount average',
69
+ 'description' => 'The average amount of orders since last collect for this store',
70
+ 'unit' => 'Amount'
71
+ );
72
+
73
+ $this->_metricData[self::KEY_ORDER_TOTAL_NEW] = array(
74
+ 'name' => 'Total New Orders',
75
+ 'description' => 'The total number of orders since last collect for this store',
76
+ 'unit' => 'orders'
77
+ );
78
+
79
+ $this->_metricData[self::KEY_ORDER_SIZE_TOTAL] = array(
80
+ 'name' => 'Order size total',
81
+ 'description' => 'The total size of all order in the system for this store',
82
+ 'unit' => 'items'
83
+ );
84
+
85
+ $this->_metricData[self::KEY_ORDER_SIZE_AVERAGE] = array(
86
+ 'name' => 'Order size total average',
87
+ 'description' => 'The average size of an order in the system for this store',
88
+ 'unit' => 'items'
89
+ );
90
+
91
+ $this->_metricData[self::KEY_ORDER_AMOUNT_TOTAL] = array(
92
+ 'name' => 'Order amount total',
93
+ 'description' => 'The total amount of an order in the system for this store',
94
+ 'unit' => 'Amount'
95
+ );
96
+
97
+ $this->_metricData[self::KEY_ORDER_AMOUNT_AVERAGE] = array(
98
+ 'name' => 'Order amount total average',
99
+ 'description' => 'The average amount of an order in the system for this store',
100
+ 'unit' => 'Amount'
101
+ );
102
+
103
+ $this->_metricData[self::KEY_ORDER_TOTAL] = array(
104
+ 'name' => 'Orders',
105
+ 'description' => 'The total number of orders in the system for this store',
106
+ 'unit' => 'orders'
107
+ );
108
+
109
+ $this->_metricData[self::KEY_ORDER_STATE_NEW] = array(
110
+ 'name' => 'Orders new',
111
+ 'description' => 'The total number of orders in new state',
112
+ 'unit' => 'orders'
113
+ );
114
+
115
+ $this->_metricData[self::KEY_ORDER_STATE_PROCESSING] = array(
116
+ 'name' => 'Orders processing',
117
+ 'description' => 'The total number of orders in processing state',
118
+ 'unit' => 'orders'
119
+ );
120
+
121
+ $this->_metricData[self::KEY_ORDER_STATE_COMPLETED] = array(
122
+ 'name' => 'Orders completed',
123
+ 'description' => 'The total number of orders in completed state',
124
+ 'unit' => 'orders'
125
+ );
126
+ }
127
+
128
+ public function resetOnCollect($key)
129
+ {
130
+ $resetKeys = array(
131
+ self::KEY_ORDER_TOTAL_NEW,
132
+ self::KEY_ORDER_AMOUNT_AVERAGE_NEW,
133
+ self::KEY_ORDER_SIZE_TOTAL_NEW,
134
+ self::KEY_ORDER_SIZE_AVERAGE_NEW,
135
+ self::KEY_ORDER_AMOUNT_TOTAL_NEW,
136
+
137
+ );
138
+
139
+ if (in_array($key, $resetKeys)) {
140
+ return true;
141
+ }
142
+ return false;
143
+ }
144
+
145
+ /**
146
+ * Observe the adding of new orders to the system
147
+ *
148
+ * @param Varien_Event_Observer $observer
149
+ */
150
+ public function addNew(Varien_Event_Observer $observer)
151
+ {
152
+ /** @var Mage_Sales_Model_Order $order */
153
+ $order = $observer->getEvent()->getOrder();
154
+
155
+ $amountUnit = Mage::getStoreConfig('currency/options/base', $order->getStoreId());
156
+
157
+ $this->setMetric(
158
+ self::ACTION_INCREMENT,
159
+ self::KEY_ORDER_SIZE_TOTAL,
160
+ $order->getStoreId(),
161
+ $order->getTotalItemCount()
162
+ );
163
+
164
+ $this->setMetric(
165
+ self::ACTION_INCREMENT,
166
+ self::KEY_ORDER_AMOUNT_TOTAL,
167
+ $order->getStoreId(),
168
+ $order->getBaseGrandTotal(),
169
+ $amountUnit
170
+ );
171
+
172
+ $this->setMetric(
173
+ self::ACTION_INCREMENT,
174
+ self::KEY_ORDER_TOTAL,
175
+ $order->getStoreId(),
176
+ 1
177
+ );
178
+
179
+ $this->setMetric(
180
+ self::ACTION_INCREMENT,
181
+ self::KEY_ORDER_SIZE_TOTAL_NEW,
182
+ $order->getStoreId(),
183
+ $order->getTotalItemCount()
184
+ );
185
+
186
+ $this->setMetric(
187
+ self::ACTION_INCREMENT,
188
+ self::KEY_ORDER_AMOUNT_TOTAL_NEW,
189
+ $order->getStoreId(),
190
+ $order->getBaseGrandTotal(),
191
+ $amountUnit
192
+ );
193
+
194
+ $this->setMetric(
195
+ self::ACTION_INCREMENT,
196
+ self::KEY_ORDER_TOTAL_NEW,
197
+ $order->getStoreId(),
198
+ 1
199
+ );
200
+
201
+ // Update state statistics (only is changed)
202
+ if ($order->getState() != $order->getOrigData('state')) {
203
+ // Decrease order processing when previous state was processing
204
+ if ($order->getOrigData('state') == 'new') {
205
+ $this->setMetric(
206
+ self::ACTION_INCREMENT,
207
+ self::KEY_ORDER_STATE_NEW,
208
+ $order->getStoreId(),
209
+ -1
210
+ );
211
+ }
212
+ // Decrease order processing when previous state was processing
213
+ if ($order->getOrigData('state') == 'processing') {
214
+ $this->setMetric(
215
+ self::ACTION_INCREMENT,
216
+ self::KEY_ORDER_STATE_PROCESSING,
217
+ $order->getStoreId(),
218
+ -1
219
+ );
220
+ }
221
+
222
+ // Increase orders with the state new
223
+ if ($order->getState() == 'new') {
224
+ $this->setMetric(
225
+ self::ACTION_INCREMENT,
226
+ self::KEY_ORDER_STATE_NEW,
227
+ $order->getStoreId(),
228
+ 1
229
+ );
230
+ }
231
+ // Increase orders with the state processing
232
+ if ($order->getState() == 'processing') {
233
+ $this->setMetric(
234
+ self::ACTION_INCREMENT,
235
+ self::KEY_ORDER_STATE_PROCESSING,
236
+ $order->getStoreId(),
237
+ 1
238
+ );
239
+ }
240
+ // Increase orders with the state complete
241
+ if ($order->getState() == 'complete') {
242
+ $this->setMetric(
243
+ self::ACTION_INCREMENT,
244
+ self::KEY_ORDER_STATE_COMPLETED,
245
+ $order->getStoreId(),
246
+ 1
247
+ );
248
+ }
249
+ }
250
+
251
+ $this->updateAvgOrderValues($order->getStoreId());
252
+ }
253
+
254
+ /**
255
+ * Update Avarage values for order details
256
+ *
257
+ * @param $storeId
258
+ */
259
+ public function updateAvgOrderValues($storeId)
260
+ {
261
+ $amountUnit = Mage::getStoreConfig('currency/options/base', $storeId);
262
+
263
+ $orderTotal = $this->getMetric(self::KEY_ORDER_TOTAL, $storeId);
264
+ $orderItems = $this->getMetric(self::KEY_ORDER_SIZE_TOTAL, $storeId);
265
+ $orderAmount = $this->getMetric(self::KEY_ORDER_AMOUNT_TOTAL, $storeId);
266
+
267
+ $newOrderTotal = $this->getMetric(self::KEY_ORDER_TOTAL_NEW, $storeId);
268
+ $newOrderItems = $this->getMetric(self::KEY_ORDER_SIZE_TOTAL_NEW, $storeId);
269
+ $newOrderAmount = $this->getMetric(self::KEY_ORDER_AMOUNT_TOTAL_NEW, $storeId);
270
+
271
+ $this->setMetric(
272
+ self::ACTION_UPDATE,
273
+ self::KEY_ORDER_SIZE_AVERAGE,
274
+ $storeId,
275
+ ($orderItems/$orderTotal),
276
+ $amountUnit
277
+ );
278
+
279
+ $this->setMetric(
280
+ self::ACTION_UPDATE,
281
+ self::KEY_ORDER_AMOUNT_AVERAGE,
282
+ $storeId,
283
+ ($orderAmount/$orderTotal),
284
+ $amountUnit
285
+ );
286
+
287
+ if ($newOrderTotal > 0) {
288
+ $this->setMetric(
289
+ self::ACTION_UPDATE,
290
+ self::KEY_ORDER_SIZE_AVERAGE_NEW,
291
+ $storeId,
292
+ ($newOrderItems / $newOrderTotal),
293
+ $amountUnit
294
+ );
295
+
296
+ $this->setMetric(
297
+ self::ACTION_UPDATE,
298
+ self::KEY_ORDER_AMOUNT_AVERAGE_NEW,
299
+ $storeId,
300
+ ($newOrderAmount / $newOrderTotal),
301
+ $amountUnit
302
+ );
303
+ }
304
+ }
305
+
306
+
307
+ public function initOrderData()
308
+ {
309
+ $collection = Mage::getResourceModel('sales/order_collection');
310
+ if (!is_object($collection)) {
311
+ return;
312
+ }
313
+ $collection->getSelect()
314
+ ->reset('columns')
315
+ ->columns(array('amount' => 'SUM(main_table.base_grand_total)',
316
+ 'items' => 'SUM(main_table.total_item_count)',
317
+ 'store_id' => 'main_table.store_id',
318
+ 'state' => 'main_table.state',
319
+ 'count' => 'COUNT(*)'))
320
+ ->group(array('main_table.store_id','main_table.state'));
321
+
322
+ $data = array();
323
+ foreach ($collection as $order) {
324
+ if (!$order->getStoreId()) {
325
+ continue;
326
+ }
327
+ if (!isset($data[$order->getStoreId()])) {
328
+ $data[$order->getStoreId()] = array(
329
+ 'items' => 0,
330
+ 'amount' => 0,
331
+ 'count' => 0,
332
+ 'new' => 0,
333
+ 'processing' => 0,
334
+ 'complete' => 0
335
+ );
336
+ }
337
+ $data[$order->getStoreId()]['items'] += $order->getItems();
338
+ $data[$order->getStoreId()]['amount'] += $order->getAmount();
339
+ $data[$order->getStoreId()]['count'] += $order->getCount();
340
+ if ($order->getState() == 'new') {
341
+ $data[$order->getStoreId()]['new'] += $order->getCount();
342
+ }
343
+
344
+ if ($order->getState() == 'processing') {
345
+ $data[$order->getStoreId()]['processing'] += $order->getCount();
346
+ }
347
+
348
+ if ($order->getState() == 'complete') {
349
+ $data[$order->getStoreId()]['complete'] += $order->getCount();
350
+ }
351
+ }
352
+
353
+ foreach ($data as $storeId => $details) {
354
+ $this->setMetric(
355
+ self::ACTION_UPDATE,
356
+ self::KEY_ORDER_SIZE_TOTAL,
357
+ $storeId,
358
+ $details['items']
359
+ );
360
+
361
+ $this->setMetric(
362
+ self::ACTION_UPDATE,
363
+ self::KEY_ORDER_AMOUNT_TOTAL,
364
+ $storeId,
365
+ $details['amount']
366
+ );
367
+
368
+ $this->setMetric(
369
+ self::ACTION_UPDATE,
370
+ self::KEY_ORDER_TOTAL,
371
+ $storeId,
372
+ $details['count']
373
+ );
374
+
375
+ $this->setMetric(
376
+ self::ACTION_UPDATE,
377
+ self::KEY_ORDER_STATE_NEW,
378
+ $storeId,
379
+ $details['new']
380
+ );
381
+
382
+ $this->setMetric(
383
+ self::ACTION_UPDATE,
384
+ self::KEY_ORDER_STATE_PROCESSING,
385
+ $storeId,
386
+ $details['processing']
387
+ );
388
+
389
+ $this->setMetric(
390
+ self::ACTION_UPDATE,
391
+ self::KEY_ORDER_STATE_COMPLETED,
392
+ $storeId,
393
+ $details['complete']
394
+ );
395
+
396
+ $this->updateAvgOrderValues($storeId);
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Get Abandonned cart amounts
402
+ * @return array
403
+ */
404
+ public function getAbandonnedCarts()
405
+ {
406
+ /** @var $collection Mage_Reports_Model_Resource_Quote_Collection */
407
+ $collection = Mage::getResourceModel('reports/quote_collection');
408
+ if (!is_object($collection)) {
409
+ return array();
410
+ }
411
+ $collection->prepareForAbandonedReport(array());
412
+ $collection->getSelect()
413
+ ->columns(array('store_id' => 'main_table.store_id',
414
+ 'count' => 'COUNT(*)',
415
+ 'subtotal' => 'subtotal'))
416
+ ->group('main_table.store_id');
417
+ $output = array();
418
+ foreach ($collection as $order) {
419
+ $output[] = array(
420
+ 'name' => 'Abandonned carts',
421
+ 'unit' => 'orders',
422
+ 'value' => (float)$order->getCount(),
423
+ 'store_id' => (int)$order->getStoreId(),
424
+ 'type' => 'A'
425
+ );
426
+ $output[] = array(
427
+ 'name' => 'Total value of abandoned carts',
428
+ 'unit' => 'Amount',
429
+ 'value' => (float)$order->getSubtotal(),
430
+ 'store_id' => (int)$order->getStoreId(),
431
+ 'type' => 'A'
432
+ );
433
+ }
434
+ return $output;
435
+ }
436
+
437
+
438
+
439
+ public function getEmailQueueSize()
440
+ {
441
+ $edition = method_exists('Mage', 'getEdition') ? Mage::getEdition():false;
442
+
443
+ // Pre CE1.7 version => No e-mail queue available
444
+ if (!$edition) {
445
+ return array();
446
+ }
447
+
448
+ // Pre CE 1.9 version => No e-mail queue available
449
+ if ($edition == 'Community' && version_compare(Mage::getVersion(), '1.9', '<')) {
450
+ return array();
451
+ }
452
+
453
+ // Pre EE 1.14 version => No e-mail queue available
454
+ if ($edition == 'Enterprise' && version_compare(Mage::getVersion(), '1.14', '<')) {
455
+ return array();
456
+ }
457
+ $collection = Mage::getResourceModel('core/email_queue_collection');
458
+ if (!is_object($collection)) {
459
+ return array();
460
+ }
461
+ return array(array(
462
+ 'name' => 'Amount of messages in the e-mail queue',
463
+ 'unit' => 'messages',
464
+ 'value' => $collection->getSize(),
465
+ 'store_id' => 0,
466
+ 'type' => 'A'
467
+ ));
468
+ }
469
+ }
app/code/community/CoScale/Monitor/Model/Metric/Product.php ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Observer for the metrics related to products/categories
5
+ *
6
+ * @package CoScale_Monitor
7
+ * @author Vladimir Kerkhoff <v.kerkhoff@genmato.com>
8
+ * @version 1.0
9
+ * @created 2015-08-18
10
+ */
11
+ class CoScale_Monitor_Model_Metric_Product extends CoScale_Monitor_Model_Metric_Abstract
12
+ {
13
+ /**
14
+ * Identifier for the total number of products in the system
15
+ */
16
+ const KEY_PRODUCT_TOTAL = 3000;
17
+ const KEY_PRODUCT_TODAY = 3001;
18
+ /**
19
+ * Identifier for the total number of categories in the system
20
+ */
21
+ const KEY_CATEGORIES_TOTAL = 3010;
22
+ const KEY_CATEGORIES_TODAY = 3011;
23
+
24
+ /**
25
+ * Public contructor function
26
+ */
27
+ public function _contruct()
28
+ {
29
+ $this->_metricData[self::KEY_PRODUCT_TOTAL] = array(
30
+ 'name' => 'Products',
31
+ 'description' => 'The total number of products in the system',
32
+ 'unit' => 'products'
33
+ );
34
+
35
+ $this->_metricData[self::KEY_PRODUCT_TODAY] = array(
36
+ 'name' => 'New products today',
37
+ 'description' => 'The total number of products created today',
38
+ 'unit' => 'products'
39
+ );
40
+
41
+ $this->_metricData[self::KEY_CATEGORIES_TOTAL] = array(
42
+ 'name' => 'Categories',
43
+ 'description' => 'The total number of categories in the system',
44
+ 'unit' => 'categories'
45
+ );
46
+
47
+ $this->_metricData[self::KEY_CATEGORIES_TODAY] = array(
48
+ 'name' => 'New categories today',
49
+ 'description' => 'The total number of categories created today',
50
+ 'unit' => 'categories'
51
+ );
52
+ }
53
+
54
+ /**
55
+ * Observe the adding of new product to the system
56
+ *
57
+ * @param Varien_Event_Observer $observer
58
+ */
59
+ public function addNewProduct(Varien_Event_Observer $observer)
60
+ {
61
+ /** @var Mage_Catalog_Model_Product $product */
62
+ $product = $observer->getEvent()->getProduct();
63
+
64
+ if ($product->getOrigData('entity_id') == $product->getId()) {
65
+ return;
66
+ }
67
+
68
+ $this->setMetric(
69
+ self::ACTION_INCREMENT,
70
+ self::KEY_PRODUCT_TOTAL,
71
+ 0,
72
+ 1
73
+ );
74
+
75
+ $this->setMetric(
76
+ self::ACTION_INCREMENT,
77
+ self::KEY_PRODUCT_TODAY,
78
+ 0,
79
+ 1
80
+ );
81
+ }
82
+
83
+ /**
84
+ * Observe the remove of product
85
+ *
86
+ * @param Varien_Event_Observer $observer
87
+ */
88
+ public function removeProduct(Varien_Event_Observer $observer)
89
+ {
90
+ $this->setMetric(
91
+ self::ACTION_INCREMENT,
92
+ self::KEY_PRODUCT_TOTAL,
93
+ 0,
94
+ -1
95
+ );
96
+ }
97
+
98
+ /**
99
+ * Observe the adding of new category to the system
100
+ *
101
+ * @param Varien_Event_Observer $observer
102
+ */
103
+ public function addNewCategory(Varien_Event_Observer $observer)
104
+ {
105
+ /** @var Mage_Catalog_Model_Category $category */
106
+ $category = $observer->getEvent()->getCategory();
107
+
108
+ if ($category->getOrigData('entity_id') == $category->getId()) {
109
+ return;
110
+ }
111
+
112
+ $this->setMetric(
113
+ self::ACTION_INCREMENT,
114
+ self::KEY_CATEGORIES_TOTAL,
115
+ 0,
116
+ 1
117
+ );
118
+
119
+ $this->setMetric(
120
+ self::ACTION_INCREMENT,
121
+ self::KEY_CATEGORIES_TODAY,
122
+ 0,
123
+ 1
124
+ );
125
+ }
126
+
127
+ /**
128
+ * Observe the remove of category
129
+ *
130
+ * @param Varien_Event_Observer $observer
131
+ */
132
+ public function removeCategory(Varien_Event_Observer $observer)
133
+ {
134
+ $this->setMetric(
135
+ self::ACTION_INCREMENT,
136
+ self::KEY_CATEGORIES_TOTAL,
137
+ 0,
138
+ -1
139
+ );
140
+ }
141
+
142
+ /**
143
+ * Cronjob to update the total number of customers
144
+ */
145
+ public function dailyCron()
146
+ {
147
+ $this->resetDayCounter();
148
+ $this->updateTotalCount();
149
+ }
150
+
151
+ /**
152
+ * Reset daily new created products counter
153
+ */
154
+ protected function resetDayCounter()
155
+ {
156
+ $this->setMetric(
157
+ self::ACTION_UPDATE,
158
+ self::KEY_PRODUCT_TODAY,
159
+ 0,
160
+ 0
161
+ );
162
+
163
+ $this->setMetric(
164
+ self::ACTION_UPDATE,
165
+ self::KEY_CATEGORIES_TODAY,
166
+ 0,
167
+ 0
168
+ );
169
+ }
170
+
171
+ /**
172
+ * Daily update full numbers of products
173
+ */
174
+ public function updateTotalCount()
175
+ {
176
+ $collection = Mage::getResourceModel('catalog/product_collection');
177
+ if(!is_object($collection))
178
+ {
179
+ return;
180
+ }
181
+ $this->setMetric(
182
+ self::ACTION_UPDATE,
183
+ self::KEY_PRODUCT_TOTAL,
184
+ 0,
185
+ $collection->getSize()
186
+ );
187
+
188
+ $collection = Mage::getResourceModel('catalog/category_collection');
189
+ if(!is_object($collection))
190
+ {
191
+ return;
192
+ }
193
+ $this->setMetric(
194
+ self::ACTION_UPDATE,
195
+ self::KEY_CATEGORIES_TOTAL,
196
+ 0,
197
+ $collection->getSize()
198
+ );
199
+ }
200
+ }
app/code/community/CoScale/Monitor/Model/Metric/Rewrite.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Metrics related to ReWrites
4
+ *
5
+ * @package CoScale_Monitor
6
+ * @author Vladimir Kerkhoff <v.kerkhoff@genmato.com>
7
+ * @version 1.0
8
+ * @created 2015-08-18
9
+ */
10
+ class CoScale_Monitor_Model_Metric_Rewrite extends CoScale_Monitor_Model_Metric_Abstract
11
+ {
12
+
13
+ /**
14
+ * Get amount of rewrites
15
+ * @return array
16
+ */
17
+ public function getUrlRewrites()
18
+ {
19
+ $collection = Mage::getResourceModel('core/url_rewrite_collection');
20
+ if(!is_object($collection))
21
+ {
22
+ return array();
23
+ }
24
+ $collection->getSelect()
25
+ ->reset('columns')
26
+ ->columns(array('store_id' => 'main_table.store_id',
27
+ 'count' => 'COUNT(*)'))
28
+ ->group('main_table.store_id');
29
+
30
+ foreach ($collection as $rewrite) {
31
+ $output[] = array(
32
+ 'name' => 'URL Rewrites',
33
+ 'unit' => 'rewrites',
34
+ 'value' => (float)$rewrite->getCount(),
35
+ 'store_id' => (int)$rewrite->getStoreId(),
36
+ 'type' => 'A'
37
+ );
38
+ }
39
+ return $output;
40
+ }
41
+ }
app/code/community/CoScale/Monitor/Model/Resource/Event.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CoScale event resource model
5
+ *
6
+ * @package CoScale_Monitor
7
+ * @author Rian Orie <rian.orie@supportdesk.nu>
8
+ * @created 2015-07-03
9
+ * @version 1.0
10
+ */
11
+ class CoScale_Monitor_Model_Resource_Event extends Mage_Core_Model_Resource_Db_Abstract
12
+ {
13
+ /**
14
+ * Construct the resource model
15
+ */
16
+ protected function _construct()
17
+ {
18
+ $this->_init('coscale_monitor/event', 'id');
19
+ }
20
+
21
+ /**
22
+ * Load event by type
23
+ *
24
+ * @throws Exception
25
+ *
26
+ * @param CoScale_Monitor_Model_Event $event
27
+ * @param string $type The type identifier to load the event by
28
+ * @return $this
29
+ */
30
+ public function loadByType(CoScale_Monitor_Model_Event $event, $type)
31
+ {
32
+ $adapter = $this->_getReadAdapter();
33
+ $bind = array('type' => $type);
34
+ $select = $adapter->select()
35
+ ->from($this->getTable('coscale_monitor/event'), array('id'))
36
+ ->where('`type` = :type')
37
+ ->order('id DESC');
38
+
39
+
40
+ $eventId = $adapter->fetchOne($select, $bind);
41
+ if ($eventId) {
42
+ $this->load($event, $eventId);
43
+ } else {
44
+ $event->setData(array());
45
+ }
46
+
47
+ return $this;
48
+ }
49
+ }
app/code/community/CoScale/Monitor/Model/Resource/Event/Collection.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CoScale event collection
5
+ *
6
+ * @package CoScale_Monitor
7
+ * @author Rian Orie <rian.orie@supportdesk.nu>
8
+ * @created 2015-07-03
9
+ * @version 1.0
10
+ */
11
+ class CoScale_Monitor_Model_Resource_Event_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
12
+ {
13
+ /**
14
+ * Construct the event collection
15
+ */
16
+ protected function _construct()
17
+ {
18
+ $this->_init('coscale_monitor/event');
19
+ }
20
+
21
+ }
app/code/community/CoScale/Monitor/Model/Resource/Metric.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CoScale metric data resource model
5
+ *
6
+ * @package CoScale_Monitor
7
+ * @author Rian Orie <rian.orie@supportdesk_nu>
8
+ * @created 2015-07-03
9
+ * @version 1.0
10
+ */
11
+ class CoScale_Monitor_Model_Resource_Metric extends Mage_Core_Model_Resource_Db_Abstract
12
+ {
13
+ /**
14
+ * Construct the resource model
15
+ */
16
+ protected function _construct()
17
+ {
18
+ $this->_init('coscale_monitor/metric', 'id');
19
+ }
20
+
21
+ /**
22
+ * Load metric by key
23
+ *
24
+ * @param CoScale_Monitor_Model_Metric $metric
25
+ * @param int $key The identifier to load the metric by
26
+ * @param int $store The store to load the metric belongs to
27
+ *
28
+ * @return $this
29
+ *
30
+ * @throws Exception
31
+ */
32
+ public function loadByKey(CoScale_Monitor_Model_Metric $metric, $key, $store)
33
+ {
34
+ $adapter = $this->_getReadAdapter();
35
+ $bind = array('key' => $key, 'store' => $store);
36
+ $select = $adapter->select()
37
+ ->from($this->getTable('coscale_monitor/metric'), array('id'))
38
+ ->where('`key` = :key AND `store_id` = :store');
39
+
40
+
41
+ $metricId = $adapter->fetchOne($select, $bind);
42
+ if ($metricId) {
43
+ $this->load($metric, $metricId);
44
+ } else {
45
+ $metric->setData(array());
46
+ }
47
+
48
+ return $this;
49
+ }
50
+ }
app/code/community/CoScale/Monitor/Model/Resource/Metric/Collection.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CoScale metric data collection
5
+ *
6
+ * @package CoScale_Monitor
7
+ * @author Rian Orie <rian.orie@supportdesk.nu>
8
+ * @created 2015-07-03
9
+ * @version 1.0
10
+ */
11
+ class CoScale_Monitor_Model_Resource_Metric_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
12
+ {
13
+ /**
14
+ * Construct the data collection
15
+ */
16
+ protected function _construct()
17
+ {
18
+ $this->_init('coscale_monitor/metric');
19
+ }
20
+ }
app/code/community/CoScale/Monitor/etc/config.xml ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <CoScale_Monitor>
5
+ <version>0.11.1</version>
6
+ </CoScale_Monitor>
7
+ </modules>
8
+ <global>
9
+ <models>
10
+ <coscale_monitor>
11
+ <class>CoScale_Monitor_Model</class>
12
+ <resourceModel>coscale_monitor_resource</resourceModel>
13
+ </coscale_monitor>
14
+ <coscale_monitor_resource>
15
+ <class>CoScale_Monitor_Model_Resource</class>
16
+ <entities>
17
+ <metric>
18
+ <table>coscale_metric</table>
19
+ </metric>
20
+ <event>
21
+ <table>coscale_event</table>
22
+ </event>
23
+ </entities>
24
+ </coscale_monitor_resource>
25
+ </models>
26
+ <blocks>
27
+ <coscale_monitor>
28
+ <class>CoScale_Monitor_Block</class>
29
+ </coscale_monitor>
30
+ </blocks>
31
+ <helpers>
32
+ <coscale_monitor>
33
+ <class>CoScale_Monitor_Helper</class>
34
+ </coscale_monitor>
35
+ </helpers>
36
+ <resources>
37
+ <coscale_monitor_setup>
38
+ <setup>
39
+ <module>CoScale_Monitor</module>
40
+ </setup>
41
+ </coscale_monitor_setup>
42
+ </resources>
43
+ <events>
44
+ <store_save_after>
45
+ <observers>
46
+ <coscale_monitor_event_store_add>
47
+ <class>coscale_monitor/event_store</class>
48
+ <method>addNew</method>
49
+ </coscale_monitor_event_store_add>
50
+ </observers>
51
+ </store_save_after>
52
+ <customer_save_after>
53
+ <observers>
54
+ <coscale_monitor_metric_customer_add>
55
+ <class>coscale_monitor/metric_customer</class>
56
+ <method>addNew</method>
57
+ </coscale_monitor_metric_customer_add>
58
+ </observers>
59
+ </customer_save_after>
60
+ <catalog_category_save_after>
61
+ <observers>
62
+ <coscale_monitor_metric_category_add>
63
+ <class>coscale_monitor/metric_product</class>
64
+ <method>addNewCategory</method>
65
+ </coscale_monitor_metric_category_add>
66
+ </observers>
67
+ </catalog_category_save_after>
68
+ <catalog_category_delete_commit_after>
69
+ <observers>
70
+ <coscale_monitor_metric_category_remove>
71
+ <class>coscale_monitor/metric_product</class>
72
+ <method>removeCategory</method>
73
+ </coscale_monitor_metric_category_remove>
74
+ </observers>
75
+ </catalog_category_delete_commit_after>
76
+ <catalog_product_save_after>
77
+ <observers>
78
+ <coscale_monitor_metric_product_add>
79
+ <class>coscale_monitor/metric_product</class>
80
+ <method>addNewProduct</method>
81
+ </coscale_monitor_metric_product_add>
82
+ </observers>
83
+ </catalog_product_save_after>
84
+ <catalog_product_delete_commit_after>
85
+ <observers>
86
+ <coscale_monitor_metric_product_remove>
87
+ <class>coscale_monitor/metric_product</class>
88
+ <method>removeProduct</method>
89
+ </coscale_monitor_metric_product_remove>
90
+ </observers>
91
+ </catalog_product_delete_commit_after>
92
+ <sales_order_place_after>
93
+ <observers>
94
+ <coscale_monitor_metric_order_add>
95
+ <class>coscale_monitor/metric_order</class>
96
+ <method>addNew</method>
97
+ </coscale_monitor_metric_order_add>
98
+ </observers>
99
+ </sales_order_place_after>
100
+
101
+ <controller_action_predispatch_adminhtml_process_massReindex>
102
+ <observers>
103
+ <coscale_monitor_event_reindex_start>
104
+ <class>coscale_monitor/event_reindex</class>
105
+ <method>startIndex</method>
106
+ </coscale_monitor_event_reindex_start>
107
+ </observers>
108
+ </controller_action_predispatch_adminhtml_process_massReindex>
109
+ <controller_action_postdispatch_adminhtml_process_massReindex>
110
+ <observers>
111
+ <coscale_monitor_event_reindex_start>
112
+ <class>coscale_monitor/event_reindex</class>
113
+ <method>endIndex</method>
114
+ </coscale_monitor_event_reindex_start>
115
+ </observers>
116
+ </controller_action_postdispatch_adminhtml_process_massReindex>
117
+
118
+ <controller_action_predispatch_adminhtml_cache_flushSystem>
119
+ <observers>
120
+ <coscale_monitor_event_reindex_start>
121
+ <class>coscale_monitor/event_cache</class>
122
+ <method>startFlushSystem</method>
123
+ </coscale_monitor_event_reindex_start>
124
+ </observers>
125
+ </controller_action_predispatch_adminhtml_cache_flushSystem>
126
+ <controller_action_postdispatch_adminhtml_cache_flushSystem>
127
+ <observers>
128
+ <coscale_monitor_event_reindex_start>
129
+ <class>coscale_monitor/event_cache</class>
130
+ <method>endFlushSystem</method>
131
+ </coscale_monitor_event_reindex_start>
132
+ </observers>
133
+ </controller_action_postdispatch_adminhtml_cache_flushSystem>
134
+
135
+ <controller_action_predispatch_adminhtml_cache_flushAll>
136
+ <observers>
137
+ <coscale_monitor_event_reindex_start>
138
+ <class>coscale_monitor/event_cache</class>
139
+ <method>startFlushAll</method>
140
+ </coscale_monitor_event_reindex_start>
141
+ </observers>
142
+ </controller_action_predispatch_adminhtml_cache_flushAll>
143
+ <controller_action_postdispatch_adminhtml_cache_flushAll>
144
+ <observers>
145
+ <coscale_monitor_event_reindex_start>
146
+ <class>coscale_monitor/event_cache</class>
147
+ <method>endFlushAll</method>
148
+ </coscale_monitor_event_reindex_start>
149
+ </observers>
150
+ </controller_action_postdispatch_adminhtml_cache_flushAll>
151
+
152
+ <controller_action_predispatch_adminhtml_cache_cleanImages>
153
+ <observers>
154
+ <coscale_monitor_event_reindex_start>
155
+ <class>coscale_monitor/event_cache</class>
156
+ <method>startCleanImages</method>
157
+ </coscale_monitor_event_reindex_start>
158
+ </observers>
159
+ </controller_action_predispatch_adminhtml_cache_cleanImages>
160
+ <controller_action_postdispatch_adminhtml_cache_cleanImages>
161
+ <observers>
162
+ <coscale_monitor_event_reindex_start>
163
+ <class>coscale_monitor/event_cache</class>
164
+ <method>endCleanImages</method>
165
+ </coscale_monitor_event_reindex_start>
166
+ </observers>
167
+ </controller_action_postdispatch_adminhtml_cache_cleanImages>
168
+
169
+ <controller_action_predispatch_adminhtml_cache_cleanMedia>
170
+ <observers>
171
+ <coscale_monitor_event_reindex_start>
172
+ <class>coscale_monitor/event_cache</class>
173
+ <method>startCleanAssets</method>
174
+ </coscale_monitor_event_reindex_start>
175
+ </observers>
176
+ </controller_action_predispatch_adminhtml_cache_cleanMedia>
177
+ <controller_action_postdispatch_adminhtml_cache_cleanMedia>
178
+ <observers>
179
+ <coscale_monitor_event_reindex_start>
180
+ <class>coscale_monitor/event_cache</class>
181
+ <method>endCleanAssets</method>
182
+ </coscale_monitor_event_reindex_start>
183
+ </observers>
184
+ </controller_action_postdispatch_adminhtml_cache_cleanMedia>
185
+
186
+ <controller_action_predispatch_adminhtml_cache_massRefresh>
187
+ <observers>
188
+ <coscale_monitor_event_reindex_start>
189
+ <class>coscale_monitor/event_cache</class>
190
+ <method>startMassRefresh</method>
191
+ </coscale_monitor_event_reindex_start>
192
+ </observers>
193
+ </controller_action_predispatch_adminhtml_cache_massRefresh>
194
+ <controller_action_postdispatch_adminhtml_cache_massRefresh>
195
+ <observers>
196
+ <coscale_monitor_event_reindex_start>
197
+ <class>coscale_monitor/event_cache</class>
198
+ <method>endMassRefresh</method>
199
+ </coscale_monitor_event_reindex_start>
200
+ </observers>
201
+ </controller_action_postdispatch_adminhtml_cache_massRefresh>
202
+ </events>
203
+ </global>
204
+ <frontend>
205
+ <layout>
206
+ <updates>
207
+ <coscale_monitor>
208
+ <file>coscale_monitor.xml</file>
209
+ </coscale_monitor>
210
+ </updates>
211
+ </layout>
212
+ </frontend>
213
+ <default>
214
+ <coscale>
215
+ <general>
216
+ <maxruntime>1000</maxruntime>
217
+ </general>
218
+ </coscale>
219
+ </default>
220
+
221
+ <crontab>
222
+ <jobs>
223
+ <coscale_daily_cron>
224
+ <schedule>
225
+ <cron_expr>0 0 * * *</cron_expr>
226
+ </schedule>
227
+ <run>
228
+ <model>coscale_monitor/cronjobs::dailyCron</model>
229
+ </run>
230
+ </coscale_daily_cron>
231
+ </jobs>
232
+ </crontab>
233
+ </config>
app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/install-0.1.0.php ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Set up an key value based database structure
4
+ *
5
+ * @package CoScale_Monitor
6
+ * @author Rian Orie <rian.orie@supportdesk.nu>
7
+ * @created 2015-07-03
8
+ * @version 1.0
9
+ */
10
+ /* @var $installer Mage_Core_Model_Resource_Setup */
11
+ $installer = $this;
12
+
13
+ $installer->startSetup();
14
+
15
+ $event = $installer->getConnection()
16
+ ->newTable($installer->getTable('coscale_monitor/event'))
17
+ ->addColumn('id', Varien_Db_Ddl_Table::TYPE_INTEGER,
18
+ 10,
19
+ array(
20
+ 'nullable' => false,
21
+ 'primary' => true,
22
+ 'identity' => true
23
+ ),
24
+ 'Identifier')
25
+ ->addColumn('name', Varien_Db_Ddl_Table::TYPE_VARCHAR,
26
+ 255,
27
+ array(
28
+ 'nullable' => false,
29
+ 'primary' => false,
30
+ ),
31
+ 'Event name')
32
+ ->addColumn('description', Varien_Db_Ddl_Table::TYPE_VARCHAR,
33
+ 255,
34
+ array(
35
+ 'nullable' => false,
36
+ 'primary' => false,
37
+ ),
38
+ 'Event description')
39
+ ->addColumn('event_data', Varien_Db_Ddl_Table::TYPE_VARCHAR,
40
+ 255,
41
+ array(
42
+ 'nullable' => true,
43
+ 'primary' => false,
44
+ ),
45
+ 'Event data (json)')
46
+ ->addColumn('type', Varien_Db_Ddl_Table::TYPE_VARCHAR,
47
+ 50,
48
+ array(
49
+ 'nullable' => false,
50
+ 'primary' => false,
51
+ ),
52
+ 'Event type')
53
+ ->addColumn('source', Varien_Db_Ddl_Table::TYPE_VARCHAR,
54
+ 50,
55
+ array(
56
+ 'nullable' => false,
57
+ 'primary' => false,
58
+ ),
59
+ 'Event source')
60
+ ->addColumn('state', Varien_Db_Ddl_Table::TYPE_INTEGER,
61
+ 1,
62
+ array(
63
+ 'nullable' => false,
64
+ 'primary' => false,
65
+ ),
66
+ 'Event state (-1 = disabled, 0 = inactive, 1 = on)')
67
+ ->addColumn('version', Varien_Db_Ddl_Table::TYPE_VARCHAR,
68
+ 10,
69
+ array(
70
+ 'nullable' => false,
71
+ 'primary' => false,
72
+ ),
73
+ 'Event version (incremented on every update)')
74
+ ->addColumn('timestamp', Varien_Db_Ddl_Table::TYPE_INTEGER,
75
+ 15,
76
+ array(),
77
+ 'Update timestamp')
78
+ ->addColumn('updated_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
79
+ null,
80
+ array(),
81
+ 'Update Timestamp readable')
82
+ ->setComment('CoScale event data');
83
+
84
+ $event->setOption('type', 'MEMORY');
85
+
86
+ $metric = $installer->getConnection()
87
+ ->newTable($installer->getTable('coscale_monitor/metric'))
88
+ ->addColumn('id', Varien_Db_Ddl_Table::TYPE_INTEGER,
89
+ 5,
90
+ array(
91
+ 'nullable' => false,
92
+ 'primary' => true,
93
+ 'identity' => true
94
+ ),
95
+ 'Identifier')
96
+ ->addColumn('key', Varien_Db_Ddl_Table::TYPE_INTEGER,
97
+ 5,
98
+ array(
99
+ 'nullable' => false,
100
+ 'primary' => false,
101
+ ),
102
+ 'Fixed identifier for the metric')
103
+ ->addColumn('datatype', Varien_Db_Ddl_Table::TYPE_VARCHAR,
104
+ 32,
105
+ array(
106
+ 'nullable' => false,
107
+ 'primary' => false,
108
+ ),
109
+ 'Metric datatype')
110
+ ->addColumn('name', Varien_Db_Ddl_Table::TYPE_VARCHAR,
111
+ 255,
112
+ array(
113
+ 'nullable' => false,
114
+ 'primary' => false,
115
+ ),
116
+ 'Metric name')
117
+ ->addColumn('description', Varien_Db_Ddl_Table::TYPE_VARCHAR,
118
+ 255,
119
+ array(
120
+ 'nullable' => false,
121
+ 'primary' => false,
122
+ ),
123
+ 'Metric description')
124
+ ->addColumn('value', Varien_Db_Ddl_Table::TYPE_VARCHAR,
125
+ 255,
126
+ array(
127
+ 'nullable' => true,
128
+ 'primary' => false,
129
+ ),
130
+ 'Metric value (mixed content)')
131
+ ->addColumn('unit', Varien_Db_Ddl_Table::TYPE_VARCHAR,
132
+ 10,
133
+ array(
134
+ 'nullable' => false,
135
+ 'primary' => false,
136
+ ),
137
+ 'Metric unit')
138
+ ->addColumn('groups', Varien_Db_Ddl_Table::TYPE_VARCHAR,
139
+ 255,
140
+ array(
141
+ 'nullable' => true,
142
+ 'primary' => false,
143
+ ),
144
+ 'Metric groups')
145
+ ->addColumn('tags', Varien_Db_Ddl_Table::TYPE_VARCHAR,
146
+ 255,
147
+ array(
148
+ 'nullable' => true,
149
+ 'primary' => false,
150
+ ),
151
+ 'Metric tags')
152
+ ->addColumn('calctype', Varien_Db_Ddl_Table::TYPE_INTEGER,
153
+ 2,
154
+ array(
155
+ 'nullable' => false,
156
+ 'primary' => false,
157
+ ),
158
+ 'Metric calculation type')
159
+ ->addColumn('timestamp', Varien_Db_Ddl_Table::TYPE_INTEGER,
160
+ 15,
161
+ array(),
162
+ 'Update timestamp')
163
+ ->addColumn('updated_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
164
+ null,
165
+ array(),
166
+ 'Update Timestamp')
167
+ ->addIndex('COSCALE_METRIC_UNIQUE_IDX', 'key', array('type' => 'UNIQUE'))
168
+ ->setComment('CoScale metric data');
169
+
170
+ $metric->setOption('type', 'MEMORY');
171
+
172
+
173
+ $installer->getConnection()->createTable($event);
174
+ $installer->getConnection()->createTable($metric);
175
+ $installer->endSetup();
app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/upgrade-0.1.0-0.2.0.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Set up an key value based database structure
4
+ *
5
+ * @package CoScale_Monitor
6
+ * @author Rian Orie <rian.orie@supportdesk.nu>
7
+ * @created 2015-07-03
8
+ * @version 1.0
9
+ */
10
+ /* @var $installer Mage_Core_Model_Resource_Setup */
11
+ $installer = $this;
12
+
13
+ $installer->startSetup();
14
+
15
+ $event = $installer->getConnection();
16
+ $event->addColumn($installer->getTable('coscale_monitor/event'), 'duration', 'INT UNSIGNED NULL AFTER `timestamp`');
17
+
18
+ $installer->endSetup();
app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/upgrade-0.2.0-0.3.0.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Set up an key value based database structure
4
+ *
5
+ * @package CoScale_Monitor
6
+ * @author Rian Orie <rian.orie@supportdesk.nu>
7
+ * @created 2015-07-03
8
+ * @version 1.0
9
+ */
10
+ /* @var $installer Mage_Core_Model_Resource_Setup */
11
+ $installer = $this;
12
+
13
+ $installer->startSetup();
14
+
15
+ $event = $installer->getConnection();
16
+ $event->addColumn($installer->getTable('coscale_monitor/event'), 'timestamp_end', 'INT(11) UNSIGNED NULL AFTER `timestamp`');
17
+ $event->dropColumn($installer->getTable('coscale_monitor/event'), 'duration');
18
+ $event->changeColumn($installer->getTable('coscale_monitor/event'), 'timestamp', 'timestamp_start', 'INT(11) UNSIGNED NULL');
19
+
20
+ $installer->endSetup();
app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/upgrade-0.3.0-0.4.0.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Set up an key value based database structure
4
+ *
5
+ * @package CoScale_Monitor
6
+ * @author Rian Orie <rian.orie@supportdesk.nu>
7
+ * @created 2015-07-03
8
+ * @version 1.0
9
+ */
10
+ /* @var $installer Mage_Core_Model_Resource_Setup */
11
+ $installer = $this;
12
+
13
+ $installer->startSetup();
14
+
15
+ $metric = $installer->getConnection();
16
+ $metric->changeColumn($installer->getTable('coscale_monitor/metric'), 'datatype', 'type', 'VARCHAR(1) NULL');
17
+ $metric->dropColumn($installer->getTable('coscale_monitor/metric'), 'groups');
18
+ $metric->dropColumn($installer->getTable('coscale_monitor/metric'), 'tags');
19
+ $metric->dropColumn($installer->getTable('coscale_monitor/metric'), 'calctype');
20
+ $metric->addColumn($installer->getTable('coscale_monitor/metric'), 'store_id', 'INT(5) UNSIGNED NOT NULL');
21
+
22
+ $metric->dropIndex($installer->getTable('coscale_monitor/metric'), 'COSCALE_METRIC_UNIQUE_IDX');
23
+ $metric->addIndex($installer->getTable('coscale_monitor/metric'), 'COSCALE_METRIC_UNIQUE_IDX', array('key', 'store_id'), $metric::INDEX_TYPE_UNIQUE);
24
+
25
+ $installer->endSetup();
app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/upgrade-0.4.0-0.5.0.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Change storige engine for metric table
4
+ *
5
+ * @package CoScale_Monitor
6
+ * @author V. Kerkhoff <v.kerkhoff@genmato.com>
7
+ * @created 2015-08-18
8
+ * @version 0.5
9
+ */
10
+ /* @var $installer Mage_Core_Model_Resource_Setup */
11
+ $installer = $this;
12
+
13
+ $installer->startSetup();
14
+
15
+ $metric = $installer->getConnection();
16
+ $metric->changeTableEngine($installer->getTable('coscale_monitor/metric'), 'InnoDB');
17
+
18
+
19
+ /**
20
+ * Initialize order data for further delta processing
21
+ */
22
+ Mage::getSingleton('coscale_monitor/metric_order')->initOrderData();
23
+
24
+ $installer->endSetup();
app/design/frontend/base/default/layout/coscale_monitor.xml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <layout version="0.1.0">
2
+
3
+ <!--
4
+ Default layout, loads most of the pages
5
+ -->
6
+
7
+ <default>
8
+ <reference name="head" before="-">
9
+ <block type="core/template" name="coscale_monitor" as="coscale_monitor" template="coscale_monitor/rum.phtml" />
10
+ </reference>
11
+ </default>
12
+ </layout>
app/design/frontend/base/default/template/coscale_monitor/rum.phtml ADDED
@@ -0,0 +1 @@
 
1
+ <!-- CoScale RUM script will be added here automatically when RUM will be enabled for Magento plugin in CoScale interface -->
app/etc/modules/CoScale_Monitor.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <CoScale_Monitor>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ </CoScale_Monitor>
8
+ </modules>
9
+ </config>
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>CoScale</name>
4
+ <version>0.11.1</version>
5
+ <stability>stable</stability>
6
+ <license>MITL</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>This module enables you to send important business and IT metrics from Magento to CoScale.</summary>
10
+ <description>The CoScale module exposes Magento events and metrics to the CoScale Agent. The metrics contain business metrics, such as the number of products, orders, abondoned carts, etc and technical metrics such as Magento caching metrics. The events contain magento admin actions such as page cache flushes, reindexing, etc.</description>
11
+ <notes>The CoScale module is still under development. All feedback is welcome. </notes>
12
+ <authors><author><name>CoScale Developer</name><user>cs-dev</user><email>info@coscale.com</email></author></authors>
13
+ <date>2015-08-13</date>
14
+ <time>09:29:57</time>
15
+ <contents><target name="mage"><dir name="."><dir name="app"><dir name="code"><dir name="community"><dir name="CoScale"><dir name="Monitor"><dir name="etc"><file name="config.xml" hash="73312a8ecbb4fb28d154eede2e5c4ec5"/></dir><dir name="Helper"><file name="Data.php" hash="0decbd7691a9b2224a65139ff59ec7df"/></dir><dir name="Model"><file name="Cronjob.php" hash="2cece4bee12e728bf4693518d3d4c842"/><dir name="Event"><file name="Cache.php" hash="2109ac7d1cb9d6fd9315f7fb0f3a67b1"/><file name="Reindex.php" hash="09f014e4c39c53f6269807f1a653eb08"/><file name="Store.php" hash="30322b55ffbbd3b56241ef3df38ca7d2"/></dir><file name="Event.php" hash="59465f878999d623aa031de08712ac03"/><dir name="Metric"><file name="Abstract.php" hash="9cdf72321d21955b7619c0555fe9540f"/><file name="Customer.php" hash="5e7ef02383d0fc5339b87a03f7cac142"/><file name="File.php" hash="ca4539525a0702f66dac9011d5fdfa10"/><file name="Order.php" hash="6e62427102baab9846923b5091a80c31"/><file name="Product.php" hash="ee71e31d1e6b8ee1ea0d4073081c3eea"/><file name="Rewrite.php" hash="aef4f9687e64cd886440c9e1603d05cb"/></dir><file name="Metric.php" hash="33762b4367c9b0f98634fecd12ec0ee6"/><dir name="Resource"><dir name="Event"><file name="Collection.php" hash="b9f1136e9a418a92ca86096664cab4d1"/></dir><file name="Event.php" hash="412b640cd9b285406cc368057af3d620"/><dir name="Metric"><file name="Collection.php" hash="c2437a6f5e402d78e6e674ed0be4609c"/></dir><file name="Metric.php" hash="c79ff08f4188317b52c8875ea60d78cd"/></dir></dir><dir name="sql"><dir name="coscale_monitor_setup"><file name="install-0.1.0.php" hash="05c50b690e49378003938abbe894f8ee"/><file name="upgrade-0.1.0-0.2.0.php" hash="6e6813a302af3f75d97a33158f1717b2"/><file name="upgrade-0.2.0-0.3.0.php" hash="191d51c3ece4fddc2aa3cf7e66c8be51"/><file name="upgrade-0.3.0-0.4.0.php" hash="4c7178d394eb42e9933beab9b1079492"/><file name="upgrade-0.4.0-0.5.0.php" hash="dd2bfe447e09f818512a724ca1847726"/></dir></dir></dir></dir></dir></dir><dir name="design"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="coscale_monitor.xml" hash="f90eb20b268a97486469d16e3f75f087"/></dir><dir name="template"><dir name="coscale_monitor"><file name="rum.phtml" hash="8784353a1539341957b301c944961615"/></dir></dir></dir></dir></dir></dir><dir name="etc"><dir name="modules"><file name="CoScale_Monitor.xml" hash="3aaf3341c82ee74aa76dbe6764b423f5"/></dir></dir></dir><dir name="shell"><file name="coscale.php" hash="5f95b6440f28392c503910c0d78e5eb4"/></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
18
+ </package>
shell/coscale.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once 'abstract.php';
4
+
5
+ /**
6
+ * CoScale shell script that will output the different elements of the module
7
+ *
8
+ * @package CoScale_Monitor
9
+ * @author Rian Orie <rian.orie@supportdesk.nu>
10
+ * @created 2015-07-03
11
+ * @version 1.0
12
+ */
13
+ class CoScale_Shell extends Mage_Shell_Abstract
14
+ {
15
+ protected $debug = false;
16
+
17
+ /**
18
+ * Execute the script
19
+ */
20
+ public function run()
21
+ {
22
+
23
+ $output['metrics'] = array();
24
+
25
+ if ($this->getArg('debug')) {
26
+ $this->debug = true;
27
+ }
28
+
29
+ // Metric collection
30
+ $this->writeDebug('Start Metric Collection');
31
+ $startTime = microtime(true);
32
+
33
+ $metricOrderDelete = Mage::getSingleton('coscale_monitor/metric_order');
34
+ $collection = Mage::getModel('coscale_monitor/metric')->getCollection();
35
+ /** @var CoScale_Monitor_Model_Metric $metric */
36
+ foreach ($collection as $metric) {
37
+ $output['metrics'][] = array(
38
+ 'name' => $metric->getName(),
39
+ 'unit' => $metric->getUnit(),
40
+ 'value' => (float)$metric->getValue(),
41
+ 'store_id' => (int)$metric->getStoreId(),
42
+ 'type' => $metric->getTypeText());
43
+
44
+ // Check if metric need to be reset after collection
45
+ if ($metricOrderDelete->resetOnCollect($metric->getKey())) {
46
+ $metric->delete();
47
+ }
48
+ }
49
+ $this->writeDebug('Completed in '.(microtime(true)-$startTime).' seconds');
50
+
51
+
52
+ // Abandonned carts
53
+ $this->writeDebug('Start Abandonned carts');
54
+ $startTime = microtime(true);
55
+
56
+ $carts = Mage::getSingleton('coscale_monitor/metric_order')->getAbandonnedCarts();
57
+ foreach ($carts as $data) {
58
+ $output['metrics'][] =$data;
59
+ }
60
+ $this->writeDebug('Completed in '.(microtime(true)-$startTime).' seconds');
61
+
62
+ // Amount of files in var/log
63
+ $this->writeDebug('Start Error Reports');
64
+ $startTime = microtime(true);
65
+
66
+ $output['metrics'][] = Mage::getSingleton('coscale_monitor/metric_file')->getErrorReports();
67
+ $this->writeDebug('Completed in '.(microtime(true)-$startTime).' seconds');
68
+
69
+ // Log file details
70
+ $this->writeDebug('Start Log Files');
71
+ $startTime = microtime(true);
72
+
73
+ $logFiles = Mage::getSingleton('coscale_monitor/metric_file')->getLogFiles();
74
+ foreach ($logFiles as $data) {
75
+ $output['metrics'][] = $data;
76
+ }
77
+ $this->writeDebug('Completed in '.(microtime(true)-$startTime).' seconds');
78
+
79
+ // URL Rewrite details
80
+ $this->writeDebug('Start URL Rewrites');
81
+ $startTime = microtime(true);
82
+
83
+ $urlRewrites = Mage::getSingleton('coscale_monitor/metric_rewrite')->getUrlRewrites();
84
+ foreach ($urlRewrites as $data) {
85
+ $output['metrics'][] = $data;
86
+ }
87
+ $this->writeDebug('Completed in '.(microtime(true)-$startTime).' seconds');
88
+
89
+ // Email queue size
90
+ $this->writeDebug('Start Email Queue Site');
91
+ $startTime = microtime(true);
92
+
93
+ $emailQueueSize = Mage::getSingleton('coscale_monitor/metric_order')->getEmailQueueSize();
94
+ foreach ($emailQueueSize as $data) {
95
+ $output['metrics'][] = $data;
96
+ }
97
+ $this->writeDebug('Completed in '.(microtime(true)-$startTime).' seconds');
98
+
99
+ $output['events'] = array();
100
+
101
+ // Maintenance Flag
102
+ $this->writeDebug('Start Maintenance Flag');
103
+ $startTime = microtime(true);
104
+
105
+
106
+ if (file_exists(Mage::getBaseDir('base') . DS . 'maintenance.flag')) {
107
+ $output['events'][] = array(
108
+ 'type' => CoScale_Monitor_Model_Event::GROUP_ADMIN,
109
+ 'message' => 'Maintenance mode enabled',
110
+ 'start_time' => 0,
111
+ 'stop_time' => 0,
112
+ );
113
+ }
114
+ $this->writeDebug('Completed in '.(microtime(true)-$startTime).' seconds');
115
+
116
+ // Event collection
117
+ $this->writeDebug('Start Event Collection');
118
+ $startTime = microtime(true);
119
+
120
+ $collection = Mage::getModel('coscale_monitor/event')->getCollection();
121
+ /** @var CoScale_Monitor_Model_Event $event */
122
+ foreach ($collection as $event) {
123
+ $output['events'][] = array(
124
+ 'type' => $event->getTypeGroup(),
125
+ 'message' => $event->getDescription(),
126
+ 'data' => array_merge(array('originator'=>$event->getSource()), unserialize($event->getEventData())),
127
+ 'start_time' => (int)(time() - $event->getTimestampStart()),
128
+ 'stop_time' => (int)($event->getTimestampEnd() != 0 ? (time() - $event->getTimestampEnd()) : 0),
129
+ );
130
+ $event->delete();
131
+ if ($event->getState() != $event::STATE_ENABLED) {
132
+ //$event->delete();
133
+ }
134
+ }
135
+ $this->writeDebug('Completed in '.(microtime(true)-$startTime).' seconds');
136
+
137
+ // Cronjobs
138
+ $this->writeDebug('Start Cronjobs Collection');
139
+ $startTime = microtime(true);
140
+
141
+ $endDateTime = date('U');
142
+ $collection = Mage::getModel('cron/schedule')->getCollection()
143
+ ->addFieldToFilter('finished_at', array('from' => date('Y-m-d H:i:s', $endDateTime-65)))
144
+ ->setOrder('finished_at', 'DESC');
145
+ /** @var Mage_Cron_Model_Schedule $event */
146
+ foreach ($collection as $cron) {
147
+ $output['events'][] = array(
148
+ 'type' => CoScale_Monitor_Model_Event::GROUP_CRON,
149
+ 'message' => $cron->getJobCode(),
150
+ 'status' => $cron->getStatus(),
151
+ 'start_time' => (int)(time() - strtotime($cron->getExecutedAt())),
152
+ 'stop_time' => (int)(time() - strtotime($cron->getFinishedAt())),
153
+ );
154
+ }
155
+ $this->writeDebug('Completed in '.(microtime(true)-$startTime).' seconds');
156
+
157
+ // Modules
158
+ $this->writeDebug('Start Modules Collection');
159
+ $startTime = microtime(true);
160
+
161
+ $output['modules'] = array();
162
+ $output['modules'][] = array('name' => 'core', 'version' => (string)Mage::getVersion());
163
+ foreach (Mage::getConfig()->getNode('modules')->children() as $module) {
164
+ $output['modules'][] = array('name' => $module->getName(), 'version' => (string)$module->version);
165
+ }
166
+ $this->writeDebug('Completed in '.(microtime(true)-$startTime).' seconds');
167
+
168
+ // Stores
169
+ $this->writeDebug('Start Stores Collection');
170
+ $startTime = microtime(true);
171
+
172
+ $output['stores'] = array();
173
+ foreach (Mage::app()->getStores() as $store) {
174
+ $output['stores'][] = array('name' => $store->getName(), 'id' => (int)$store->getId());
175
+ }
176
+ $this->writeDebug('Completed in '.(microtime(true)-$startTime).' seconds');
177
+
178
+ // Write JSON output
179
+ $this->writeDebug('Start Write JSON Output');
180
+ $startTime = microtime(true);
181
+
182
+ echo Zend_Json::encode($output);
183
+ $this->writeDebug('Completed in '.(microtime(true)-$startTime).' seconds');
184
+
185
+ $this->writeDebug('Run completed!');
186
+ }
187
+
188
+ public function writeDebug($msg)
189
+ {
190
+ if ($this->debug) {
191
+ Mage::log($msg, Zend_Log::DEBUG, 'coscale-collect.log', true);
192
+ }
193
+ }
194
+ }
195
+
196
+ $shell = new CoScale_Shell();
197
+ $shell->run();