Procházet zdrojové kódy

added Debug, DBG::log

Piotr Labudda před 9 roky
rodič
revize
f1829a0843
2 změnil soubory, kde provedl 394 přidání a 0 odebrání
  1. 54 0
      SE/se-lib/DBG.php
  2. 340 0
      SE/se-lib/Route/Debug.php

+ 54 - 0
SE/se-lib/DBG.php

@@ -1,5 +1,7 @@
 <?php
 
+Lib::loadClass('User');
+
 class DBG {
 
 	public static function isActive($mode = null) {
@@ -123,4 +125,56 @@ class DBG {
 		echo '<pre style="background-color:'.$col['bg-dark'].'; color:'.$col['white'].'; font-size:x-small">' . $outLines . '</pre>' . "\n";
 	}
 
+	/**
+	 * @param $mixedArg string or Exception
+	 */
+	public static function log($mixedArg) {
+		if (!self::isActive()) return;
+		// * TODO: debug to file based on session_id (/tmp/se-debug-{$date("Y-m-d")}-{$login}_{$ip}_{$session_id}.log)
+		$logInfo = [
+			'date' => date("Y-m-d H:i:s"),
+			'type' => 'unknown',
+			'msg' => '',
+			'log' => '',
+			'trace' => '',
+		];
+		if ($mixedArg instanceof Exception) {
+			$logInfo['type'] = 'Exception';
+			$logInfo['msg'] = $mixedArg->getMessage();
+			$logInfo['log'] = [
+				'code' => $mixedArg->getCode(),
+				'line' => $mixedArg->getLine(),
+				'file' => str_replace(APP_PATH_ROOT, 'SE', $mixedArg->getFile()),
+			];
+			$logInfo['trace'] = $mixedArg->getTraceAsString();// getTrace
+		} else if (is_string($mixedArg)) {
+			$logInfo['type'] = 'string';
+			$logInfo['msg'] = $mixedArg;
+			$logInfo['log'] = array();
+			ob_start();
+			debug_print_backtrace();
+			$logInfo['trace'] = ob_get_clean();
+		} else if (is_array($mixedArg)) {
+			$logInfo['type'] = 'array';
+			$logInfo['msg'] = V::get('msg', '', $mixedArg);
+			$logInfo['log'] = $mixedArg;
+			ob_start();
+			debug_print_backtrace();
+			$logInfo['trace'] = ob_get_clean();
+		}
+		$logInfo['trace'] = str_replace(APP_PATH_ROOT, 'SE', $logInfo['trace']);
+		$logInfo['trace'] .= (("\n" == substr($logInfo['trace'], -1)) ? '' :  "\n") . "URI: " . V::get('REQUEST_URI', '', $_SERVER);
+		error_log(
+			json_encode($logInfo) . "\n"
+			, 3
+			, '/tmp/se-debug-' . implode('-', [
+				date("Y-m-d"),
+				User::getLogin(),
+				Request::getUserIp(),
+				substr(session_id(), 0, 6),
+				V::get('REQUEST_TIME', '', $_SERVER)// [REQUEST_TIME] => 1485770466
+			]) . '.log'
+		);
+	}
+
 }

+ 340 - 0
SE/se-lib/Route/Debug.php

@@ -0,0 +1,340 @@
+<?php
+
+Lib::loadClass('RouteBase');
+
+/**
+ * TODO: debug to file based on session_id (/tmp/se-debug-{$date("Y-m-d")}-{$login}_{$ip}_{$session_id}.log)
+ * TODO: function if loggind enabled, then save to file and print in default page
+ *       - DBG::log(string $msg or Exception $e)
+ * TODO: better wfs log by fingerprint (User::getLogin() + IP + UserAgent)
+ */
+class Route_Debug extends RouteBase {
+
+  public function handleAuth() {
+		if (!User::logged()) {
+      throw new HttpException('Unauthorized', 401);
+		}
+		if (!User::hasAccess('dbg')) {// User::get('ADM_ADMIN_LEVEL') == 0
+      throw new HttpException('Unauthorized - required dbg access', 401);
+		}
+	}
+
+  public function defaultAction() {
+    session_write_close();
+    $this->defaultView();
+  }
+
+  public function defaultView($flashMsg = '') {
+		UI::gora();
+		UI::menu();
+    try {
+      echo UI::h('h1', [], [
+        "Debug ",
+        UI::h('small', [], "(" . (DBG::isActive() ? "włączony" : "wyłączony") . ") "),
+        UI::hButtonPost((DBG::isActive()) ? "Wyłącz debug" : "Włącz debug", [
+          'class' => "btn-success btn-xs",
+          'data' => [
+            '_route' => 'Debug',
+            '_task' => DBG::isActive() ? 'deactivateDebug' : 'activateDebug'
+          ]
+        ])
+      ]);
+      echo $flashMsg;
+
+      // DBG::nicePrint($_SERVER, '$_SERVER');
+      // DBG::nicePrint([
+      //   'date' => date("Y-m-d"),
+      //   'login' => User::getLogin(),
+      //   'ip' => Request::getUserIp(),
+      //   'session_id' => session_id()
+      // ], 'dbg');
+
+      UI::table([
+        'caption' => "Log Files " . UI::h('a', [
+          'href' => "index.php?_route=Debug&_task=viewLatestUserLog",
+          'class' => "btn btn-xs btn-primary"
+        ], "pokaż ostatni") . " " . UI::hButtonPost("Remove all log files", [
+          'class' => "btn-danger btn-xs",
+          'data' => [
+            '_route' => 'Debug',
+            '_task' => 'rmAllLogFiles'
+          ]
+        ]) . " " . UI::hButtonPost("Remove old log files", [
+          'class' => "btn-warning btn-xs",
+          'data' => [
+            '_route' => 'Debug',
+            '_task' => 'rmOldLogFiles'
+          ]
+        ]),
+        'cols' => [
+          '#',
+          'file',
+          'user',
+          'request date',
+          'ip',
+          'rm',
+        ],
+        'rows' => array_map(
+          function ($logFile) {
+            // /tmp/se-debug-2017-01-25-plabudda-192.168.61.206-4qqrd0.log
+            try {
+              if ('/tmp/se-debug-' != substr($logFile, 0, strlen('/tmp/se-debug-'))) throw new Exception("Wrong log file name '{$logFile}'");
+              if ('.log' != substr($logFile, -4)) throw new Exception("Wrong log file name extension '{$logFile}'");
+              $logName = substr($logFile, strlen('/tmp/se-debug-'), -4);
+              list($logYear, $logMonth, $logDay, $logUser, $logIP, $logSessId, $logReqDate) = explode('-', $logName);
+
+              return [
+                '#' => UI::h('a', [
+                  'href' => "index.php?_route=Debug&_task=viewLog&name={$logName}"
+                ], "Pokaż"),
+                'request date' => ($logReqDate) ? date("Y-m-d H:i:s", $logReqDate) : '',// 1485775975
+                'file' => $logFile,
+                'user' => $logUser,
+                'ip' => $logIP,
+                'rm' => UI::hButtonPost("Usuń", [
+                  'data' => [
+                    '_route' => 'Debug',
+                    '_task' => 'rmLogFile',
+                    'logName' => $logName
+                  ]
+                ]),
+              ];
+            } catch (Exception $e) {
+              return [
+                '#' => '',
+                'file' => $e->getMessage(),
+              ];
+            }
+          }
+          , glob("/tmp/se-debug-*.log", GLOB_NOSORT)
+        )
+      ]);
+
+      echo UI::hButtonPost("Test dbg with sleep", [
+        'class' => "btn-warning btn-xs",
+        'data' => [
+          '_route' => 'Debug',
+          '_task' => 'testDebugWithSleep'
+        ]
+      ]);
+
+    } catch (Exception $e) {
+      UI::alert('danger', $e->getMessage());
+      DBG::log($e);
+    }
+    UI::dol();
+  }
+
+  public function viewLatestUserLogAction() {
+    session_write_close();
+    UI::gora();
+    // UI::menu();
+    echo UI::h('div', ['class'=>'container'], [
+      UI::h('a', ['href'=>'index.php?_route=DEBUG'], "wróć")
+    ]);
+    try {
+      $filerUser = V::get('user', '', $_REQUEST);// TODO: show another user debug
+      $logName = V::get('name', '', $_REQUEST);
+      if (!$logName) {
+        $today = date("Y-m-d");
+        $cmd = "ls -1rt /tmp/se-debug-{$today}-*.log | tail -5";
+        V::exec($cmd, $out, $ret);
+        if (empty($out)) {
+          UI::alert('warning', "No logs today. Searching previous...");
+          $cmd = "ls -1rt /tmp/se-debug-*.log | tail -5";
+          V::exec($cmd, $out, $ret);
+          if (empty($out)) throw new Exception("Log files not found");
+        }
+        echo UI::h('div', ['class'=>"alert alert-info"], [
+          "Last log files",
+          " (return code: {$ret})",
+          "<br>cmd: <code>{$cmd}</code>",
+          UI::h('pre', [], implode("\n", $out))
+        ]);
+        $logName = end($out);// /tmp/se-debug-2017-01-30-plabudda-192.168.61.206-4qqrd0-1485775975.log
+        {
+          if ('/tmp/se-debug-' != substr($logName, 0, strlen('/tmp/se-debug-'))) throw new Exception("Wrong log name prefix");
+          if ('.log' != substr($logName, -1 * strlen('.log'))) throw new Exception("Wrong log name suffix");
+          $logName = substr($logName, strlen('/tmp/se-debug-'), -1 * strlen('.log'));
+        }
+      }
+      $this->printLogFileView($logName);
+    } catch (Exception $e) {
+      UI::alert('danger', $e->getMessage());
+    }
+    UI::dol();
+  }
+  public function viewLogAction() {
+    session_write_close();
+    UI::gora();
+    // UI::menu();
+    echo UI::h('div', ['class'=>'container'], [
+      UI::h('a', ['href'=>'index.php?_route=DEBUG'], "wróć")
+    ]);
+    try {
+      $logName = V::get('name', '', $_REQUEST);
+      $this->printLogFileView($logName);
+    } catch (Exception $e) {
+      UI::alert('danger', $e->getMessage());
+    }
+    UI::dol();
+  }
+  public function printLogFileView($logName) {
+    if (empty($logName)) throw new Exception("Missing name");
+    $logName = $this->validateParamLogName($logName);
+    $logPath = "/tmp/se-debug-{$logName}.log";
+    if (!file_exists($logPath)) throw new Exception("Log file not exists");
+    $content = file_get_contents($logPath);
+    UI::table([
+      'cols' => [
+        'date',
+        'type',
+        'msg',
+        'log',
+        'trace',
+      ],
+      'cols_help' => [
+        'trace' => "Cick to show trace"
+      ],
+      'rows' => array_map(
+        function ($line) {
+          if (empty($line)) return [];
+          $dbg = @json_decode($line, $assoc = true);
+          if (null == $dbg && 0 !== json_last_error()) {
+            return [
+              'type' => 'decode json error',
+              'msg' => "Error Processing Request - Parse json error: " . json_last_error()
+            ];
+          }
+          return [
+            'date' => '<nobr>' . $dbg['date'] . '</nobr>',
+            'type' => $dbg['type'],
+            'msg' => $dbg['msg'],
+            // 'log' => (!empty($dbg['log'])) ? json_encode($dbg['log']) : '',
+            'log' => UI::h('div', [
+                'title' => htmlspecialchars(var_export($dbg['log'], true)),
+                'onClick' => "return p5DBG__showLogTrace(this, event)",
+                'style' => "cursor:pointer"
+              ], substr(htmlspecialchars(json_encode($dbg['log'])), 0, 100) . ' ...'
+            ),
+            'trace' => UI::h('div', [
+                'title' => htmlspecialchars($dbg['trace']),
+                'onClick' => "return p5DBG__showLogTrace(this, event)",
+                'style' => "cursor:pointer"
+              ], ('Exception' == $dbg['type'])
+                ? "Code: {$dbg['log']['code']}, File: {$dbg['log']['file']}"
+                : '...'
+            ),
+          ];
+        },
+        explode("\n", $content)
+      ),
+    ]);
+    echo UI::h('script', [], "
+      function p5DBG__showLogTrace(n, e) {
+        if (!e) return false;
+        if (e.target && 'PRE' == e.target.tagName) return false;
+        if (n.lastChild.tagName == 'PRE') {
+          if ('none' == n.lastChild.style.display) {
+            n.lastChild.style.display = 'block'
+          } else {
+            n.lastChild.style.display = 'none'
+          }
+        } else {
+          var pre = document.createElement('pre')
+          pre.appendChild( document.createTextNode(n.title) )
+          n.appendChild(pre)
+        }
+      }
+    ");
+  }
+
+  public function activateDebugAction() {
+    DBG::activate();
+    $this->defaultView();
+  }
+
+  public function deactivateDebugAction() {
+    DBG::deactivate();
+    $this->defaultView();
+  }
+
+  public function testDebugWithSleepAction() {
+    session_write_close();
+    UI::gora();
+    flush();
+    for ($i = 0; $i < 10; $i++) {
+      echo "TEST {$i}<br>";
+      DBG::log("TEST {$i}");
+      flush();
+      sleep(2);
+    }
+    echo "DONE";
+    DBG::log("DONE");
+    UI::dol();
+  }
+
+  public function validateParamLogName($logName) {
+    if (empty($logName)) throw new Exception("Missing log file name");
+    if (!preg_match('/^[\-\.a-zA-Z0-9]+$/', $logName)) throw new Exception("Wrong log file name format");
+    return $logName;
+  }
+
+  public function rmAllLogFilesAction() {
+    session_write_close();
+    try {
+      $today = date("Y-m-d");
+      $cmd = "rm -v /tmp/se-debug-*.log 2>&1";
+      V::exec($cmd, $out, $ret);
+      $this->defaultView(UI::h('div', ['class'=>"alert alert-success"], [
+        (0 === $ret) ? "All Log Files Removed" : "Error?",
+        " (return code: {$ret})",
+        "<br>cmd: <code>{$cmd}</code>",
+        UI::h('pre', [], implode("\n", $out))
+      ]));
+    } catch (AlertSuccessException $e) {
+      $this->defaultView(UI::h('div', ['class'=>"alert alert-success"], $e->getMessage()));
+    } catch (AlertWarningException $e) {
+      $this->defaultView(UI::h('div', ['class'=>"alert alert-warning"], $e->getMessage()));
+    } catch (Exception $e) {
+      $this->defaultView(UI::h('div', ['class'=>"alert alert-danger"], $e->getMessage()));
+    }
+  }
+  public function rmOldLogFilesAction() {
+    session_write_close();
+    try {
+      $today = date("Y-m-d");
+      $cmd = "ls -1 /tmp/se-debug-*.log | grep -v '/tmp/se-debug-{$today}-' | xargs rm -v 2>&1";
+      V::exec($cmd, $out, $ret);
+      $this->defaultView(UI::h('div', ['class'=>"alert alert-success"], [
+        (0 === $ret) ? "Old Log Files Removed" : "Error?",
+        " (return code: {$ret})",
+        "<br>cmd: <code>{$cmd}</code>",
+        UI::h('pre', [], implode("\n", $out))
+      ]));
+    } catch (AlertSuccessException $e) {
+      $this->defaultView(UI::h('div', ['class'=>"alert alert-success"], $e->getMessage()));
+    } catch (AlertWarningException $e) {
+      $this->defaultView(UI::h('div', ['class'=>"alert alert-warning"], $e->getMessage()));
+    } catch (Exception $e) {
+      $this->defaultView(UI::h('div', ['class'=>"alert alert-danger"], $e->getMessage()));
+    }
+  }
+  public function rmLogFileAction() {
+    session_write_close();
+    try {
+      $logName = $this->validateParamLogName(V::get('logName', '', $_REQUEST));
+      $logPath = "/tmp/se-debug-{$logName}.log";
+      if (!file_exists($logPath)) throw new AlertWarningException("Log file not exists");
+      unlink($logPath);
+      throw new AlertSuccessException("File Removed");
+    } catch (AlertSuccessException $e) {
+      $this->defaultView(UI::h('div', ['class'=>"alert alert-success"], $e->getMessage()));
+    } catch (AlertWarningException $e) {
+      $this->defaultView(UI::h('div', ['class'=>"alert alert-warning"], $e->getMessage()));
+    } catch (Exception $e) {
+      $this->defaultView(UI::h('div', ['class'=>"alert alert-danger"], $e->getMessage()));
+    }
+  }
+
+}