【问题标题】:How do i save logs in php我如何在php中保存日志
【发布时间】:2010-07-06 14:40:17
【问题描述】:

如何在 PHP 中保存日志? php 中是否有任何“神奇”功能可用于这样做,或者任何库?还是我每次都必须fopen 归档并转储?我想将我的日志保存在文本文件中。

提前致谢:)

【问题讨论】:

  • 我只想要 print_r 数据。有什么用吗?

标签: php


【解决方案1】:

如果你不想使用自己的实现或者只是做 fopen-stuff 你可以使用内置函数 error_log('string to log'); 。这会将所需的字符串写入服务器软件的错误日志中。

【讨论】:

  • PHP 允许您使用error_log php.ini 设置配置默认记录器:php.net/error-log
【解决方案2】:

我写了一个简单的类来做到这一点。也许你会发现它很有用。

class Log
  {
  public function __construct($log_name,$page_name)
    {
    if(!file_exists('/your/directory/'.$log_name)){ $log_name='a_default_log.log'; }
    $this->log_name=$log_name;

    $this->app_id=uniqid();//give each process a unique ID for differentiation
    $this->page_name=$page_name;

    $this->log_file='/your/directory/'.$this->log_name;
    $this->log=fopen($this->log_file,'a');
    }
  public function log_msg($msg)
    {//the action
    $log_line=join(' : ', array( date(DATE_RFC822), $this->page_name, $this->app_id, $msg ) );
    fwrite($this->log, $log_line."\n");
    }
  function __destruct()
    {//makes sure to close the file and write lines when the process ends.
    $this->log_msg("Closing log");
    fclose($this->log);
    }
  }

 $log=new Log('file_name','my_php_page');
 $log->log_msg('fizzy soda : 45 bubbles remaining per cubic centimeter');

【讨论】:

  • 感谢 Alex JL,但这对我来说听起来很新鲜$this->app_id=self::real_unique_string()。进程 ID 对日志有何用处?以后查看日志时,进程 ID 如何帮助我?
  • 我使用进程 ID 来保持直线的来源。日志中的每个页面都是唯一的,因此假设您有 5 个人同时访问您的页面 - 日志中只会有大量行。它可以帮助您了解哪些行来自同一进程的 ID。如果你不需要它,你可以随时把它拿出来。
  • 这似乎是PHP的error_log($msg, 3, $log_name);的一个极其复杂的版本
  • @R. Bemrose 这只是用一些便利包装了 fopen 和 fclose……我不明白它怎么会被视为“极其复杂”。
  • 好的,谢谢 Alex JL。现在我明白了。
【解决方案3】:

如果您不喜欢使用其他回复提到的 PHP 错误处理函数 (http://www.php.net/manual/en/ref.errorfunc.php),这里有一个我以前使用过的非常简单的 Logger 类。标准警告适用,因为我没有在高风险应用程序或流量很大的网站上使用它(尽管它应该没问题)。

<?
class Logger
{
  private static function addEntry($str)
  {
    $handle = fopen('./services.log', 'a');
    fwrite($handle, sprintf("%s %s\n", date('c'), $str));
    fclose($handle);
  }

  public static function warn($str)
  {
    self::addEntry("WARNING $str");
  }

  public static function info($str)
  {
    self::addEntry("INFO $str");
  }

  public static function debug($str)
  {
    self::addEntry("DEBUG $str");
  }
}
?>

那么你可以这样使用它:

<?php
require('Logger.php');
Logger::debug('test');
Logger::warn('bwah');
Logger::info('omg');
?>

添加更多功能非常简单(例如Logger::error()),存储文件处理程序,这样您就不必在每次要记录某些内容时都重新打开它(即,将$handle 变量存储在一个私有静态类作用域变量,并让 addEntry() 在运行时检查它是否已设置,如果没有则运行 fopen()),或者更改您记录的格式。

干杯。

【讨论】:

  • 很高兴您喜欢它,并感谢您的投票。是的,这是何时使用静态的教科书示例。干杯。
【解决方案4】:

一切都取决于您要记录的内容。默认情况下,您将拥有一个 error_log,它本质上是一个纯文本文件。如果您正在讨论在代码中记录事件以在脚本中进行调试或跟踪活动,那么您将需要为此编写自己的日志处理程序,但这非常简单。正如另一位海报所说,您可以使用 error_log() 函数将内容推送到错误日志,但这会导致一些非常难以管理的日志文件 imv。

【讨论】:

    【解决方案5】:

    最后一个答案是 2010 年的,所以它需要呼吸新鲜空气。我正在与您分享我在程序中使用的 php 类。 我对上面@Sam-Bisbee 的回答采取了类似的方法,因此很容易添加新的功能和功能,但我也使它更灵活地用于不同的程序/脚本。

    我把我的课放在Logg.php文件里,你也可以。

    我的班级

    <?php
    class Logg
    {
        public static $fileName = 'new_log';
        public static $filePath = '/';
        public static $fileType = '.log';
        
        public static function addInfo($logMsg, $fName = null, $fPath = null)
        {
            $fName = $fName ?: self::$fileName;
            $fPath = $fPath ?: self::$filePath;
            self::addData($logMsg, $fName, $fPath, ' |  INFO   |');
        }
        
        public static function addWarn($logMsg, $fName = null, $fPath = null)
        {
            $fName = $fName ?: self::$fileName;
            $fPath = $fPath ?: self::$filePath;
            self::addData($logMsg, $fName, $fPath, ' | WARNING |');
        }
        
        public static function addErr($logMsg, $fName = null, $fPath = null)
        {
            $fName = $fName ?: self::$fileName;
            $fPath = $fPath ?: self::$filePath;
            self::addData($logMsg, $fName, $fPath, ' |  ERROR  |');
        }
        
        public static function addConf($logMsg, $fName = null, $fPath = null)
        {
            $fName = $fName ?: self::$fileName;
            $fPath = $fPath ?: self::$filePath;
            self::addData($logMsg, $fName, $fPath, ' | CONFIG  |');
        }
        
        private static function addData($logMsg, $fName, $fPath, $type)
        {
            $handle = fopen($fPath . $fName . self::$fileType, 'a');
            
            if (gettype($logMsg) == 'array') {
                if (count($logMsg)%2 == 0) {
                    $logText = '';
                    for ($i = 0; $i < count($logMsg); $i+=2) {
                        $logText .= str_pad($logMsg[$i], $logMsg[$i+1], " ", STR_PAD_BOTH).'|';
                    }
                    fwrite($handle, sprintf("| %s%s", date("Y-m-d H:i:s"), $type.$logText.PHP_EOL));
                } else {
                    throw new Exception('Wrong arguments for Array-type log.');
                }
            } else {
                fwrite($handle, sprintf("| %s%s", date("Y-m-d H:i:s"), $type.' '.$logMsg.PHP_EOL));
            }
            
            fclose($handle);
        }
        
        public static function addLine($lines = 1, $fName = null, $fPath = null)
        {
            $fName = $fName ?: self::$fileName;
            $fPath = $fPath ?: self::$filePath;
            $handle = fopen($fPath . $fName . self::$fileType, 'a');
            fwrite($handle, str_repeat(PHP_EOL, $lines));
            fclose($handle);
        }
    }
    ?>
    

    使用示例

    包括类 - 指定日志文件名和路径:

    <?php 
    require '/Logg.php';
    
    //specifying logs file name and path - best do this right after include
    Logg::$fileName = 'ExampleName_'.date("Y_m_d");             //if not specified, default value = 'new_log'
    Logg::$filePath = 'C:/Apache24/htdocs/public_html/logs/';   //if not specified, default value = '/'
    

    如果您愿意,您可以稍后在您的程序中再次更改此值。

    简单用法:

    //Logging simple messages
    Logg::addInfo("FooBar");            //sample information log message
    Logg::addWarn("Sample warning");    //sample warning log message
    Logg::addErr ("Sample error");      //sample error log message
    Logg::addConf("Sample config log"); //sample config change log message
    
    //Adding empty lines
    Logg::addLine();                            //adds empty line
    Logg::addInfo("Log after empty line");      //some log
    Logg::addLine(3);                           //adds 3 lines instead of one
    Logg::addInfo("Log after 3 empty lines");   //some log
    
    

    您也可以使用Array(推荐)代替String作为您的“日志消息”,如下例所示。它将使您的日志消息格式化为指定的长度,以使其更具可读性:

    Logg::addLine();
    Logg::addInfo(['Goo', 5]);          //logs 'Goo' as char of length 5
    Logg::addInfo(['', 10, 'Goo', 5]);  //logs empty space of length 10 and a 'Goo' of length 5 after that
    Logg::addInfo(['Foo',       10 , 'Bar', 5, 'Sample message with some length formatted to 75 chars',              75]); //more examples
    Logg::addInfo(['FooBar',    10 , 'Baz', 5, 'Another sample message with different length formatted to 75 chars', 75]);
    Logg::addLine();
    Logg::addInfo(['Different message of length 65 - trying to format it to length 50', 50]);   //in this case the message will keep it initial length so we wont be loosing any of the information we are logging
    

    执行上面的代码,在指定的文件路径中创建了一个文件“ExampleName_2021_08_31.log”,内容为:

    | 2021-08-31 11:28:52 |  INFO   | FooBar
    | 2021-08-31 11:28:52 | WARNING | Sample warning
    | 2021-08-31 11:28:52 |  ERROR  | Sample error
    | 2021-08-31 11:28:52 | CONFIG  | Sample config log
    
    | 2021-08-31 11:28:52 |  INFO   | Log after empty line
    
    
    
    | 2021-08-31 11:28:52 |  INFO   | Log after 3 empty lines
    
    | 2021-08-31 11:28:52 |  INFO   | Goo |
    | 2021-08-31 11:28:52 |  INFO   |          | Goo |
    | 2021-08-31 11:28:52 |  INFO   |   Foo    | Bar |           Sample message with some length formatted to 75 chars           |
    | 2021-08-31 11:28:52 |  INFO   |  FooBar  | Baz |    Another sample message with different length formatted to 75 chars     |
    
    | 2021-08-31 11:28:52 |  INFO   |Different message of length 65 - trying to format it to length 50|
    
    
    

    更改文件类型

    您可以通过更改我的 Logg 类的 $fileType 属性来更改为不同的文件类型。默认文件类型为 ".log"

    例如:

    //changing file type, can be put after class include
    Logg::$fileType = ".txt";
    
    //logging some example messages
    Logg::addInfo("Log message now in .txt file");
    Logg::addWarn("Everything will be saved to this file from now on!");
    

    现在 "ExampleName_2021_08_31.txt" 文件已创建,内容如下:

    | 2021-08-31 09:35:20 |  INFO   | Log message now in .txt file
    | 2021-08-31 09:35:20 | WARNING | Everything will be saved to this file from now on!
    
    

    附加功能参数

    每个公共“添加”函数都有两个附加参数 - 文件名文件路径。指定此参数将临时覆盖之前指定的Logg::$fileNameLogg::$filePath 类变量值。 如果您想将某些信息记录到具有不同名称的文件或不同路径的文件中,但您不想更改程序中使用的每个日志的文件路径或文件名,它会很有用。

    用法:

    //Additional parameters
    Logg::addErr("New error log");                                                          //no additional parameters - uses filename and path from "Logg::$fileName" and "Logg::$filePath"
    Logg::addErr("New error log in different file", "<file name>");                         //one additional parameter - uses provided filename instead of "Logg::$fileName"
    Logg::addErr("New error log in different file and path", '<file name>', '<file path>'); //two additional parameters - uses provided filename and path instead of "Logg::$fileName" and "Logg::$filePath"
    

    示例:

    //this:
    {
        //logging information to different file in different path
        Logg::addInfo(['Some info', 15], 'AnotherFileName', '/some/different/path/');
    }
    //is equal to this:
    {
        //changing filename and path
        Logg::$fileName = 'AnotherFileName';
        Logg::$filePath = '/some/different/path/';
    
        //logging information
        Logg::addInfo(['Some info', 15]);
    
        //changing filename and path back to its original values
        Logg::$fileName = 'ExampleName_'.date("Y_m_d");
        Logg::$filePath = 'C:/Apache24/htdocs/public_html/logs/';
    }
    

    我正在等待您的 cmets 和建议。 祝你有美好的一天。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-03
      • 2015-07-30
      • 2016-05-11
      • 2012-01-12
      • 2013-01-11
      • 2015-02-04
      • 2021-07-17
      • 1970-01-01
      相关资源
      最近更新 更多