CoScale - Version 0.12.0

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.12.0
Comparing to
See all releases


Version 0.12.0

Files changed (33) hide show
  1. app/code/community/CoScale/Monitor/Helper/Data.php +72 -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/Observer.php +83 -0
  6. app/code/community/CoScale/Monitor/Model/Event/Reindex.php +43 -0
  7. app/code/community/CoScale/Monitor/Model/Event/Store.php +38 -0
  8. app/code/community/CoScale/Monitor/Model/Metric.php +148 -0
  9. app/code/community/CoScale/Monitor/Model/Metric/Abstract.php +109 -0
  10. app/code/community/CoScale/Monitor/Model/Metric/Customer.php +98 -0
  11. app/code/community/CoScale/Monitor/Model/Metric/File.php +88 -0
  12. app/code/community/CoScale/Monitor/Model/Metric/Observer.php +42 -0
  13. app/code/community/CoScale/Monitor/Model/Metric/Order.php +672 -0
  14. app/code/community/CoScale/Monitor/Model/Metric/Product.php +219 -0
  15. app/code/community/CoScale/Monitor/Model/Metric/Rewrite.php +63 -0
  16. app/code/community/CoScale/Monitor/Model/Metric/System.php +39 -0
  17. app/code/community/CoScale/Monitor/Model/Output/Generator.php +38 -0
  18. app/code/community/CoScale/Monitor/Model/Resource/Event.php +49 -0
  19. app/code/community/CoScale/Monitor/Model/Resource/Event/Collection.php +21 -0
  20. app/code/community/CoScale/Monitor/Model/Resource/Metric.php +50 -0
  21. app/code/community/CoScale/Monitor/Model/Resource/Metric/Collection.php +20 -0
  22. app/code/community/CoScale/Monitor/etc/config.xml +277 -0
  23. app/code/community/CoScale/Monitor/etc/system.xml +57 -0
  24. app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/install-0.1.0.php +175 -0
  25. app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/upgrade-0.1.0-0.2.0.php +18 -0
  26. app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/upgrade-0.2.0-0.3.0.php +20 -0
  27. app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/upgrade-0.3.0-0.4.0.php +25 -0
  28. app/code/community/CoScale/Monitor/sql/coscale_monitor_setup/upgrade-0.4.0-0.5.0.php +24 -0
  29. app/design/frontend/base/default/layout/coscale_monitor.xml +12 -0
  30. app/design/frontend/base/default/template/coscale_monitor/rum.phtml +1 -0
  31. app/etc/modules/CoScale_Monitor.xml +9 -0
  32. package.xml +18 -0
  33. shell/coscale.php +45 -0
app/code/community/CoScale/Monitor/Helper/Data.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ protected $debug = false;
14
+ protected $timer = array();
15
+
16
+ public function isEnabled()
17
+ {
18
+ if (!Mage::getStoreConfig('system/coscale_monitor/enabled')) {
19
+ return false;
20
+ }
21
+
22
+ $resource = Mage::getSingleton('core/resource')->getConnection('core_write');
23
+
24
+ try {
25
+ $tables = Mage::getConfig()->getNode('global/models/coscale_monitor_resource/entities')->asArray();
26
+
27
+ foreach ($tables as $id => $data) {
28
+ $metricTable = $resource->getTableName($data['table']);
29
+ if (! $resource->isTableExists($metricTable)) {
30
+ return false;
31
+ }
32
+ }
33
+ } catch (Exception $ex) {
34
+ return false;
35
+ }
36
+ return true;
37
+ }
38
+
39
+ public function writeDebug($msg)
40
+ {
41
+ if ($this->debug) {
42
+ Mage::log($msg, Zend_Log::DEBUG, 'coscale-collect.log', true);
43
+ }
44
+ }
45
+
46
+ public function debugStart($name)
47
+ {
48
+ $this->writeDebug('Start: ' . $name);
49
+ $this->timer[$name] = microtime(true);
50
+ }
51
+
52
+ public function debugEnd($name)
53
+ {
54
+ $startTime = isset($this->timer[$name]) ? $this->timer[$name]:microtime(true);
55
+ $duration = microtime(true)-$startTime;
56
+
57
+ $this->writeDebug('Completed: ' . $name . ' (' . number_format($duration, 6) . 's)');
58
+ }
59
+
60
+ public function debugEndError($name, $ex)
61
+ {
62
+ $startTime = isset($this->timer[$name]) ? $this->timer[$name]:microtime(true);
63
+ $duration = microtime(true)-$startTime;
64
+
65
+ $this->writeDebug('Error: ' . $name . ' (' . number_format($duration, 6) . 's) [' . $ex->getMessage() . ']');
66
+ }
67
+
68
+ public function enableDebug()
69
+ {
70
+ $this->debug = true;
71
+ }
72
+ }
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($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/Observer.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class CoScale_Monitor_Model_Event_Observer
4
+ {
5
+ public function generate(Varien_Event_Observer $observer)
6
+ {
7
+ $event = $observer->getEvent();
8
+
9
+ /** @var CoScale_Monitor_Helper_Data $logger */
10
+ $logger = $event->getLogger();
11
+ /** @var CoScale_Monitor_Model_Output_Generator $output */
12
+ $output = $event->getOutput();
13
+
14
+ // Get Events Collection
15
+ try {
16
+ $logger->debugStart('Events Collection');
17
+
18
+ $collection = Mage::getModel('coscale_monitor/event')->getCollection();
19
+ /** @var CoScale_Monitor_Model_Event $event */
20
+ foreach ($collection as $event) {
21
+ $output->addEvent(
22
+ array(
23
+ 'type' => $event->getTypeGroup(),
24
+ 'message' => $event->getDescription(),
25
+ 'data' => array_merge(
26
+ array('originator' => $event->getSource()),
27
+ unserialize($event->getEventData())
28
+ ),
29
+ 'start_time' => (int)(time() - $event->getTimestampStart()),
30
+ 'stop_time' => (int)($event->getTimestampEnd() != 0 ? (time() - $event->getTimestampEnd()) : 0),
31
+ )
32
+ );
33
+
34
+ $event->delete();
35
+ if ($event->getState() != $event::STATE_ENABLED) {
36
+ //$event->delete();
37
+ }
38
+ }
39
+ $logger->debugEnd('Events Collection');
40
+ } catch (Exception $ex) {
41
+ $logger->debugEndError('Events Collection', $ex);
42
+ }
43
+
44
+ // Get Cronjob Collection
45
+ try {
46
+ $logger->debugStart('Cronjob Collection');
47
+
48
+ $endDateTime = date('U');
49
+ $collection = Mage::getModel('cron/schedule')->getCollection()
50
+ ->addFieldToFilter('finished_at', array('from' => date('Y-m-d H:i:s', $endDateTime-65)))
51
+ ->setOrder('finished_at', 'DESC');
52
+ /** @var Mage_Cron_Model_Schedule $event */
53
+ foreach ($collection as $cron) {
54
+ $output['events'][] = array(
55
+ 'type' => CoScale_Monitor_Model_Event::GROUP_CRON,
56
+ 'message' => $cron->getJobCode(),
57
+ 'status' => $cron->getStatus(),
58
+ 'start_time' => (int)(time() - strtotime($cron->getExecutedAt())),
59
+ 'stop_time' => (int)(time() - strtotime($cron->getFinishedAt())),
60
+ );
61
+ }
62
+ $logger->debugEnd('Cronjob Collection');
63
+ } catch (Exception $ex) {
64
+ $logger->debugEndError('Events Collection', $ex);
65
+ }
66
+
67
+ try {
68
+ $logger->debugStart('Maintenance Flag');
69
+ if (file_exists(Mage::getBaseDir('base') . DS . 'maintenance.flag')) {
70
+ $output['events'][] = array(
71
+ 'type' => CoScale_Monitor_Model_Event::GROUP_ADMIN,
72
+ 'message' => 'Maintenance mode enabled',
73
+ 'start_time' => 0,
74
+ 'stop_time' => 0,
75
+ );
76
+ }
77
+ $logger->debugEnd('Maintenance Flag');
78
+ } catch (Exception $ex) {
79
+ $logger->debugEndError('Maintenance Flag', $ex);
80
+ }
81
+
82
+ }
83
+ }
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,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ protected $_helper = false;
15
+
16
+ protected $_metricType = CoScale_Monitor_Model_Metric::TYPE_APPLICATION;
17
+
18
+ const ACTION_UPDATE = 1;
19
+ const ACTION_INCREMENT=2;
20
+
21
+ public function __construct()
22
+ {
23
+ $this->_metric = Mage::getModel('coscale_monitor/metric');
24
+ $this->_helper = Mage::helper('coscale_monitor');
25
+ $this->_contruct();
26
+ }
27
+
28
+ /**
29
+ * Public contructor
30
+ */
31
+ public function _contruct()
32
+ {
33
+
34
+ }
35
+
36
+ /**
37
+ * Shorthand to add/update or increment a metric to the system
38
+ *
39
+ * @param int $action Specify action
40
+ * @param int $key A key as predefined in this model
41
+ * @param int $store The store id
42
+ * @param int|bool $type A predefined type for the metric
43
+ * @param string|bool $name The name of the metric
44
+ * @param string|bool $descr A longer description of the metric
45
+ * @param mixed $value The value to set
46
+ * @param string|bool $unit The unit the value is saved in
47
+ *
48
+ * @throws Exception
49
+ */
50
+ protected function setMetric($action, $key, $store, $value, $unit = false, $type = false, $name = false, $descr = false)
51
+ {
52
+ if (!$type) {
53
+ $type = $this->_metricType;
54
+ }
55
+
56
+ if (!$name && isset($this->_metricData[$key]['name'])) {
57
+ $name = $this->_metricData[$key]['name'];
58
+ }
59
+
60
+ if (!$descr && isset($this->_metricData[$key]['description'])) {
61
+ $descr = $this->_metricData[$key]['description'];
62
+ }
63
+
64
+ if (!$unit && isset($this->_metricData[$key]['unit'])) {
65
+ $unit = $this->_metricData[$key]['unit'];
66
+ }
67
+
68
+ if (!$name || !$descr || !$unit) {
69
+ throw new Exception('Invalid metric data supplied');
70
+ }
71
+
72
+ if ($action == self::ACTION_UPDATE) {
73
+ $this->_metric->updateMetric($key, $store, $type, $name, $descr, $value, $unit);
74
+ } else {
75
+ $this->_metric->incrementMetric($key, $store, $type, $name, $descr, $value, $unit);
76
+ }
77
+ }
78
+
79
+ /**
80
+ * @param $key
81
+ * @param $store
82
+ * @return int
83
+ */
84
+ protected function getMetric($key, $store)
85
+ {
86
+ if (!$data = $this->getMetricData($key, $store)) {
87
+ return 0;
88
+ }
89
+ return $data->getValue();
90
+ }
91
+
92
+ /**
93
+ * @param $key
94
+ * @param $store
95
+ * @return $data|bool
96
+ */
97
+ protected function getMetricData($key, $store)
98
+ {
99
+ /** @var CoScale_Monitor_Model_Metric $data */
100
+ $data = $this->_metric->loadByKey($key, $store);
101
+
102
+ if (!$data->getId()) {
103
+ return false;
104
+ }
105
+ return $data;
106
+ }
107
+
108
+
109
+ }
app/code/community/CoScale/Monitor/Model/Metric/Customer.php ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ if (!$this->_helper->isEnabled()) {
42
+ return;
43
+ }
44
+
45
+ /** @var Mage_Customer_Model_Customer $customer */
46
+ $customer = $observer->getEvent()->getCustomer();
47
+
48
+ if ($customer->getOrigData('entity_id') == $customer->getId()) {
49
+ return;
50
+ }
51
+
52
+ $this->setMetric(
53
+ self::ACTION_INCREMENT,
54
+ self::KEY_CUSTOMER_TOTAL,
55
+ $customer->getStore()->getId(),
56
+ 1
57
+ );
58
+ }
59
+
60
+ /**
61
+ * Cronjob to update the total number of customers
62
+ */
63
+ public function dailyCron()
64
+ {
65
+ if (!$this->_helper->isEnabled()) {
66
+ return;
67
+ }
68
+ $this->updateTotalCount();
69
+ }
70
+
71
+ /**
72
+ * Daily update full numbers of customers
73
+ */
74
+ public function updateTotalCount()
75
+ {
76
+ $collection = Mage::getResourceModel('customer/customer_collection');
77
+ if (!is_object($collection)) {
78
+ return;
79
+ }
80
+ $collection->getSelect()
81
+ ->reset('columns')
82
+ ->columns(array('website_id' => 'e.website_id',
83
+ 'customer_count' => 'COUNT(*)'))
84
+ ->group('e.website_id');
85
+
86
+ foreach ($collection as $customer) {
87
+ $storeIds = Mage::app()->getWebsite($customer->getWebsiteId())->getStoreIds();
88
+ foreach ($storeIds as $storeId) {
89
+ $this->setMetric(
90
+ self::ACTION_UPDATE,
91
+ self::KEY_CUSTOMER_TOTAL,
92
+ $storeId,
93
+ $customer->getCustomerCount()
94
+ );
95
+ }
96
+ }
97
+ }
98
+ }
app/code/community/CoScale/Monitor/Model/Metric/File.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ public function generate(Varien_Event_Observer $observer)
13
+ {
14
+ $event = $observer->getEvent();
15
+
16
+ /** @var CoScale_Monitor_Helper_Data $logger */
17
+ $logger = $event->getLogger();
18
+ /** @var CoScale_Monitor_Model_Output_Generator $output */
19
+ $output = $event->getOutput();
20
+
21
+ // Get Error reports
22
+ try {
23
+ $logger->debugStart('Error Reports');
24
+
25
+ $output->addMetric($this->getErrorReports());
26
+
27
+ $logger->debugEnd('Error Reports');
28
+ } catch (Exception $ex) {
29
+ $logger->debugEndError('Error Reports', $ex);
30
+ }
31
+
32
+ // Get Logfiles (name and size)
33
+ try {
34
+ $logger->debugStart('Logfiles');
35
+
36
+ foreach ($this->getLogFiles() as $data) {
37
+ $output->addMetric($data);
38
+ }
39
+ $logger->debugEnd('Logfiles');
40
+ } catch (Exception $ex) {
41
+ $logger->debugEndError('Logfiles', $ex);
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Get amount of reports in var/report
47
+ * @return array
48
+ */
49
+ public function getErrorReports()
50
+ {
51
+ $dir = Mage::getBaseDir('var') . DS . 'report';
52
+
53
+ $contents = scandir($dir);
54
+
55
+ return array(
56
+ 'name' => 'Files in var/report/',
57
+ 'unit' => 'files',
58
+ 'value' => (count($contents)-2),
59
+ 'store_id' => 0,
60
+ 'type' => 'S'
61
+ );
62
+ }
63
+
64
+ /**
65
+ * Get details of logfiles in var/log
66
+ * @return array
67
+ */
68
+ public function getLogFiles()
69
+ {
70
+ $dir = Mage::getBaseDir('var') . DS . 'log';
71
+
72
+ $contents = scandir($dir);
73
+ $output = array();
74
+ foreach ($contents as $logfile) {
75
+ if ($logfile == '.' || $logfile=='..') {
76
+ continue;
77
+ }
78
+ $output[] = array(
79
+ 'name' => 'Logfile var/log/' . $logfile,
80
+ 'unit' => 'bytes',
81
+ 'value' => filesize($dir . DS . $logfile),
82
+ 'store_id' => 0,
83
+ 'type' => 'S'
84
+ );
85
+ }
86
+ return $output;
87
+ }
88
+ }
app/code/community/CoScale/Monitor/Model/Metric/Observer.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class CoScale_Monitor_Model_Metric_Observer
4
+ {
5
+ public function generate(Varien_Event_Observer $observer)
6
+ {
7
+ $event = $observer->getEvent();
8
+
9
+ /** @var CoScale_Monitor_Helper_Data $logger */
10
+ $logger = $event->getLogger();
11
+ /** @var CoScale_Monitor_Model_Output_Generator $output */
12
+ $output = $event->getOutput();
13
+
14
+ // Get Metrics Collection
15
+ try {
16
+ $logger->debugStart('Metrics Collection');
17
+
18
+ $metricOrderDelete = Mage::getSingleton('coscale_monitor/metric_order');
19
+ $collection = Mage::getModel('coscale_monitor/metric')->getCollection();
20
+ /** @var CoScale_Monitor_Model_Metric $metric */
21
+ foreach ($collection as $metric) {
22
+ $output->addMetric(
23
+ array(
24
+ 'name' => $metric->getName(),
25
+ 'unit' => $metric->getUnit(),
26
+ 'value' => (float)$metric->getValue(),
27
+ 'store_id' => (int)$metric->getStoreId(),
28
+ 'type' => $metric->getTypeText()
29
+ )
30
+ );
31
+
32
+ // Check if metric need to be reset after collection
33
+ if ($metricOrderDelete->resetOnCollect($metric->getKey())) {
34
+ $metric->delete();
35
+ }
36
+ }
37
+ $logger->debugEnd('Metrics Collection');
38
+ } catch (Exception $ex) {
39
+ $logger->debugEndError('Metrics Collection', $ex);
40
+ }
41
+ }
42
+ }
app/code/community/CoScale/Monitor/Model/Metric/Order.php ADDED
@@ -0,0 +1,672 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ protected $statusPendingPickPack = false;
15
+ protected $statusPickPack = false;
16
+ protected $statusCompletedPickPack = false;
17
+
18
+ /**
19
+ * Identifier for total orders
20
+ */
21
+ const KEY_ORDER_TOTAL = 2000;
22
+ const KEY_ORDER_TOTAL_TODAY = 2001;
23
+ const KEY_ORDER_TOTAL_NEW = 2002;
24
+
25
+ /**
26
+ * Identifier for order amount average and total
27
+ */
28
+ const KEY_ORDER_AMOUNT_AVERAGE = 2010;
29
+ const KEY_ORDER_SIZE_TOTAL = 2011;
30
+ const KEY_ORDER_AMOUNT_AVERAGE_NEW = 2012;
31
+ const KEY_ORDER_SIZE_TOTAL_NEW = 2013;
32
+
33
+ /**
34
+ * Identifier for order size average and total
35
+ */
36
+ const KEY_ORDER_SIZE_AVERAGE = 2020;
37
+ const KEY_ORDER_AMOUNT_TOTAL = 2021;
38
+ const KEY_ORDER_SIZE_AVERAGE_NEW = 2022;
39
+ const KEY_ORDER_AMOUNT_TOTAL_NEW = 2023;
40
+
41
+ /**
42
+ * Identifier for order state processing/completed
43
+ */
44
+ const KEY_ORDER_STATE_NEW = 2030;
45
+ const KEY_ORDER_STATE_PROCESSING = 2031;
46
+ const KEY_ORDER_STATE_COMPLETED = 2032;
47
+
48
+ /**
49
+ * Identifier for pick order and time calculation
50
+ */
51
+ const KEY_ORDER_STATE_PENDING_PICKPACK = 2040;
52
+ const KEY_ORDER_STATE_CURRENT_PICKPACK = 2041;
53
+ const KEY_ORDER_STATE_COMPLETED_PICKPACK = 2042;
54
+ const KEY_START_PICKPACK = 2043;
55
+ const KEY_PICKED_QTY = 2044;
56
+ const KEY_PICKED_TIME = 2045;
57
+ const KEY_AVGTIME_PICKPACK = 2046;
58
+ const KEY_TIME_PENDING_PICKPACK = 2047;
59
+ const KEY_TIME_CURRENT_PICKPACK = 2048;
60
+
61
+ /**
62
+ * Public contructor function
63
+ */
64
+ public function _contruct()
65
+ {
66
+ $this->_metricData[self::KEY_ORDER_SIZE_TOTAL_NEW] = array(
67
+ 'name' => 'New Order size total',
68
+ 'description' => 'The total size of orders since last collect for this store',
69
+ 'unit' => 'items'
70
+ );
71
+
72
+ $this->_metricData[self::KEY_ORDER_SIZE_AVERAGE_NEW] = array(
73
+ 'name' => 'Order size average',
74
+ 'description' => 'The average size of orders since last collect for this store',
75
+ 'unit' => 'items'
76
+ );
77
+
78
+ $this->_metricData[self::KEY_ORDER_AMOUNT_TOTAL_NEW] = array(
79
+ 'name' => 'New Order amount total',
80
+ 'description' => 'The total amount of orders since last collect for this store',
81
+ 'unit' => 'Amount'
82
+ );
83
+
84
+ $this->_metricData[self::KEY_ORDER_AMOUNT_AVERAGE_NEW] = array(
85
+ 'name' => 'Order amount average',
86
+ 'description' => 'The average amount of orders since last collect for this store',
87
+ 'unit' => 'Amount'
88
+ );
89
+
90
+ $this->_metricData[self::KEY_ORDER_TOTAL_NEW] = array(
91
+ 'name' => 'Total New Orders',
92
+ 'description' => 'The total number of orders since last collect for this store',
93
+ 'unit' => 'orders'
94
+ );
95
+
96
+ $this->_metricData[self::KEY_ORDER_SIZE_TOTAL] = array(
97
+ 'name' => 'Order size total',
98
+ 'description' => 'The total size of all order in the system for this store',
99
+ 'unit' => 'items'
100
+ );
101
+
102
+ $this->_metricData[self::KEY_ORDER_SIZE_AVERAGE] = array(
103
+ 'name' => 'Order size total average',
104
+ 'description' => 'The average size of an order in the system for this store',
105
+ 'unit' => 'items'
106
+ );
107
+
108
+ $this->_metricData[self::KEY_ORDER_AMOUNT_TOTAL] = array(
109
+ 'name' => 'Order amount total',
110
+ 'description' => 'The total amount of an order in the system for this store',
111
+ 'unit' => 'Amount'
112
+ );
113
+
114
+ $this->_metricData[self::KEY_ORDER_AMOUNT_AVERAGE] = array(
115
+ 'name' => 'Order amount total average',
116
+ 'description' => 'The average amount of an order in the system for this store',
117
+ 'unit' => 'Amount'
118
+ );
119
+
120
+ $this->_metricData[self::KEY_ORDER_TOTAL] = array(
121
+ 'name' => 'Orders',
122
+ 'description' => 'The total number of orders in the system for this store',
123
+ 'unit' => 'orders'
124
+ );
125
+
126
+ $this->_metricData[self::KEY_ORDER_STATE_NEW] = array(
127
+ 'name' => 'Orders new',
128
+ 'description' => 'The total number of orders in new state',
129
+ 'unit' => 'orders'
130
+ );
131
+
132
+ $this->_metricData[self::KEY_ORDER_STATE_PROCESSING] = array(
133
+ 'name' => 'Orders processing',
134
+ 'description' => 'The total number of orders in processing state',
135
+ 'unit' => 'orders'
136
+ );
137
+
138
+ $this->_metricData[self::KEY_ORDER_STATE_COMPLETED] = array(
139
+ 'name' => 'Orders completed',
140
+ 'description' => 'The total number of orders in completed state',
141
+ 'unit' => 'orders'
142
+ );
143
+
144
+ $this->_metricData[self::KEY_ORDER_STATE_PENDING_PICKPACK] = array(
145
+ 'name' => 'Orders pending pick/pack',
146
+ 'description' => 'The total number of orders in waiting for pick/pack state',
147
+ 'unit' => 'orders'
148
+ );
149
+
150
+ $this->_metricData[self::KEY_ORDER_STATE_CURRENT_PICKPACK] = array(
151
+ 'name' => 'Orders pick/pack',
152
+ 'description' => 'The total number of orders in pick/pack state',
153
+ 'unit' => 'orders'
154
+ );
155
+
156
+ $this->_metricData[self::KEY_ORDER_STATE_COMPLETED_PICKPACK] = array(
157
+ 'name' => 'Orders completed pick/pack',
158
+ 'description' => 'The total number of orders in completed pick/pack state',
159
+ 'unit' => 'orders'
160
+ );
161
+
162
+ $this->_metricData[self::KEY_PICKED_QTY] = array(
163
+ 'name' => 'Picked qty',
164
+ 'description' => 'The qty of orders picked',
165
+ 'unit' => 'qty'
166
+ );
167
+
168
+ $this->_metricData[self::KEY_PICKED_TIME] = array(
169
+ 'name' => 'Picked time',
170
+ 'description' => 'Total time to pick/pack',
171
+ 'unit' => 'seconds'
172
+ );
173
+
174
+ $this->_metricData[self::KEY_AVGTIME_PICKPACK] = array(
175
+ 'name' => 'Avg time pick/pack',
176
+ 'description' => 'Avg time to pick/pack an order',
177
+ 'unit' => 'seconds'
178
+ );
179
+
180
+ $this->_metricData[self::KEY_TIME_PENDING_PICKPACK] = array(
181
+ 'name' => 'Time pending pick/pack',
182
+ 'description' => 'The total time needed to pick/pack new orders',
183
+ 'unit' => 'seconds'
184
+ );
185
+
186
+ $this->_metricData[self::KEY_TIME_CURRENT_PICKPACK] = array(
187
+ 'name' => 'Time current pick/pack',
188
+ 'description' => 'The total time needed to pick/pack current orders in pick/pack state',
189
+ 'unit' => 'seconds'
190
+ );
191
+
192
+ $this->statusPendingPickPack = Mage::getStoreConfig('system/coscale_monitor/status_pickpack_pending');
193
+ $this->statusPickPack = Mage::getStoreConfig('system/coscale_monitor/status_pickpack');
194
+ $this->statusCompletedPickPack = Mage::getStoreConfig('system/coscale_monitor/status_pickpack_completed');
195
+ }
196
+
197
+ public function resetOnCollect($key)
198
+ {
199
+ $resetKeys = array(
200
+ self::KEY_ORDER_TOTAL_NEW,
201
+ self::KEY_ORDER_AMOUNT_AVERAGE_NEW,
202
+ self::KEY_ORDER_SIZE_TOTAL_NEW,
203
+ self::KEY_ORDER_SIZE_AVERAGE_NEW,
204
+ self::KEY_ORDER_AMOUNT_TOTAL_NEW,
205
+
206
+ );
207
+
208
+ if (in_array($key, $resetKeys)) {
209
+ return true;
210
+ }
211
+ return false;
212
+ }
213
+
214
+ /**
215
+ * Observe the adding of new orders to the system
216
+ *
217
+ * @param Varien_Event_Observer $observer
218
+ */
219
+ public function salesOrderPlaceAfter(Varien_Event_Observer $observer)
220
+ {
221
+ if (!$this->_helper->isEnabled()) {
222
+ return;
223
+ }
224
+
225
+ /** @var Mage_Sales_Model_Order $order */
226
+ $order = $observer->getEvent()->getOrder();
227
+ $amountUnit = Mage::getStoreConfig('currency/options/base', $order->getStoreId());
228
+
229
+ $this->setMetric(
230
+ self::ACTION_INCREMENT,
231
+ self::KEY_ORDER_SIZE_TOTAL,
232
+ $order->getStoreId(),
233
+ $order->getTotalItemCount()
234
+ );
235
+
236
+ $this->setMetric(
237
+ self::ACTION_INCREMENT,
238
+ self::KEY_ORDER_AMOUNT_TOTAL,
239
+ $order->getStoreId(),
240
+ $order->getBaseGrandTotal(),
241
+ $amountUnit
242
+ );
243
+
244
+ $this->setMetric(
245
+ self::ACTION_INCREMENT,
246
+ self::KEY_ORDER_TOTAL,
247
+ $order->getStoreId(),
248
+ 1
249
+ );
250
+
251
+ $this->setMetric(
252
+ self::ACTION_INCREMENT,
253
+ self::KEY_ORDER_SIZE_TOTAL_NEW,
254
+ $order->getStoreId(),
255
+ $order->getTotalItemCount()
256
+ );
257
+
258
+ $this->setMetric(
259
+ self::ACTION_INCREMENT,
260
+ self::KEY_ORDER_AMOUNT_TOTAL_NEW,
261
+ $order->getStoreId(),
262
+ $order->getBaseGrandTotal(),
263
+ $amountUnit
264
+ );
265
+
266
+ $this->setMetric(
267
+ self::ACTION_INCREMENT,
268
+ self::KEY_ORDER_TOTAL_NEW,
269
+ $order->getStoreId(),
270
+ 1
271
+ );
272
+
273
+ $this->updateAvgOrderValues($order->getStoreId());
274
+ }
275
+
276
+ /**
277
+ * Save order status changes on order save
278
+ *
279
+ * @param Varien_Event_Observer $observer
280
+ */
281
+ public function salesOrderSaveCommitAfter(Varien_Event_Observer $observer)
282
+ {
283
+ $keys = array();
284
+ if (!$this->_helper->isEnabled()) {
285
+ return;
286
+ }
287
+
288
+ /** @var Mage_Sales_Model_Order $order */
289
+ $order = $observer->getEvent()->getOrder();
290
+
291
+ // Update state/status statistics (only if changed)
292
+ if ($order->getState() != $order->getOrigData('state')) {
293
+ // Decrease qty for previous state
294
+ switch ($order->getOrigData('state')) {
295
+ case Mage_Sales_Model_Order::STATE_NEW:
296
+ $keys[self::KEY_ORDER_STATE_NEW] = -1;
297
+ break;
298
+ case Mage_Sales_Model_Order::STATE_PROCESSING:
299
+ $keys[self::KEY_ORDER_STATE_PROCESSING] = -1;
300
+ break;
301
+ }
302
+ // Increase qty for current state
303
+ switch ($order->getData('state')) {
304
+ case Mage_Sales_Model_Order::STATE_NEW:
305
+ $keys[self::KEY_ORDER_STATE_NEW] = 1;
306
+ break;
307
+ case Mage_Sales_Model_Order::STATE_PROCESSING:
308
+ $keys[self::KEY_ORDER_STATE_PROCESSING] = 1;
309
+ break;
310
+ case Mage_Sales_Model_Order::STATE_COMPLETE:
311
+ $keys[self::KEY_ORDER_STATE_COMPLETED] = 1;
312
+ break;
313
+ }
314
+ }
315
+
316
+ if ($order->getStatus() != $order->getOrigData('status')) {
317
+ // Decrease qty for previous state
318
+ switch ($order->getOrigData('status')) {
319
+ case $this->statusPendingPickPack:
320
+ $keys[self::KEY_ORDER_STATE_PENDING_PICKPACK] = -1;
321
+ break;
322
+ case $this->statusPickPack:
323
+ $keys[self::KEY_ORDER_STATE_CURRENT_PICKPACK] = -1;
324
+ break;
325
+ case $this->statusCompletedPickPack:
326
+ $keys[self::KEY_ORDER_STATE_COMPLETED_PICKPACK] = -1;
327
+ break;
328
+ }
329
+ // Increase qty for current state
330
+ switch ($order->getData('status')) {
331
+ case $this->statusPendingPickPack:
332
+ $keys[self::KEY_ORDER_STATE_PENDING_PICKPACK] = 1;
333
+ break;
334
+ case $this->statusPickPack:
335
+ $keys[self::KEY_ORDER_STATE_CURRENT_PICKPACK] = 1;
336
+ break;
337
+ case $this->statusCompletedPickPack:
338
+ $keys[self::KEY_ORDER_STATE_COMPLETED_PICKPACK] = 1;
339
+ break;
340
+ }
341
+ }
342
+ if (count($keys)>0) {
343
+ // Check if order picked data decreases
344
+ if (isset($keys[self::KEY_ORDER_STATE_CURRENT_PICKPACK]) &&
345
+ $keys[self::KEY_ORDER_STATE_CURRENT_PICKPACK]<0) {
346
+ // Get difference between last timestamp and now (time used for orderpicking)
347
+ $timeUsed = 1;
348
+ if ($metricData = $this->getMetricData(self::KEY_PICKED_TIME, $order->getStoreId())) {
349
+ $currentDate = date('U', Mage::getModel('core/date')->timestamp(time()));
350
+ $lastDate = date('U', strtotime($metricData->getUpdatedAt()));
351
+ $timeUsed = $currentDate - $lastDate;
352
+ }
353
+ $keys[self::KEY_PICKED_TIME] = $timeUsed;
354
+ $keys[self::KEY_PICKED_QTY] = 1;
355
+ }
356
+
357
+ foreach ($keys as $key => $qty) {
358
+ if ($qty <> 0) {
359
+ $this->setMetric(
360
+ self::ACTION_INCREMENT,
361
+ $key,
362
+ $order->getStoreId(),
363
+ $qty
364
+ );
365
+ }
366
+
367
+ }
368
+ $this->updateAvgPickValues($order->getStoreId());
369
+ }
370
+
371
+ }
372
+
373
+ /**
374
+ * Update pick/pack avarage values
375
+ *
376
+ * @param $storeId
377
+ */
378
+ public function updateAvgPickValues($storeId)
379
+ {
380
+ $pickTime = $this->getMetric(self::KEY_PICKED_TIME, $storeId);
381
+ $pickQty = $this->getMetric(self::KEY_PICKED_QTY, $storeId);
382
+
383
+ // Update avg pick time
384
+ if ($pickQty>0) {
385
+ $avgPickTime = floor($pickTime/$pickQty);
386
+ $this->setMetric(
387
+ self::ACTION_UPDATE,
388
+ self::KEY_AVGTIME_PICKPACK,
389
+ $storeId,
390
+ $avgPickTime,
391
+ 'seconds'
392
+ );
393
+
394
+ $updateAvgKeys = array(
395
+ self::KEY_ORDER_STATE_PENDING_PICKPACK=>self::KEY_TIME_PENDING_PICKPACK,
396
+ self::KEY_ORDER_STATE_CURRENT_PICKPACK=>self::KEY_TIME_CURRENT_PICKPACK
397
+ );
398
+ // Update avg values for keys
399
+ foreach ($updateAvgKeys as $from => $to) {
400
+ $qty = $this->getMetric($from, $storeId);
401
+
402
+ $this->setMetric(
403
+ self::ACTION_UPDATE,
404
+ $to,
405
+ $storeId,
406
+ ($qty*$avgPickTime),
407
+ 'qty'
408
+ );
409
+ }
410
+ }
411
+ }
412
+
413
+ /**
414
+ * Update Avarage values for order details
415
+ *
416
+ * @param $storeId
417
+ */
418
+ public function updateAvgOrderValues($storeId)
419
+ {
420
+ $amountUnit = Mage::getStoreConfig('currency/options/base', $storeId);
421
+
422
+ $orderTotal = $this->getMetric(self::KEY_ORDER_TOTAL, $storeId);
423
+ $orderItems = $this->getMetric(self::KEY_ORDER_SIZE_TOTAL, $storeId);
424
+ $orderAmount = $this->getMetric(self::KEY_ORDER_AMOUNT_TOTAL, $storeId);
425
+
426
+ $newOrderTotal = $this->getMetric(self::KEY_ORDER_TOTAL_NEW, $storeId);
427
+ $newOrderItems = $this->getMetric(self::KEY_ORDER_SIZE_TOTAL_NEW, $storeId);
428
+ $newOrderAmount = $this->getMetric(self::KEY_ORDER_AMOUNT_TOTAL_NEW, $storeId);
429
+
430
+ $this->setMetric(
431
+ self::ACTION_UPDATE,
432
+ self::KEY_ORDER_SIZE_AVERAGE,
433
+ $storeId,
434
+ ($orderItems/$orderTotal),
435
+ $amountUnit
436
+ );
437
+
438
+ $this->setMetric(
439
+ self::ACTION_UPDATE,
440
+ self::KEY_ORDER_AMOUNT_AVERAGE,
441
+ $storeId,
442
+ ($orderAmount/$orderTotal),
443
+ $amountUnit
444
+ );
445
+
446
+ if ($newOrderTotal > 0) {
447
+ $this->setMetric(
448
+ self::ACTION_UPDATE,
449
+ self::KEY_ORDER_SIZE_AVERAGE_NEW,
450
+ $storeId,
451
+ ($newOrderItems / $newOrderTotal),
452
+ $amountUnit
453
+ );
454
+
455
+ $this->setMetric(
456
+ self::ACTION_UPDATE,
457
+ self::KEY_ORDER_AMOUNT_AVERAGE_NEW,
458
+ $storeId,
459
+ ($newOrderAmount / $newOrderTotal),
460
+ $amountUnit
461
+ );
462
+ }
463
+ }
464
+
465
+
466
+ public function initOrderData()
467
+ {
468
+ if (!$this->_helper->isEnabled()) {
469
+ return;
470
+ }
471
+
472
+ $collection = Mage::getResourceModel('sales/order_collection');
473
+ if (!is_object($collection)) {
474
+ return;
475
+ }
476
+ $collection->getSelect()
477
+ ->reset('columns')
478
+ ->columns(array('amount' => 'SUM(main_table.base_grand_total)',
479
+ 'items' => 'SUM(main_table.total_item_count)',
480
+ 'store_id' => 'main_table.store_id',
481
+ 'state' => 'main_table.state',
482
+ 'count' => 'COUNT(*)'))
483
+ ->group(array('main_table.store_id','main_table.state'));
484
+
485
+ $data = array();
486
+ foreach ($collection as $order) {
487
+ if (!$order->getStoreId()) {
488
+ continue;
489
+ }
490
+ if (!isset($data[$order->getStoreId()])) {
491
+ $data[$order->getStoreId()] = array(
492
+ 'items' => 0,
493
+ 'amount' => 0,
494
+ 'count' => 0,
495
+ 'new' => 0,
496
+ 'processing' => 0,
497
+ 'complete' => 0
498
+ );
499
+ }
500
+ $data[$order->getStoreId()]['items'] += $order->getItems();
501
+ $data[$order->getStoreId()]['amount'] += $order->getAmount();
502
+ $data[$order->getStoreId()]['count'] += $order->getCount();
503
+ if ($order->getState() == 'new') {
504
+ $data[$order->getStoreId()]['new'] += $order->getCount();
505
+ }
506
+
507
+ if ($order->getState() == 'processing') {
508
+ $data[$order->getStoreId()]['processing'] += $order->getCount();
509
+ }
510
+
511
+ if ($order->getState() == 'complete') {
512
+ $data[$order->getStoreId()]['complete'] += $order->getCount();
513
+ }
514
+ }
515
+
516
+ foreach ($data as $storeId => $details) {
517
+ $this->setMetric(
518
+ self::ACTION_UPDATE,
519
+ self::KEY_ORDER_SIZE_TOTAL,
520
+ $storeId,
521
+ $details['items']
522
+ );
523
+
524
+ $this->setMetric(
525
+ self::ACTION_UPDATE,
526
+ self::KEY_ORDER_AMOUNT_TOTAL,
527
+ $storeId,
528
+ $details['amount']
529
+ );
530
+
531
+ $this->setMetric(
532
+ self::ACTION_UPDATE,
533
+ self::KEY_ORDER_TOTAL,
534
+ $storeId,
535
+ $details['count']
536
+ );
537
+
538
+ $this->setMetric(
539
+ self::ACTION_UPDATE,
540
+ self::KEY_ORDER_STATE_NEW,
541
+ $storeId,
542
+ $details['new']
543
+ );
544
+
545
+ $this->setMetric(
546
+ self::ACTION_UPDATE,
547
+ self::KEY_ORDER_STATE_PROCESSING,
548
+ $storeId,
549
+ $details['processing']
550
+ );
551
+
552
+ $this->setMetric(
553
+ self::ACTION_UPDATE,
554
+ self::KEY_ORDER_STATE_COMPLETED,
555
+ $storeId,
556
+ $details['complete']
557
+ );
558
+
559
+ $this->updateAvgOrderValues($storeId);
560
+ }
561
+ }
562
+
563
+ /**
564
+ * Generate output event
565
+ *
566
+ * @param Varien_Event_Observer $observer
567
+ */
568
+ public function generate(Varien_Event_Observer $observer)
569
+ {
570
+ $event = $observer->getEvent();
571
+
572
+ /** @var CoScale_Monitor_Helper_Data $logger */
573
+ $logger = $event->getLogger();
574
+ /** @var CoScale_Monitor_Model_Output_Generator $output */
575
+ $output = $event->getOutput();
576
+
577
+ // Get Abandonned Carts
578
+ try {
579
+ $logger->debugStart('AbandonnedCarts');
580
+
581
+ $carts = $this->getAbandonnedCarts();
582
+ foreach ($carts as $data) {
583
+ $output->addMetric($data);
584
+ }
585
+ $logger->debugEnd('AbandonnedCarts');
586
+ } catch (Exception $ex) {
587
+ $logger->debugEndError('AbandonnedCarts', $ex);
588
+ }
589
+
590
+ // Get Email Queue Size
591
+ try {
592
+ $logger->debugStart('Email Queue Size');
593
+
594
+ foreach ($this->getEmailQueueSize() as $data) {
595
+ $output->addMetric($data);
596
+ }
597
+ $logger->debugEnd('Email Queue Size');
598
+ } catch (Exception $ex) {
599
+ $logger->debugEndError('Email Queue Size', $ex);
600
+ }
601
+ }
602
+
603
+ /**
604
+ * Get Abandonned cart amounts
605
+ * @return array
606
+ */
607
+ public function getAbandonnedCarts()
608
+ {
609
+ /** @var $collection Mage_Reports_Model_Resource_Quote_Collection */
610
+ $collection = Mage::getResourceModel('reports/quote_collection');
611
+ if (!is_object($collection)) {
612
+ return array();
613
+ }
614
+ $collection->prepareForAbandonedReport(array());
615
+ $collection->getSelect()
616
+ ->columns(array('store_id' => 'main_table.store_id',
617
+ 'count' => 'COUNT(*)',
618
+ 'subtotal' => 'subtotal'))
619
+ ->group('main_table.store_id');
620
+ $output = array();
621
+ foreach ($collection as $order) {
622
+ $output[] = array(
623
+ 'name' => 'Abandonned carts',
624
+ 'unit' => 'orders',
625
+ 'value' => (float)$order->getCount(),
626
+ 'store_id' => (int)$order->getStoreId(),
627
+ 'type' => 'A'
628
+ );
629
+ $output[] = array(
630
+ 'name' => 'Total value of abandoned carts',
631
+ 'unit' => 'Amount',
632
+ 'value' => (float)$order->getSubtotal(),
633
+ 'store_id' => (int)$order->getStoreId(),
634
+ 'type' => 'A'
635
+ );
636
+ }
637
+ return $output;
638
+ }
639
+
640
+
641
+
642
+ public function getEmailQueueSize()
643
+ {
644
+ $edition = method_exists('Mage', 'getEdition') ? Mage::getEdition():false;
645
+
646
+ // Pre CE1.7 version => No e-mail queue available
647
+ if (!$edition) {
648
+ return array();
649
+ }
650
+
651
+ // Pre CE 1.9 version => No e-mail queue available
652
+ if ($edition == 'Community' && version_compare(Mage::getVersion(), '1.9', '<')) {
653
+ return array();
654
+ }
655
+
656
+ // Pre EE 1.14 version => No e-mail queue available
657
+ if ($edition == 'Enterprise' && version_compare(Mage::getVersion(), '1.14', '<')) {
658
+ return array();
659
+ }
660
+ $collection = Mage::getResourceModel('core/email_queue_collection');
661
+ if (!is_object($collection)) {
662
+ return array();
663
+ }
664
+ return array(array(
665
+ 'name' => 'Amount of messages in the e-mail queue',
666
+ 'unit' => 'messages',
667
+ 'value' => $collection->getSize(),
668
+ 'store_id' => 0,
669
+ 'type' => 'A'
670
+ ));
671
+ }
672
+ }
app/code/community/CoScale/Monitor/Model/Metric/Product.php ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ if (!$this->_helper->isEnabled()) {
62
+ return;
63
+ }
64
+
65
+ /** @var Mage_Catalog_Model_Product $product */
66
+ $product = $observer->getEvent()->getProduct();
67
+
68
+ if ($product->getOrigData('entity_id') == $product->getId()) {
69
+ return;
70
+ }
71
+
72
+ $this->setMetric(
73
+ self::ACTION_INCREMENT,
74
+ self::KEY_PRODUCT_TOTAL,
75
+ 0,
76
+ 1
77
+ );
78
+
79
+ $this->setMetric(
80
+ self::ACTION_INCREMENT,
81
+ self::KEY_PRODUCT_TODAY,
82
+ 0,
83
+ 1
84
+ );
85
+ }
86
+
87
+ /**
88
+ * Observe the remove of product
89
+ *
90
+ * @param Varien_Event_Observer $observer
91
+ */
92
+ public function removeProduct(Varien_Event_Observer $observer)
93
+ {
94
+ if (!$this->_helper->isEnabled()) {
95
+ return;
96
+ }
97
+
98
+ $this->setMetric(
99
+ self::ACTION_INCREMENT,
100
+ self::KEY_PRODUCT_TOTAL,
101
+ 0,
102
+ -1
103
+ );
104
+ }
105
+
106
+ /**
107
+ * Observe the adding of new category to the system
108
+ *
109
+ * @param Varien_Event_Observer $observer
110
+ */
111
+ public function addNewCategory(Varien_Event_Observer $observer)
112
+ {
113
+ if (!$this->_helper->isEnabled()) {
114
+ return;
115
+ }
116
+
117
+ /** @var Mage_Catalog_Model_Category $category */
118
+ $category = $observer->getEvent()->getCategory();
119
+
120
+ if ($category->getOrigData('entity_id') == $category->getId()) {
121
+ return;
122
+ }
123
+
124
+ $this->setMetric(
125
+ self::ACTION_INCREMENT,
126
+ self::KEY_CATEGORIES_TOTAL,
127
+ 0,
128
+ 1
129
+ );
130
+
131
+ $this->setMetric(
132
+ self::ACTION_INCREMENT,
133
+ self::KEY_CATEGORIES_TODAY,
134
+ 0,
135
+ 1
136
+ );
137
+ }
138
+
139
+ /**
140
+ * Observe the remove of category
141
+ *
142
+ * @param Varien_Event_Observer $observer
143
+ */
144
+ public function removeCategory(Varien_Event_Observer $observer)
145
+ {
146
+ if (!$this->_helper->isEnabled()) {
147
+ return;
148
+ }
149
+
150
+ $this->setMetric(
151
+ self::ACTION_INCREMENT,
152
+ self::KEY_CATEGORIES_TOTAL,
153
+ 0,
154
+ -1
155
+ );
156
+ }
157
+
158
+ /**
159
+ * Cronjob to update the total number of customers
160
+ */
161
+ public function dailyCron()
162
+ {
163
+ if (!$this->_helper->isEnabled()) {
164
+ return;
165
+ }
166
+ $this->resetDayCounter();
167
+ $this->updateTotalCount();
168
+ }
169
+
170
+ /**
171
+ * Reset daily new created products counter
172
+ */
173
+ protected function resetDayCounter()
174
+ {
175
+ $this->setMetric(
176
+ self::ACTION_UPDATE,
177
+ self::KEY_PRODUCT_TODAY,
178
+ 0,
179
+ 0
180
+ );
181
+
182
+ $this->setMetric(
183
+ self::ACTION_UPDATE,
184
+ self::KEY_CATEGORIES_TODAY,
185
+ 0,
186
+ 0
187
+ );
188
+ }
189
+
190
+ /**
191
+ * Daily update full numbers of products
192
+ */
193
+ public function updateTotalCount()
194
+ {
195
+ $collection = Mage::getResourceModel('catalog/product_collection');
196
+ if(!is_object($collection))
197
+ {
198
+ return;
199
+ }
200
+ $this->setMetric(
201
+ self::ACTION_UPDATE,
202
+ self::KEY_PRODUCT_TOTAL,
203
+ 0,
204
+ $collection->getSize()
205
+ );
206
+
207
+ $collection = Mage::getResourceModel('catalog/category_collection');
208
+ if(!is_object($collection))
209
+ {
210
+ return;
211
+ }
212
+ $this->setMetric(
213
+ self::ACTION_UPDATE,
214
+ self::KEY_CATEGORIES_TOTAL,
215
+ 0,
216
+ $collection->getSize()
217
+ );
218
+ }
219
+ }
app/code/community/CoScale/Monitor/Model/Metric/Rewrite.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ public function generate(Varien_Event_Observer $observer)
14
+ {
15
+ $event = $observer->getEvent();
16
+
17
+ /** @var CoScale_Monitor_Helper_Data $logger */
18
+ $logger = $event->getLogger();
19
+ /** @var CoScale_Monitor_Model_Output_Generator $output */
20
+ $output = $event->getOutput();
21
+
22
+ // Get URL Rewrites
23
+ try {
24
+ $logger->debugStart('Rewrites');
25
+
26
+ foreach ($this->getUrlRewrites() as $data) {
27
+ $output->addMetric($data);
28
+ }
29
+
30
+ $logger->debugEnd('Rewrites');
31
+ } catch (Exception $ex) {
32
+ $logger->debugEndError('Rewrites', $ex);
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Get amount of rewrites
38
+ * @return array
39
+ */
40
+ public function getUrlRewrites()
41
+ {
42
+ $collection = Mage::getResourceModel('core/url_rewrite_collection');
43
+ if (!is_object($collection)) {
44
+ return array();
45
+ }
46
+ $collection->getSelect()
47
+ ->reset('columns')
48
+ ->columns(array('store_id' => 'main_table.store_id',
49
+ 'count' => 'COUNT(*)'))
50
+ ->group('main_table.store_id');
51
+
52
+ foreach ($collection as $rewrite) {
53
+ $output[] = array(
54
+ 'name' => 'URL Rewrites',
55
+ 'unit' => 'rewrites',
56
+ 'value' => (float)$rewrite->getCount(),
57
+ 'store_id' => (int)$rewrite->getStoreId(),
58
+ 'type' => 'A'
59
+ );
60
+ }
61
+ return $output;
62
+ }
63
+ }
app/code/community/CoScale/Monitor/Model/Metric/System.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class CoScale_Monitor_Model_Metric_System
4
+ {
5
+ public function generate(Varien_Event_Observer $observer)
6
+ {
7
+ $event = $observer->getEvent();
8
+
9
+ /** @var CoScale_Monitor_Helper_Data $logger */
10
+ $logger = $event->getLogger();
11
+ /** @var CoScale_Monitor_Model_Output_Generator $output */
12
+ $output = $event->getOutput();
13
+
14
+ // Get Installed Modules
15
+ try {
16
+ $logger->debugStart('Installed Modules');
17
+
18
+ $output->addCustom('modules', array('name' => 'core', 'version' => (string)Mage::getVersion()));
19
+ foreach (Mage::getConfig()->getNode('modules')->children() as $module) {
20
+ $output->addCustom('modules', array('name' => $module->getName(), 'version' => (string)$module->version));
21
+ }
22
+ $logger->debugEnd('Installed Modules');
23
+ } catch (Exception $ex) {
24
+ $logger->debugEndError('Installed Modules', $ex);
25
+ }
26
+
27
+ // Get Stores collection
28
+ try {
29
+ $logger->debugStart('Stores');
30
+
31
+ foreach (Mage::app()->getStores() as $store) {
32
+ $output->addCustom('stores', array('name' => $store->getName(), 'id' => (int)$store->getId()));
33
+ }
34
+ $logger->debugEnd('Stores');
35
+ } catch (Exception $ex) {
36
+ $logger->debugEndError('Stores', $ex);
37
+ }
38
+ }
39
+ }
app/code/community/CoScale/Monitor/Model/Output/Generator.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class CoScale_Monitor_Model_Output_Generator extends Varien_Object
4
+ {
5
+ public function __construct()
6
+ {
7
+ $logger = Mage::helper('coscale_monitor');
8
+ Mage::dispatchEvent('coscale_output_generator', array('output' => $this, 'logger'=>$logger));
9
+ }
10
+
11
+ public function addMetric($data)
12
+ {
13
+ return $this->addArray('metrics', $data);
14
+ }
15
+
16
+ public function addEvent($data)
17
+ {
18
+ return $this->addArray('events', $data);
19
+ }
20
+
21
+ public function addCustom($name, $data)
22
+ {
23
+ return $this->addArray($name, $data);
24
+ }
25
+
26
+ protected function addArray($name, $data)
27
+ {
28
+ $origData = $this->getData($name);
29
+ $origData[] = $data;
30
+ $this->setData($name, $origData);
31
+ return $this;
32
+ }
33
+
34
+ public function getJsonOutput()
35
+ {
36
+ return $this->toJson();
37
+ }
38
+ }
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,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <CoScale_Monitor>
5
+ <version>0.12.0</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
+ <coscale_output_generator>
45
+ <observers>
46
+ <coscale_generate_metrics>
47
+ <class>coscale_monitor/metric_observer</class>
48
+ <method>generate</method>
49
+ </coscale_generate_metrics>
50
+ <coscale_generate_events>
51
+ <class>coscale_monitor/event_observer</class>
52
+ <method>generate</method>
53
+ </coscale_generate_events>
54
+ <coscale_generate_order_metrics>
55
+ <class>coscale_monitor/metric_order</class>
56
+ <method>generate</method>
57
+ </coscale_generate_order_metrics>
58
+ <coscale_generate_file_metrics>
59
+ <class>coscale_monitor/metric_file</class>
60
+ <method>generate</method>
61
+ </coscale_generate_file_metrics>
62
+ <coscale_generate_rewrite_metrics>
63
+ <class>coscale_monitor/metric_rewrite</class>
64
+ <method>generate</method>
65
+ </coscale_generate_rewrite_metrics>
66
+ <coscale_generate_system_metrics>
67
+ <class>coscale_monitor/metric_system</class>
68
+ <method>generate</method>
69
+ </coscale_generate_system_metrics>
70
+ </observers>
71
+ </coscale_output_generator>
72
+ <store_save_after>
73
+ <observers>
74
+ <coscale_monitor_event_store_add>
75
+ <class>coscale_monitor/event_store</class>
76
+ <method>addNew</method>
77
+ </coscale_monitor_event_store_add>
78
+ </observers>
79
+ </store_save_after>
80
+ <customer_save_after>
81
+ <observers>
82
+ <coscale_monitor_metric_customer_add>
83
+ <class>coscale_monitor/metric_customer</class>
84
+ <method>addNew</method>
85
+ </coscale_monitor_metric_customer_add>
86
+ </observers>
87
+ </customer_save_after>
88
+ <catalog_category_save_after>
89
+ <observers>
90
+ <coscale_monitor_metric_category_add>
91
+ <class>coscale_monitor/metric_product</class>
92
+ <method>addNewCategory</method>
93
+ </coscale_monitor_metric_category_add>
94
+ </observers>
95
+ </catalog_category_save_after>
96
+ <catalog_category_delete_commit_after>
97
+ <observers>
98
+ <coscale_monitor_metric_category_remove>
99
+ <class>coscale_monitor/metric_product</class>
100
+ <method>removeCategory</method>
101
+ </coscale_monitor_metric_category_remove>
102
+ </observers>
103
+ </catalog_category_delete_commit_after>
104
+ <catalog_product_save_after>
105
+ <observers>
106
+ <coscale_monitor_metric_product_add>
107
+ <class>coscale_monitor/metric_product</class>
108
+ <method>addNewProduct</method>
109
+ </coscale_monitor_metric_product_add>
110
+ </observers>
111
+ </catalog_product_save_after>
112
+ <catalog_product_delete_commit_after>
113
+ <observers>
114
+ <coscale_monitor_metric_product_remove>
115
+ <class>coscale_monitor/metric_product</class>
116
+ <method>removeProduct</method>
117
+ </coscale_monitor_metric_product_remove>
118
+ </observers>
119
+ </catalog_product_delete_commit_after>
120
+ <sales_order_place_after>
121
+ <observers>
122
+ <coscale_monitor_metric_order_add>
123
+ <class>coscale_monitor/metric_order</class>
124
+ <method>salesOrderPlaceAfter</method>
125
+ </coscale_monitor_metric_order_add>
126
+ </observers>
127
+ </sales_order_place_after>
128
+ <sales_order_save_commit_after>
129
+ <observers>
130
+ <coscale_monitor_metric_order_save>
131
+ <class>coscale_monitor/metric_order</class>
132
+ <method>salesOrderSaveCommitAfter</method>
133
+ </coscale_monitor_metric_order_save>
134
+ </observers>
135
+ </sales_order_save_commit_after>
136
+
137
+ <controller_action_predispatch_adminhtml_process_massReindex>
138
+ <observers>
139
+ <coscale_monitor_event_reindex_start>
140
+ <class>coscale_monitor/event_reindex</class>
141
+ <method>startIndex</method>
142
+ </coscale_monitor_event_reindex_start>
143
+ </observers>
144
+ </controller_action_predispatch_adminhtml_process_massReindex>
145
+ <controller_action_postdispatch_adminhtml_process_massReindex>
146
+ <observers>
147
+ <coscale_monitor_event_reindex_start>
148
+ <class>coscale_monitor/event_reindex</class>
149
+ <method>endIndex</method>
150
+ </coscale_monitor_event_reindex_start>
151
+ </observers>
152
+ </controller_action_postdispatch_adminhtml_process_massReindex>
153
+
154
+ <controller_action_predispatch_adminhtml_cache_flushSystem>
155
+ <observers>
156
+ <coscale_monitor_event_reindex_start>
157
+ <class>coscale_monitor/event_cache</class>
158
+ <method>startFlushSystem</method>
159
+ </coscale_monitor_event_reindex_start>
160
+ </observers>
161
+ </controller_action_predispatch_adminhtml_cache_flushSystem>
162
+ <controller_action_postdispatch_adminhtml_cache_flushSystem>
163
+ <observers>
164
+ <coscale_monitor_event_reindex_start>
165
+ <class>coscale_monitor/event_cache</class>
166
+ <method>endFlushSystem</method>
167
+ </coscale_monitor_event_reindex_start>
168
+ </observers>
169
+ </controller_action_postdispatch_adminhtml_cache_flushSystem>
170
+
171
+ <controller_action_predispatch_adminhtml_cache_flushAll>
172
+ <observers>
173
+ <coscale_monitor_event_reindex_start>
174
+ <class>coscale_monitor/event_cache</class>
175
+ <method>startFlushAll</method>
176
+ </coscale_monitor_event_reindex_start>
177
+ </observers>
178
+ </controller_action_predispatch_adminhtml_cache_flushAll>
179
+ <controller_action_postdispatch_adminhtml_cache_flushAll>
180
+ <observers>
181
+ <coscale_monitor_event_reindex_start>
182
+ <class>coscale_monitor/event_cache</class>
183
+ <method>endFlushAll</method>
184
+ </coscale_monitor_event_reindex_start>
185
+ </observers>
186
+ </controller_action_postdispatch_adminhtml_cache_flushAll>
187
+
188
+ <controller_action_predispatch_adminhtml_cache_cleanImages>
189
+ <observers>
190
+ <coscale_monitor_event_reindex_start>
191
+ <class>coscale_monitor/event_cache</class>
192
+ <method>startCleanImages</method>
193
+ </coscale_monitor_event_reindex_start>
194
+ </observers>
195
+ </controller_action_predispatch_adminhtml_cache_cleanImages>
196
+ <controller_action_postdispatch_adminhtml_cache_cleanImages>
197
+ <observers>
198
+ <coscale_monitor_event_reindex_start>
199
+ <class>coscale_monitor/event_cache</class>
200
+ <method>endCleanImages</method>
201
+ </coscale_monitor_event_reindex_start>
202
+ </observers>
203
+ </controller_action_postdispatch_adminhtml_cache_cleanImages>
204
+
205
+ <controller_action_predispatch_adminhtml_cache_cleanMedia>
206
+ <observers>
207
+ <coscale_monitor_event_reindex_start>
208
+ <class>coscale_monitor/event_cache</class>
209
+ <method>startCleanAssets</method>
210
+ </coscale_monitor_event_reindex_start>
211
+ </observers>
212
+ </controller_action_predispatch_adminhtml_cache_cleanMedia>
213
+ <controller_action_postdispatch_adminhtml_cache_cleanMedia>
214
+ <observers>
215
+ <coscale_monitor_event_reindex_start>
216
+ <class>coscale_monitor/event_cache</class>
217
+ <method>endCleanAssets</method>
218
+ </coscale_monitor_event_reindex_start>
219
+ </observers>
220
+ </controller_action_postdispatch_adminhtml_cache_cleanMedia>
221
+
222
+ <controller_action_predispatch_adminhtml_cache_massRefresh>
223
+ <observers>
224
+ <coscale_monitor_event_reindex_start>
225
+ <class>coscale_monitor/event_cache</class>
226
+ <method>startMassRefresh</method>
227
+ </coscale_monitor_event_reindex_start>
228
+ </observers>
229
+ </controller_action_predispatch_adminhtml_cache_massRefresh>
230
+ <controller_action_postdispatch_adminhtml_cache_massRefresh>
231
+ <observers>
232
+ <coscale_monitor_event_reindex_start>
233
+ <class>coscale_monitor/event_cache</class>
234
+ <method>endMassRefresh</method>
235
+ </coscale_monitor_event_reindex_start>
236
+ </observers>
237
+ </controller_action_postdispatch_adminhtml_cache_massRefresh>
238
+ </events>
239
+ </global>
240
+ <frontend>
241
+ <layout>
242
+ <updates>
243
+ <coscale_monitor>
244
+ <file>coscale_monitor.xml</file>
245
+ </coscale_monitor>
246
+ </updates>
247
+ </layout>
248
+ </frontend>
249
+ <default>
250
+ <coscale>
251
+ <general>
252
+ <maxruntime>1000</maxruntime>
253
+ </general>
254
+ </coscale>
255
+ <system>
256
+ <coscale_monitor>
257
+ <enabled>1</enabled>
258
+ <status_pickpack_pending>processing</status_pickpack_pending>
259
+ <status_pickpack>processing_pickpack</status_pickpack>
260
+ <status_pickpack_completed>processing_pickpack_done</status_pickpack_completed>
261
+ </coscale_monitor>
262
+ </system>
263
+ </default>
264
+
265
+ <crontab>
266
+ <jobs>
267
+ <coscale_daily_cron>
268
+ <schedule>
269
+ <cron_expr>0 0 * * *</cron_expr>
270
+ </schedule>
271
+ <run>
272
+ <model>coscale_monitor/cronjobs::dailyCron</model>
273
+ </run>
274
+ </coscale_daily_cron>
275
+ </jobs>
276
+ </crontab>
277
+ </config>
app/code/community/CoScale/Monitor/etc/system.xml ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <sections>
4
+ <system>
5
+ <groups>
6
+ <coscale_monitor>
7
+ <label>CoScale Monitoring</label>
8
+ <sort_order>200</sort_order>
9
+ <show_in_default>1</show_in_default>
10
+ <show_in_website>0</show_in_website>
11
+ <show_in_store>0</show_in_store>
12
+ <fields>
13
+ <enabled>
14
+ <label>Enabled</label>
15
+ <frontend_type>select</frontend_type>
16
+ <source_model>adminhtml/system_config_source_yesno</source_model>
17
+ <sort_order>1</sort_order>
18
+ <show_in_default>1</show_in_default>
19
+ <show_in_website>0</show_in_website>
20
+ <show_in_store>0</show_in_store>
21
+ </enabled>
22
+ <status_pickpack_pending>
23
+ <label>Status Pending Pickpack</label>
24
+ <frontend_type>select</frontend_type>
25
+ <source_model>adminhtml/system_config_source_order_status</source_model>
26
+ <depends><enabled>1</enabled></depends>
27
+ <sort_order>10</sort_order>
28
+ <show_in_default>1</show_in_default>
29
+ <show_in_website>0</show_in_website>
30
+ <show_in_store>0</show_in_store>
31
+ </status_pickpack_pending>
32
+ <status_pickpack>
33
+ <label>Status During Pickpack</label>
34
+ <frontend_type>select</frontend_type>
35
+ <source_model>adminhtml/system_config_source_order_status</source_model>
36
+ <depends><enabled>1</enabled></depends>
37
+ <sort_order>11</sort_order>
38
+ <show_in_default>1</show_in_default>
39
+ <show_in_website>0</show_in_website>
40
+ <show_in_store>0</show_in_store>
41
+ </status_pickpack>
42
+ <status_pickpack_completed>
43
+ <label>Status Completed Pickpack</label>
44
+ <frontend_type>select</frontend_type>
45
+ <source_model>adminhtml/system_config_source_order_status</source_model>
46
+ <depends><enabled>1</enabled></depends>
47
+ <sort_order>12</sort_order>
48
+ <show_in_default>1</show_in_default>
49
+ <show_in_website>0</show_in_website>
50
+ <show_in_store>0</show_in_store>
51
+ </status_pickpack_completed>
52
+ </fields>
53
+ </coscale_monitor>
54
+ </groups>
55
+ </system>
56
+ </sections>
57
+ </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.12.0</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="71ab08a030dc1bc6455f49f4851c7bd0"/><file name="system.xml" hash="42be2964b9a0099bbb368c2d2cc9b0d3"/></dir><dir name="Helper"><file name="Data.php" hash="5ae7702dabdad7dadfa33d807347a394"/></dir><dir name="Model"><file name="Cronjob.php" hash="2cece4bee12e728bf4693518d3d4c842"/><dir name="Event"><file name="Cache.php" hash="2109ac7d1cb9d6fd9315f7fb0f3a67b1"/><file name="Observer.php" hash="75c769f108c1fede613f251690c36ad0"/><file name="Reindex.php" hash="09f014e4c39c53f6269807f1a653eb08"/><file name="Store.php" hash="30322b55ffbbd3b56241ef3df38ca7d2"/></dir><file name="Event.php" hash="1071a8393fb9a435ccf4b2a39a8c2720"/><dir name="Metric"><file name="Abstract.php" hash="22bc047ea0a6e9c6ca3ac78bf002791b"/><file name="Customer.php" hash="791170ce6b6850966faa6003937b43fb"/><file name="File.php" hash="c1fef22000a768890023fa6d46fa4072"/><file name="Observer.php" hash="c12fb7f04d0a57e4f3213c1b3c4de7f0"/><file name="Order.php" hash="6ee825751b6cec5503cbbe39409b57dc"/><file name="Product.php" hash="b6cf5bfecb5f2d33a43f6d37eef74625"/><file name="Rewrite.php" hash="9da7e8f4c454a80a296f515e71230824"/><file name="System.php" hash="bdbf7ae7d1430e1bc8ded38ba9ed2f60"/></dir><file name="Metric.php" hash="33762b4367c9b0f98634fecd12ec0ee6"/><dir name="Output"><file name="Generator.php" hash="9cddf1ed8f2b43c17ee78bf6613f1fed"/></dir><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="cff356877c4d1eef57cfc686ee34bd8f"/></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,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ $helper = Mage::helper('coscale_monitor');
23
+
24
+ if (!$helper->isEnabled()) {
25
+ echo json_encode(array('error'=>'CoScale Module not active!'));
26
+ return;
27
+ }
28
+
29
+ if ($this->getArg('debug')) {
30
+ $helper->enableDebug();
31
+ }
32
+
33
+ // Generate output
34
+ try {
35
+ $helper->debugStart('Output Generation');
36
+ echo Mage::getSingleton('coscale_monitor/output_generator')->getJsonOutput();
37
+ $helper->debugEnd('Output Generation');
38
+ } catch (Exception $ex) {
39
+ $helper->debugEndError('Output Generation', $ex);
40
+ }
41
+ }
42
+ }
43
+
44
+ $shell = new CoScale_Shell();
45
+ $shell->run();