Просмотр исходного кода

#5460 Alerts logger: record last execution and timing for each record in sys_alerts_handlers

Aleksandr Trofimov 4 месяцев назад
Родитель
Сommit
136a07c79a

+ 2 - 1
inc/classes/BxDolAIQuery.php

@@ -959,7 +959,7 @@ class BxDolAIQuery extends BxDolDb
     public function getAlerts()
     public function getAlerts()
     {
     {
         $aValues = [];
         $aValues = [];
-        $aAlerts = $this->getAll("SELECT `unit`, `action`, `counter_24h` FROM `sys_alerts_log` ORDER BY `unit`, `action`");
+        $aAlerts = $this->getAll("SELECT `unit`, `action`, `counter_24h`, `counter_per_request` FROM `sys_alerts_log` ORDER BY `unit`, `action`");
         foreach ($aAlerts as $a) {
         foreach ($aAlerts as $a) {
             $sKey = $a['unit'] . ':' . $a['action'];
             $sKey = $a['unit'] . ':' . $a['action'];
             $aValues[$sKey] = [
             $aValues[$sKey] = [
@@ -969,6 +969,7 @@ class BxDolAIQuery extends BxDolDb
                 'name' => $a['unit'] . ' - ' . $a['action'],
                 'name' => $a['unit'] . ' - ' . $a['action'],
                 'desc' => $this->getAlertDesc($a['unit'] . ':' . $a['action']),
                 'desc' => $this->getAlertDesc($a['unit'] . ':' . $a['action']),
                 'counter_24h' => $a['counter_24h'],
                 'counter_24h' => $a['counter_24h'],
+                'counter_per_request' => $a['counter_per_request'],
             ];
             ];
         }
         }
         return $aValues;
         return $aValues;

+ 4 - 38
inc/classes/BxDolAlerts.php

@@ -112,6 +112,7 @@ class BxDolAlerts extends BxDol
 
 
                 if (isset($GLOBALS['bx_profiler']) && 'bx_profiler' != $aHandler['name']) 
                 if (isset($GLOBALS['bx_profiler']) && 'bx_profiler' != $aHandler['name']) 
                     $GLOBALS['bx_profiler']->beginAlert($this->sUnit, $this->sAction, $aHandler['name']);
                     $GLOBALS['bx_profiler']->beginAlert($this->sUnit, $this->sAction, $aHandler['name']);
+                $fStart = microtime(true);
 
 
                 if (!empty($aHandler['file']) && !empty($aHandler['class']) && file_exists(BX_DIRECTORY_PATH_ROOT . $aHandler['file'])) {
                 if (!empty($aHandler['file']) && !empty($aHandler['class']) && file_exists(BX_DIRECTORY_PATH_ROOT . $aHandler['file'])) {
                     if(!class_exists($aHandler['class'], false))
                     if(!class_exists($aHandler['class'], false))
@@ -128,7 +129,8 @@ class BxDolAlerts extends BxDol
 
 
                     BxDolService::call($aService['module'], $aService['method'], $aParams, isset($aService['class']) ? $aService['class'] : 'Module');
                     BxDolService::call($aService['module'], $aService['method'], $aParams, isset($aService['class']) ? $aService['class'] : 'Module');
                 }
                 }
-
+                
+                BxDolAlertsStats::hit($aHandler['name'], microtime(true) - $fStart);
                 if (isset($GLOBALS['bx_profiler']) && 'bx_profiler' != $aHandler['name']) 
                 if (isset($GLOBALS['bx_profiler']) && 'bx_profiler' != $aHandler['name']) 
                     $GLOBALS['bx_profiler']->endAlert($this->sUnit, $this->sAction, $aHandler['name']);
                     $GLOBALS['bx_profiler']->endAlert($this->sUnit, $this->sAction, $aHandler['name']);
             }
             }
@@ -146,7 +148,7 @@ class BxDolAlerts extends BxDol
         }
         }
 
 
         // log alert
         // log alert
-        $this->logAlert();
+        BxDolAlertsStats::log($this);
 
 
         // call agents
         // call agents
         $oAi = BxDolAI::getInstance();
         $oAi = BxDolAI::getInstance();
@@ -221,42 +223,6 @@ class BxDolAlerts extends BxDol
         return $aResult;
         return $aResult;
     }
     }
 
 
-    public function logAlert()
-    {
-        $oDb = BxDolDb::getInstance();
-        $aExtraRefs = [];
-        foreach($this->aExtras as $sKey => $mixedValue) {
-            if (preg_match('/^(ref|override|return)_/', $sKey) || preg_match('/_(ref|override|return)$/', $sKey) || $sKey == 'result' || $sKey == 'res' || $sKey == 'return' || $sKey == 'ret' || $sKey == 'check_result') {
-                $aExtraRefs[] = $sKey;
-            }
-        }
-        $aBind = [
-            'unit' => $this->sUnit,
-            'action' => $this->sAction,
-            'object' => $this->iObject,
-            'sender' => $this->iSender,
-            'extra' => json_encode($this->aExtras),
-            'extra_refs' => json_encode($aExtraRefs)
-        ];
-        $oDb->query("
-            INSERT INTO sys_alerts_log
-            SET
-                unit = :unit,
-                action = :action,
-                object = :object,
-                sender = :sender,
-                extra = :extra,
-                extra_refs = :extra_refs,
-                ts = UNIX_TIMESTAMP(),
-                counter_total = 1,
-                counter_24h = 1
-            ON DUPLICATE KEY UPDATE
-                ts = UNIX_TIMESTAMP(),
-                counter_total = counter_total + 1,
-                counter_24h = counter_24h + 1
-        ", $aBind);
-    }
-
     static public function resetAlertsCounter24h()
     static public function resetAlertsCounter24h()
     {
     {
         $oDb = BxDolDb::getInstance();
         $oDb = BxDolDb::getInstance();

+ 129 - 0
inc/classes/BxDolAlertsStats.php

@@ -0,0 +1,129 @@
+<?php defined('BX_DOL') or defined('BX_DOL_INSTALL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+
+class BxDolAlertsStats extends BxDol
+{
+    private static array $logs = [];
+    private static array $stats = [];
+    private static bool $registered = false;
+
+    public static function log(object $oAlert): void
+    {
+        if (!self::$registered) {
+            self::$registered = true;
+            register_shutdown_function([self::class, 'flush']);
+        }
+
+        $s = $oAlert->sUnit . ':' . $oAlert->sAction;
+        if (!isset(self::$logs[$s])) {
+            self::$logs[$s] = [
+                'unit' => $oAlert->sUnit,
+                'action' => $oAlert->sAction,
+                'object' => $oAlert->iObject,
+                'sender' => $oAlert->iSender,
+                'extra' => $oAlert->aExtras,
+                'counter' => 1,
+            ];
+        }
+        else {
+            self::$logs[$s]['counter']++;
+        }
+    }
+
+    public static function hit(string $hookName, float $timing): void
+    {
+        if (!self::$registered) {
+            self::$registered = true;
+            register_shutdown_function([self::class, 'flush']);
+        }
+
+        if (!isset(self::$stats[$hookName])) {
+            self::$stats[$hookName] = [
+                'count' => 0,
+                'last' => time(),
+                'timing' => $timing,
+            ];
+        }
+
+        self::$stats[$hookName]['count']++;
+        self::$stats[$hookName]['last'] = time();
+        self::$stats[$hookName]['timing'] += $timing;
+    }
+
+    public static function flush(): void
+    {
+        self::flushStats();
+        self::flushLogs();
+    }
+
+    public static function flushStats(): void
+    {
+        if (!self::$stats)
+            return;
+
+        foreach (self::$stats as $hookName => $data) {
+
+            $sql = "
+                UPDATE `sys_alerts_handlers`
+                SET
+                    `ts` = :last,
+                    `timing` = :timing,
+                    `call_count` = call_count + :count, 
+                    `calls_per_request` = GREATEST(`calls_per_request`, :count)
+                WHERE `name` = :name
+            ";
+
+            BxDolDb::getInstance()->query($sql, [
+                'count' => $data['count'],
+                'last' => $data['last'],
+                'timing' => $data['timing'],
+                'name' => $hookName,
+            ]);
+        }
+    }
+
+    public static function flushLogs(): void
+    {
+        if (!self::$logs)
+            return;
+
+        foreach (self::$logs as $s => $data) {
+            $aExtraRefs = [];
+            foreach($data['extra'] as $sKey => $mixedValue) {
+                if (preg_match('/^(ref|override|return)_/', $sKey) || preg_match('/_(ref|override|return)$/', $sKey) || $sKey == 'result' || $sKey == 'res' || $sKey == 'return' || $sKey == 'ret' || $sKey == 'check_result') {
+                    self::$logs[$s]['extra_refs'][] = $sKey;
+                }
+            }
+            self::$logs[$s]['extra_refs'] = json_encode(self::$logs[$s]['extra_refs'] ?? []);
+            self::$logs[$s]['extra'] = json_encode(self::$logs[$s]['extra']);
+
+            BxDolDb::getInstance()->query("
+                INSERT INTO sys_alerts_log
+                SET
+                    unit = :unit,
+                    action = :action,
+                    object = :object,
+                    sender = :sender,
+                    extra = :extra,
+                    extra_refs = :extra_refs,
+                    ts = UNIX_TIMESTAMP(),
+                    counter_total = :counter,
+                    counter_24h = :counter,
+                    counter_per_request = :counter
+                ON DUPLICATE KEY UPDATE
+                    ts = UNIX_TIMESTAMP(),
+                    counter_total = counter_total + :counter,
+                    counter_24h = counter_24h + :counter,
+                    counter_per_request = GREATEST(counter_per_request, :counter)
+            ", self::$logs[$s]);
+        }
+    }
+}
+
+/** @} */

+ 5 - 0
install/sql/system.sql

@@ -2222,6 +2222,10 @@ CREATE TABLE `sys_alerts_handlers` (
   `file` varchar(255) NOT NULL default '',
   `file` varchar(255) NOT NULL default '',
   `service_call` text NOT NULL default '', 
   `service_call` text NOT NULL default '', 
   `active` tinyint(4) NOT NULL default '1',
   `active` tinyint(4) NOT NULL default '1',
+  `ts` int(10) UNSIGNED NOT NULL,
+  `timing` float NOT NULL,
+  `call_count` int(10) UNSIGNED NOT NULL,
+  `calls_per_request` int(10) UNSIGNED NOT NULL,
   PRIMARY KEY  (`id`),
   PRIMARY KEY  (`id`),
   UNIQUE KEY `name` (`name`)
   UNIQUE KEY `name` (`name`)
 );
 );
@@ -2317,6 +2321,7 @@ CREATE TABLE `sys_alerts_log` (
   `ts` int(10) UNSIGNED NOT NULL,
   `ts` int(10) UNSIGNED NOT NULL,
   `counter_total` int(10) UNSIGNED NOT NULL,
   `counter_total` int(10) UNSIGNED NOT NULL,
   `counter_24h` int(10) UNSIGNED NOT NULL,
   `counter_24h` int(10) UNSIGNED NOT NULL,
+  `counter_per_request` int(10) UNSIGNED NOT NULL,
   PRIMARY KEY (`id`),
   PRIMARY KEY (`id`),
   UNIQUE KEY `unit_action` (`unit`,`action`)
   UNIQUE KEY `unit_action` (`unit`,`action`)
 );
 );

+ 1 - 0
modules/boonex/english/data/langs/system/en.xml

@@ -2289,6 +2289,7 @@
     <string name="_sys_agents_automators_btn_approve"><![CDATA[Approve]]></string>
     <string name="_sys_agents_automators_btn_approve"><![CDATA[Approve]]></string>
     <string name="_sys_agents_automators_popup_add"><![CDATA[Add automator]]></string>
     <string name="_sys_agents_automators_popup_add"><![CDATA[Add automator]]></string>
     <string name="_sys_agents_count_today"><![CDATA[{0} calls today]]></string>
     <string name="_sys_agents_count_today"><![CDATA[{0} calls today]]></string>
+    <string name="_sys_agents_count_per_req"><![CDATA[{0} calls per request]]></string>
     <string name="_sys_agents_popup_edit"><![CDATA[Edit automator]]></string>
     <string name="_sys_agents_popup_edit"><![CDATA[Edit automator]]></string>
     <string name="_sys_agents_field_name"><![CDATA[Name]]></string>
     <string name="_sys_agents_field_name"><![CDATA[Name]]></string>
     <string name="_sys_agents_field_name_info"><![CDATA[Uniq agent name]]></string>
     <string name="_sys_agents_field_name_info"><![CDATA[Uniq agent name]]></string>

+ 1 - 0
modules/boonex/russian/data/langs/system/ru.xml

@@ -2265,6 +2265,7 @@
         <string name="_sys_agents_automators_btn_approve"><![CDATA[Одобрить]]></string>
         <string name="_sys_agents_automators_btn_approve"><![CDATA[Одобрить]]></string>
         <string name="_sys_agents_automators_popup_add"><![CDATA[Добавить автоматизатор]]></string>
         <string name="_sys_agents_automators_popup_add"><![CDATA[Добавить автоматизатор]]></string>
         <string name="_sys_agents_count_today"><![CDATA[{0} вызовов сегодня]]></string>
         <string name="_sys_agents_count_today"><![CDATA[{0} вызовов сегодня]]></string>
+        <string name="_sys_agents_count_per_req"><![CDATA[{0} вызовов на запрос]]></string>
         <string name="_sys_agents_popup_edit"><![CDATA[Редактировать автоматизатор]]></string>
         <string name="_sys_agents_popup_edit"><![CDATA[Редактировать автоматизатор]]></string>
         <string name="_sys_agents_field_name"><![CDATA[Название]]></string>
         <string name="_sys_agents_field_name"><![CDATA[Название]]></string>
         <string name="_sys_agents_field_name_info"><![CDATA[Уникальное название агента.]]></string>
         <string name="_sys_agents_field_name_info"><![CDATA[Уникальное название агента.]]></string>

+ 7 - 2
studio/template/agents_agents_alerts_select.html

@@ -1,7 +1,7 @@
 <div id="bx-agents-agents-alert-cont" style="overflow:visible;">
 <div id="bx-agents-agents-alert-cont" style="overflow:visible;">
 <select id="bx-agents-agents-alert" name="alert" class="bx-def-font-inputs bx-form-input-select">
 <select id="bx-agents-agents-alert" name="alert" class="bx-def-font-inputs bx-form-input-select">
     <bx_repeat:alerts>
     <bx_repeat:alerts>
-        <option value="__value__" <bx_if:sel>__sel__</bx_if:sel> data-desc="__desc__" data-count="__count__">__name__</option>
+        <option value="__value__" <bx_if:sel>__sel__</bx_if:sel> data-desc="__desc__" data-count="__count__" data-count_per_req="__count_per_req__">__name__</option>
     </bx_repeat:alerts>
     </bx_repeat:alerts>
 </select>
 </select>
 </div>
 </div>
@@ -11,13 +11,18 @@
             return state.text;
             return state.text;
         const desc = $(state.element).data('desc');
         const desc = $(state.element).data('desc');
         const count = $(state.element).data('count');
         const count = $(state.element).data('count');
+        const count_per_req = $(state.element).data('count_per_req');
         return $(`
         return $(`
         <div class="bx-alert-wrap">
         <div class="bx-alert-wrap">
             <div>
             <div>
                 <div class="bx-alert-text">${state.text}</div>
                 <div class="bx-alert-text">${state.text}</div>
                 <div class="bx-alert-desc">${desc || ''}</div>
                 <div class="bx-alert-desc">${desc || ''}</div>
             </div>
             </div>
-            <div class="bx-alert-counter">${count}</div>
+            <div class="bx-alert-counter">
+                ${count}
+                <br />
+                ${count_per_req}
+            </div>
         </div>
         </div>
         `);
         `);
     }
     }

+ 3 - 0
studio/template/scripts/BxBaseStudioAgentsAgents.php

@@ -584,6 +584,8 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
                     'name' => _t('_sys_please_select'), 
                     'name' => _t('_sys_please_select'), 
                     'value' => '', 
                     'value' => '', 
                     'desc' => '', 
                     'desc' => '', 
+                    'count' => 0,
+                    'count_per_req' => 0,
                     'bx_if:sel' => [
                     'bx_if:sel' => [
                         'condition' => false,
                         'condition' => false,
                         'content' => ['sel' => '']
                         'content' => ['sel' => '']
@@ -597,6 +599,7 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
                 'value' => $r['key'],
                 'value' => $r['key'],
                 'desc' => bx_html_attribute($r['desc']),
                 'desc' => bx_html_attribute($r['desc']),
                 'count' => bx_html_attribute(_t('_sys_agents_count_today', $r['counter_24h'])),
                 'count' => bx_html_attribute(_t('_sys_agents_count_today', $r['counter_24h'])),
+                'count_per_req' => bx_html_attribute(_t('_sys_agents_count_per_req', $r['counter_per_request'])),
                 'bx_if:sel' => [
                 'bx_if:sel' => [
                     'condition' => $sValue == $r['key'],
                     'condition' => $sValue == $r['key'],
                     'content' => [
                     'content' => [