/components/Logger.php
PHP | 395 lines | 299 code | 39 blank | 57 comment | 26 complexity | 6a2de07261c07edd925ef9d6423e77e2 MD5 | raw file
- <?php
- namespace nitm\components;
- use yii\base\Model;
- use yii\helpers\ArrayHelper;
- use nitm\helpers\Session;
- use nitm\helpers\Network;
- class Logger extends \yii\log\Logger
- {
- use \nitm\traits\EventTraits;
- //constant data
- const LT_FILE = 'file';
- const LT_DB = 'db';
- const LT_MONGO = 'mongo';
- //public data
- public $db;
- public $targets;
- public $level = 'notice';
- public $traceLevel = 1;
- public $dbName;
- public $collectionName = 'no-log-selected';
- public $categories = [];
- public $oldCollectionName;
- public $type;
- public $currentUser;
- //For Logger events
- const EVENT_START = 'nitm.logger.prepare';
- const EVENT_PROCESS = 'nitm.logger.process';
- const EVENT_END = 'nitm.logger.end';
- public function init()
- {
- parent::init();
- $this->currentUser = (\Yii::$app->hasProperty('user') && \Yii::$app->user->getId()) ? \Yii::$app->user->getIdentity() : new \nitm\models\User(['username' => (php_sapi_name() == 'cli' ? 'console' : 'web')]);
- if(!$this->dispatcher instanceof \yii\log\Dispatcher) {
- $this->initDispatcher();
- }
- $this->attachToEvents([
- self::EVENT_START => [$this, 'prepare'],
- self::EVENT_PROCESS => [$this, 'process'],
- self::EVENT_END => [$this, 'flush']
- ]);
- }
- public function initTarget($refresh=false)
- {
- switch($this->type)
- {
- case self::LT_MONGO:
- $class = log\MongoTarget::className();
- break;
- case self::LT_DB:
- $class = log\DbTarget::className();
- break;
- default:
- $class = log\FileTarget::className();
- break;
- }
- $options = [
- 'class' => $class,
- 'levels' => 0,
- 'enabled' => true,
- 'categories' => $this->categories
- ];
- if($this->db && !empty($this->db))
- $options += ArrayHelper::toArray($this->db);
- return \Yii::createObject($options);
- }
- public function initDispatcher()
- {
- if(\Yii::$app->get('log') && is_array($this->dispatcher) && isset($this->dispatcher['targets'])) {
- $targets = array_map(function ($config) {
- return \Yii::createObject($config);
- }, $this->dispatcher['targets']);
- $this->dispatcher = \Yii::$app->log;
- $this->dispatcher->targets = $targets;
- \Yii::$app->log->targets = array_merge(\Yii::$app->log->targets, $targets);
- } else {
- if(is_array($this->dispatcher))
- {
- $this->dispatcher = \Yii::createObject(array_merge([
- 'class' => '\yii\log\Dispatcher'
- ], ArrayHelper::toArray($this->dispatcher)));
- }
- else {
- $this->dispatcher = \Yii::$app->log;
- }
- $thisTarget = $this->initTarget();
- $this->targets = [
- 'nitm-'.$this->type.'-log' => $thisTarget
- ];
- foreach($this->dispatcher->targets as $target) {
- $target->except = array_merge((array)$target->except, $thisTarget->categories);
- }
- $this->dispatcher->targets = array_merge(\Yii::$app->log->targets, $this->targets);
- }
- return $this;
- }
- /**
- * Temporarily change the collection name
- * @param string $newName
- */
- public function changeCollectionName($newName=null)
- {
- if(is_null($newName)) {
- $this->collectionName = $this->oldCollectionName;
- $this->oldCollectionName = null;
- }
- else {
- $this->oldCollectionName = $this->collectionName;
- $this->collectionName = $newName;
- }
- foreach($this->dispatcher->targets as $target)
- $target->logTable = $this->collectionName;
- }
- //- end write
- /**
- * Prepare a log event
- */
- public function prepare($event) {
- return false;
- }
- /**
- * Proces a log event
- * @param \yii\base\Event $event
- * @return boolean
- */
- public function process($event)
- {
- if($event->hasProperty('result')) {
- $event->data = $event->result;
- }
- $action = $event->sender->getScenario();
- if(!$this->canLog(ArrayHelper::getValue($event->data, 'level', null)))
- return;
- try {
- $changedAttributes = $event->sender->changedAttributes;
- } catch(\Exception $e) {
- $changedAttributes = '';
- }
- $event->data = array_merge([
- 'internal_category' => $this->getCategoryText(ArrayHelper::getValue($event->data, 'internal_category', null), $event->sender->getScenario()),
- 'level' => $this->getlevel($event->sender->getScenario()),
- 'category' => $this->getCategory(ArrayHelper::getValue($event->data, 'category', null), $event->sender->getScenario()),
- 'action' => \Yii::$app->getModule('nitm')->getAlert()->store()->getStoredAction($event),
- 'timestamp' => microtime(true),
- 'table_name' => $event->sender->isWhat(),
- 'message' => implode(' ', [
- "Succesfully {$action}d",
- $event->sender->isWhat(),
- ':'.$event->sender->title()."[".$event->sender->getId()."]\n\nChanged values: \n".json_encode($changedAttributes, JSON_PRETTY_PRINT)
- ])
- ], (array)$event->data);
- $event->handled = $this->log($event->data, $event->data['level'], $event->data['category'], ArrayHelper::remove($event->data, 'collectionName', null));
- return $event->handled;
- }
- public function getLevels() {
- return [
- 'log',
- 'debug',
- 'info',
- 'notice',
- 'warning',
- 'error',
- 'critical',
- 'alert',
- 'emergency',
- ];
- }
- public function levelName($level) {
- return ArrayHelper::getValue($this->levels, $this->getLevel($level), 'log');
- }
- public function getLevel($level) {
- if(is_numeric($level)) {
- return $level >= 0 && $level < count($this->levels) ? $level : 0;
- } else {
- return array_search(strtolower($level), $this->levels);
- }
- }
- /**
- * Base on the provided scenario determine a log level
- * @param string $scenario The model scenario
- * levels
- * 0: log,
- * 1: debug,
- * 2: info,
- * 3: notice,
- * 4: warning,
- * 5: error,
- * 6: critical,
- * 7: alert,
- * 8: emergency,
- * @return int The log level based on scneario
- */
- protected function getScenarioLevel($scenario)
- {
- $ret_val = 0;
- switch($scenario)
- {
- case 'create':
- case 'delete':
- $ret_val = 3;
- break;
- case 'disable':
- case 'resolve':
- case 'close':
- case 'complete':
- case 'approve':
- case 'update':
- $ret_val = 0;
- break;
- case 'view':
- $ret_val = 2;
- break;
- }
- return $ret_val;
- }
- protected function getCategoryText($category=null, $scenario=null)
- {
- switch($scenario)
- {
- case 'view':
- $ret_val = 'User Activity';
- break;
- default:
- $ret_val = is_null($category) ? 'User Action' : $category;
- break;
- }
- return $ret_val;
- }
- /**
- * @param string $category
- * @param string $scenario
- * @return string
- */
- protected function getCategory($category=null, $scenario=null)
- {
- switch($scenario)
- {
- case 'view':
- $ret_val = 'user-ctivity';
- break;
- default:
- $ret_val = is_null($category) ? 'user-action' : $category;
- break;
- }
- return $ret_val;
- }
- protected function getAction($action=null)
- {
- $ret_val = $action;
- return $ret_val;
- }
- /**
- * Log data
- * @param array $array
- * @param string $collectionName
- * @return Logger $this
- */
- public function log($array, $level, $category='application', $collectionName=null)
- {
- if(is_array($array) && $array != [])
- {
- $array['category'] = ArrayHelper::getValue($array, 'category', $category);
- $keys = array_flip([
- 'message', 'level', 'category', 'timestamp'
- ]);
- $coreInfo = array_values(array_replace($keys, array_intersect_key((array)$array, $keys)));
- $coreInfo = array_merge($coreInfo, [$this->traces, memory_get_usage()]);
- $array = array_merge($coreInfo,
- $this->getBaseInfo(),
- (array)array_diff_key((array)$array, $keys),
- $this->getExtraInfo());
- $array[1] = $this->getLevel($array[1]);
- $array['action'] = $this->getAction($array['action']);
- if(is_string($collectionName))
- $this->messages[$collectionName.':'.uniqid()] = $array;
- else
- $this->messages[] = $array;
- }
- return $this;
- }
- protected function getTraces() {
- $traces = [];
- if ($this->traceLevel > 0) {
- $count = 0;
- $ts = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
- array_pop($ts); // remove the last trace since it would be the entry script, not very useful
- foreach ($ts as $trace) {
- if (isset($trace['file'], $trace['line']) && strpos($trace['file'], YII2_PATH) !== 0) {
- unset($trace['object'], $trace['args']);
- $traces[] = $trace;
- if (++$count >= $this->traceLevel) {
- break;
- }
- }
- }
- }
- return $traces;
- }
- //end fucntion
- /**
- * Determine whether this level is loggable
- * @param int $level
- * @return boolean the data can be stored for logging
- */
- public function canLog($level=null)
- {
- return $level <= $this->threshold;
- }
- protected function getThreshold() {
- return $this->getLevel($this->level);
- }
- /**
- * Return some general log info
- * @return array
- */
- protected function getBaseInfo()
- {
- return [
- 'action' => 'log',
- 'db_name' => \nitm\models\DB::getDefaultDbName(),
- 'table_name' => 'logger',
- 'user' => $this->currentUser->username,
- 'user_id' => (int)$this->currentUser->getId(),
- 'prefix' => $this->collectionName,
- 'log_time' => strtotime('now'),
- 'response_status_code' => \Yii::$app->response->statusCode,
- 'response_status_text' => \Yii::$app->response->statusText,
- 'response_headers' => json_encode(\Yii::$app->response->headers->toArray()),
- 'response_data' => json_encode(\Yii::$app->response->data),
- 'request_headers' => json_encode(\Yii::$app->request->headers->toArray()),
- 'request_data' => json_encode(\Yii::$app->request->bodyParams),
- 'error_level' => 0,
- ];
- }
- /**
- * Return some general log info
- * @return array
- */
- protected function getExtraInfo()
- {
- $parser = (\UAParser\Parser::create());
- $r = $parser->parse(!\Yii::$app->request->userAgent ? $_SERVER['SERVER_SOFTWARE'] : \Yii::$app->request->userAgent);
- return [
- 'ua_family' => $r->ua->family,
- 'ua_version' => implode('.', array_filter([$r->ua->major, $r->ua->minor])).($r->ua->patch ? '-'.$r->ua->patch : ''),
- 'os_family' => $r->os->family,
- 'os_version' => implode('.', array_filter([$r->os->major, $r->os->minor])).($r->os->patch ? '-'.$r->os->patch : ''),
- 'device_family' => $r->device->family,
- 'request_method' => \Yii::$app->request->method,
- 'user_agent' => \Yii::$app->request->userAgent,
- 'ip_addr' => !\Yii::$app->request->userIp ? 'localhost' : \Yii::$app->request->userIp,
- 'host' => !\Yii::$app->request->userHost ? 'localhost' : \Yii::$app->request->userHost,
- ];
- }
- }
- // end log class
- ?>