当前位置: 首页 > 面试题库 >

顺利记录错误

苏昊英
2023-03-14
问题内容

我一直在阅读“错误日志记录”,并且想出了“ error_log”函数,它似乎是处理错误日志记录的好工具。但是,最流畅和最佳的使用方式是什么?

如果我有一个

try {
     //try a database connection...

} catch (PDOException $e) {
    error_log($e->getMessage(), 3, "/var/tmp/my-errors.log");

}

这会将错误记录在my-errors.log文件中。但是,如果我有时需要更改文件位置,新文件夹或其他内容的位置,该怎么办?如果我有大量文件,则需要全部更改。

现在,我开始考虑使用变量来设置错误日志的路径。当然可以,但是如果我想在函数或类方法中使用error_log怎么办?然后,我需要将变量设置为全局变量,但这被认为是不好的做法!但是,如果我不应该在一个类的深处使用该函数,那也算不上坏习惯吗?这里有什么好的解决方案?

<?php

function legit() {
    try {
        if (1 == 1) {
            throw new Exception('There was an error here');
        }
    } catch (Exception $e) {
        throw new Exception('throw the error to the try-catch outside the function...');
    }

}

try {
    legit();
} catch (Exception $e) {
    echo 'error here' . $e->getMessage();

    //log it
}

这是我在上面谈论的一个示例(没有在类/函数中进行深入日志记录。这是一个好方法吗?)

进一步:

我不太确定应该如何一般使用Exceptions。假设我想在方法中使用SQL对数据库进行INSERT,是否可以使用try /
catch然后在异常失败后重新抛出该异常?那被认为是好习惯吗?请举例。


问题答案:

首先,我要赞扬您查看PHP中的标准错误方法。不幸的是error_log,您发现了一些限制。

这是一个很长的答案,请继续阅读以下内容:

  1. 失误
    • 直接记录错误vs trigger_errorset_error_handler
    • 好的错误会变坏的地方-致命错误。
  2. 例外情况
    • 声压级
    • 该怎么办?
    • 设定
    • 用法

TL; DR 使用trigger_error筹集的错误和set_error_handler用于记录他们。

当事情在程序中没有按预期进行时,您通常会想引发一个错误,以便有人或某事得到通知。错误是指程序可以继续运行,但发生了一些值得注意的,可能有害或错误的情况。此时,许多人希望使用所选的日志记录包立即记录错误。我相信这完全是错误的事情。我建议使用trigger_error引发错误,以便可以通过设置的回调来处理该错误set_error_handler。让我们比较一下这些选项:

直接记录错误

因此,您已经选择了日志记录包。现在,您可以将代码中发生错误的任何地方分散到记录器中。让我们看一下您可能会打的一个电话(我将使用与Jack回答中类似的记录器):

Logger::getLogger('standard')->error('Ouch, this hurts');

您需要什么来运行此代码?

    **类** :记录器
     **方法** :getLogger
     **返回** :具有方法“错误”的对象

这些是使用此代码所需的依赖项。每个想重用此代码的人都必须提供这些依赖项。这意味着标准的PHP配置将不再足以重用您的代码。在最好的情况下,使用依赖注入,您仍然需要将logger对象传递到所有可能产生错误的代码中。

另外,除了代码负责什么之外,它还负责记录错误。这违背了单一责任原则。

我们可以看到 直接记录错误是不好的

trigger_error进行救援

PHP有一个称为的函数trigger_error,可以像标准函数一样用来引发错误。与它一起使用的错误级别在错误级别常量中定义。当你必须使用用户错误的一个用户:E_USER_ERRORE_USER_WARNING或默认值E_USER_NOTICE(其他错误级别被保留用于标准的功能等)。使用标准的PHP函数引发错误,可使代码在任何标准的PHP安装中重复使用!我们的代码不再负责记录错误(仅确保已引发错误)。

使用trigger_error我们,我们仅执行错误记录过程的一半(引发错误),并为错误处理程序节省了响应错误的责任,这将在后面介绍。

错误处理程序

我们使用set_error_handler函数设置了一个自定义错误处理程序(请参阅代码设置)。此自定义错误处理程序代替了通常根据PHP配置设置将标准消息记录在Web服务器错误日志中的标准PHP错误处理程序。我们仍然可以通过false在自定义错误处理程序中返回来使用此标准错误处理程序。

定制错误处理程序有一个责任:响应错误(包括您要执行的任何日志记录)。在自定义错误处理程序中,您具有对系统的完全访问权限,并且可以运行所需的任何类型的日志记录。几乎所有使用Observer设计模式的记录器都可以(我不打算讨论它,因为我认为它是次要的)。这应该允许您挂接新的日志观察器,以将输出发送到所需的位置。

您具有完全的控制权,可以在代码的单个可维护部分中对错误进行处理。现在,可以在项目之间或在单个项目中的页面之间快速,轻松地更改错误日志。有趣的是,即使@被抑制的错误也以errno0表示到达自定义错误处理程序,如果error_reporting遵守掩码,则不应报告该错误。

当好的错误变成坏的-致命错误

无法从某些错误继续。以下错误级别不能从自定义错误处理程序处理:E_ERRORE_PARSEE_CORE_ERRORE_CORE_WARNINGE_COMPILE_ERRORE_COMPILE_WARNING。当标准函数调用触发了这类错误时,自定义错误处理程序将被跳过,系统将关闭。这可以通过以下方式生成:

call_this_function_that_obviously_does_not_exist_or_was_misspelt();

这是一个 严重的
错误!无法恢复,系统即将关闭。我们唯一的选择是register_shutdown_function处理关机问题。但是,只要脚本完成(成功和失败),就会执行此功能。error_get_last当最后一个错误是致命错误时,可以使用此信息和一些基本信息进行记录(此时系统几乎已关闭)。发送正确的状态代码并显示您选择的“内部服务器错误”类型页面也很有用。

2.例外情况

可以用与基本错误非常相似的方式处理异常。取而代之的trigger_error异常会被你的代码(手动抛出throw new Exception或从一个标准的函数调用)。使用set_exception_handler定义要用来处理与异常的回调。

声压级

标准PHP库(SPL)提供了exceptions。它们是引发异常的首选方式,因为就像trigger_error它们是PHP的标准部分一样,它不会为您的代码引入额外的依赖关系。

该怎么办?

引发异常时,可以做出三种选择:

  1. 捕获并修复它(然后代码继续运行,好像没有发生任何不好的事情一样)。
  2. 抓住它,添加有用的信息,然后重新抛出。
  3. 让它上升到更高的水平。

在堆栈的每个级别都进行了这些选择。最终,一旦达到最高级别,您设置的回调set_exception_handler将被执行。这是您的日志记录代码所属的位置(出于与错误处理相同的原因),而不是遍及catch代码中的整个语句。

3.代码

设定

错误处理程序

function errorHandler($errno , $errstr, $errfile, $errline, $errcontext)
{
    // Perform your error handling here, respecting error_reporting() and
    // $errno.  This is where you can log the errors.  The choice of logger
    // that you use is based on your preference.  So long as it implements
    // the observer pattern you will be able to easily add logging for any
    // type of output you desire.
}

$previousErrorHandler = set_error_handler('errorHandler');

异常处理程序

function exceptionHandler($e)
{
    // Perform your exception handling here.
}

$previousExceptionHandler = set_exception_handler('exceptionHandler');

关机功能

function shutdownFunction()
{
    $err = error_get_last();

    if (!isset($err))
    {
        return;
    }

    $handledErrorTypes = array(
        E_USER_ERROR      => 'USER ERROR',
        E_ERROR           => 'ERROR',
        E_PARSE           => 'PARSE',
        E_CORE_ERROR      => 'CORE_ERROR',
        E_CORE_WARNING    => 'CORE_WARNING',
        E_COMPILE_ERROR   => 'COMPILE_ERROR',
        E_COMPILE_WARNING => 'COMPILE_WARNING');

    // If our last error wasn't fatal then this must be a normal shutdown.  
    if (!isset($handledErrorTypes[$err['type']]))
    {
        return;
    }

    if (!headers_sent())
    {
        header('HTTP/1.1 500 Internal Server Error');
    }

    // Perform simple logging here.
}

register_shutdown_function('shutdownFunction');

用法

失误

// Notices.
trigger_error('Disk space is below 20%.', E_USER_NOTICE);
trigger_error('Disk space is below 20%.'); // Defaults to E_USER_NOTICE

// Warnings.
fopen('BAD_ARGS'); // E_WARNING fopen() expects at least 2 parameters, 1 given
trigger_error('Warning, this mode could be dangerous', E_USER_WARNING);

// Fatal Errors.    
// This function has not been defined and so a fatal error is generated that
// does not reach the custom error handler.
this_function_has_not_been_defined();
// Execution does not reach this point.

// The following will be received by the custom error handler but is fatal.
trigger_error('Error in the code, cannot continue.', E_USER_ERROR);
// Execution does not reach this point.

例外情况

以前列出的三个选择中的每一个都以通用的方式列出在这里,对其进行修复,追加并使其冒出。

1可修复:

try
{
    $value = code_that_can_generate_exception();
}
catch (Exception $e)
{
    // We decide to emit a notice here (a warning could also be used).
    trigger_error('We had to use the default value instead of ' .
                  'code_that_can_generate_exception\'s', E_USER_NOTICE);
    // Fix the exception.
    $value = DEFAULT_VALUE;
}

// Code continues executing happily here.

2附加:

下面观察如何code_that_can_generate_exception()不知道的$context。该级别的catch块具有更多信息,如果可以通过将其重新抛出有用,则可以将其附加到异常上。

try
{
    $context = 'foo';
    $value = code_that_can_generate_exception();
}
catch (Exception $e)
{
    // Raise another exception, with extra information and the existing
    // exception set as the previous exception. 
    throw new Exception('Context: ' . $context, 0, $e);
}

3让它冒出来:

// Don't catch it.


 类似资料:
  • #2023秋招##顺丰# 9.5 笔试 9.12 16.30 顺丰一面 1. 自我介绍 2. 项目介绍 3. 工程化和源码相关 4. vue 组件通信 5. 实习期间开发流程 6. 除了实习,有没有做过其它项目 顺丰整体面试时间大约为24分钟,很轻松的面试体验,只问了一个八股相关问题。

  • 岗位:AIGC算法岗 base:北京 一面1.23算法题:1.无序数组第k大数,要求优化部分快排 2.链表相加 二面1.25算法题:1.二叉树非递归实现中序遍历 2.手撕nms和iou 三面1.30无算法 四面2.1 HR面 五面2.7技术加面 2.8 offer审批通过 年后谈薪 #字节#

  • 0.3 新版功能. 应用故障,服务器故障。早晚你会在产品中看见异常。即使你的代码是 100% 正确的, 你仍然会不时看见异常。为什么?因为涉及的所有一切都会出现故障。这里给出一些 完美正确的代码导致服务器错误的情况: 客户端在应用读取到达数据时,提前终止请求 数据库服务器超载,并无法处理查询 文件系统满了 硬盘损坏 后端服务器超载 你所用的库出现程序错误 服务器的网络连接或其它系统故障 而且这只是

  • 可确认下载失败或无法与互联网连接时等,最新的10件错误历史记录。 轻触列表的错误项目,会显示详细内容。部分项目还可确认建议解决方法。

  • 我正在学习Fastapi,我正在localhost启动一个uvicorn服务器。每当出现错误/异常时,我都不会得到回溯。所有我得到的是: 所以,调试很困难,我正在试用python的日志模块 我还尝试过使用调试参数启动uvicorn

  • 本章讨论Laravel项目中的错误和日志记录以及如何处理它们。 Errors 正在进行的项目承担一些错误。 启动新的Laravel项目时,已经为您配置了错误和异常处理。 通常,在本地环境中,我们需要查看错误以进行调试。 我们需要在生产环境中隐藏用户的这些错误。 这可以通过存储在应用程序根目录的环境文件.env设置的变量APP_DEBUG来实现。 对于本地环境, APP_DEBUG的值应为true但