1: <?php
2:
3: namespace Alpha\Util\Logging;
4:
5: use Alpha\Model\Type\Timestamp;
6: use Alpha\Model\Type\String;
7: use Alpha\Util\Helper\Validator;
8: use Alpha\Util\Config\ConfigProvider;
9: use Alpha\Util\Http\Session\SessionProviderFactory;
10:
11: /**
12: * A Key Performance Indicator (KPI) logging class.
13: *
14: * @since 1.1
15: *
16: * @author John Collins <dev@alphaframework.org>
17: * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
18: * @copyright Copyright (c) 2015, John Collins (founder of Alpha Framework).
19: * All rights reserved.
20: *
21: * <pre>
22: * Redistribution and use in source and binary forms, with or
23: * without modification, are permitted provided that the
24: * following conditions are met:
25: *
26: * * Redistributions of source code must retain the above
27: * copyright notice, this list of conditions and the
28: * following disclaimer.
29: * * Redistributions in binary form must reproduce the above
30: * copyright notice, this list of conditions and the
31: * following disclaimer in the documentation and/or other
32: * materials provided with the distribution.
33: * * Neither the name of the Alpha Framework nor the names
34: * of its contributors may be used to endorse or promote
35: * products derived from this software without specific
36: * prior written permission.
37: *
38: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
39: * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
40: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
41: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42: * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
43: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
48: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
49: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51: * </pre>
52: */
53: class KPI
54: {
55: /**
56: * The date/time of the KPI event.
57: *
58: * @var Alpha\Model\Type\Timestamp
59: *
60: * @since 1.1
61: */
62: private $timeStamp;
63:
64: /**
65: * The name of the KPI.
66: *
67: * @var Alpha\Model\Type\String
68: *
69: * @since 1.1
70: */
71: private $name;
72:
73: /**
74: * The session ID of the current HTTP session.
75: *
76: * @var string
77: *
78: * @since 1.1
79: */
80: private $sessionID;
81:
82: /**
83: * The start time of the KPI event (UNIX timestamp in seconds).
84: *
85: * @var float
86: *
87: * @since 1.1
88: */
89: private $startTime;
90:
91: /**
92: * The end time of the KPI event (UNIX timestamp in seconds).
93: *
94: * @var float
95: *
96: * @since 1.1
97: */
98: private $endTime;
99:
100: /**
101: * The duration in seconds.
102: *
103: * @var float
104: *
105: * @since 1.1
106: */
107: private $duration;
108:
109: /**
110: * Constructor.
111: *
112: * @param string $name The name of the KPI which is used in the log files, must only be letters and/or numbers.
113: *
114: * @throws Alpha\Exception\IllegalArguementException
115: *
116: * @since 1.1
117: */
118: public function __construct($name)
119: {
120: $config = ConfigProvider::getInstance();
121:
122: $this->name = new String();
123: $this->name->setRule(Validator::REQUIRED_ALPHA_NUMERIC);
124: $this->name->setHelper('The KPI name can only contain letters and numbers');
125:
126: $this->name->setValue($name);
127:
128: $this->timeStamp = new Timestamp(date('Y-m-d H:i:s'));
129:
130: $this->startTime = microtime(true);
131:
132: $sessionProvider = $config->get('session.provider.name');
133: $session = SessionProviderFactory::getInstance($sessionProvider);
134:
135: // a startTime value may have been passed from a previous request
136: if ($session->get($name.'-startTime') !== false) {
137: $this->startTime = $session->get($name.'-startTime');
138: $session->delete($name.'-startTime');
139: }
140:
141: $this->sessionID = $session->getID();
142: }
143:
144: /**
145: * Stores the current startTime for the KPI in the session, useful for multi-request KPI tracking.
146: *
147: * @since 1.0
148: */
149: public function storeStartTimeInSession()
150: {
151: $config = ConfigProvider::getInstance();
152: $sessionProvider = $config->get('session.provider.name');
153: $session = SessionProviderFactory::getInstance($sessionProvider);
154:
155: $session->set($this->name->getValue().'-startTime', $this->startTime);
156: }
157:
158: /**
159: * Writes the KPI event to a log file named logs/kpi-'.$this->name->getValue().'.csv, which will be created if it does
160: * not exist.
161: *
162: * @since 1.1
163: */
164: public function log()
165: {
166: $config = ConfigProvider::getInstance();
167:
168: $this->endTime = microtime(true);
169:
170: $this->duration = $this->endTime - $this->startTime;
171:
172: $logfile = new LogProviderFile();
173: $logfile->setPath($config->get('app.file.store.dir').'logs/kpi-'.$this->name->getValue().'.csv');
174:
175: $logfile->setMaxSize($config->get('app.log.file.max.size'));
176:
177: $logfile->writeLine(array($this->timeStamp, $this->name->getValue(), $this->sessionID, $this->startTime, $this->endTime, $this->duration));
178: }
179:
180: /**
181: * Writes a step in the KPI event to a log file named logs/kpi-'.$this->name->getValue().'.csv, which will be created if it does
182: * not exist.
183: *
184: * @since 1.1
185: */
186: public function logStep($stepName)
187: {
188: $config = ConfigProvider::getInstance();
189:
190: $this->endTime = microtime(true);
191:
192: $this->duration = $this->endTime - $this->startTime;
193:
194: $logfile = new LogProviderFile();
195: $logfile->setPath($config->get('app.file.store.dir').'logs/kpi-'.$this->name->getValue().'.csv');
196:
197: $logfile->setMaxSize($config->get('app.log.file.max.size'));
198:
199: $logfile->writeLine(array($this->timeStamp, $this->name->getValue().' ['.$stepName.']', $this->sessionID, $this->startTime, $this->endTime, $this->duration));
200: }
201: }
202: