rssreader  
          
              
                February 13, 2020,  6:58am
               
              1 
           
         
        
          I have log - target:
'error' => [
    'class' => 'yii\log\EmailTarget',
    'levels' => ['error', 'warning'],
    'except' => ['yii\web\HttpException:404'],
    'message' => [
        'from' => ['XXXXXXX'],
        'to' => ['XXXXXXX'],
        'subject' => 'XXXXXX - error',
    ],
],
 
It will send me an email whenever an application error/warning occurs. It’s OK.
The problem is a “long duration” error (for example database down, but it could be anything else).
How prevent recurring emails with the same error?
         
        
           
         
            
       
      
        
          
          
            samdark  
          
              
                February 13, 2020, 10:37am
               
              2 
           
         
        
          For production it’s much better to use something like https://sentry.io/welcome/  (they have OpenSource version) or https://rollbar.com/ . They’s both recording each error instance with full context, getting you a list of the most repeating errors and sending summary emails.
         
        
           
         
            
       
      
        
          
          
            rssreader  
          
              
                March 25, 2020,  8:06am
               
              3 
           
         
        
          I prefer a simple solution over implementing another error management system
         
        
           
         
            
       
      
        
          
          
            samdark  
          
              
                March 25, 2020,  1:50pm
               
              4 
           
         
        
          Simple solution is to take existing solution but if you need to re-invent your own then:
You need to generalize error i.e. strip parameters out of it. 
You need to store hash of this stripped down error when sending email. 
When deciding if next one should be sent, search for its hash in database. If it’s there then do not send an email. 
 
         
        
           
         
            
       
      
        
          
          
            rssreader  
          
              
                April 6, 2020, 10:22am
               
              5 
           
         
        
          This works for me now (email every 30 seconds max):
<?php
namespace app\base\log;
use yii\helpers\VarDumper;
use yii\log\Logger;
use yii\log\LogRuntimeException;
class EmailTarget extends \yii\log\EmailTarget
{
    public function formatMessage($message)
    {
        list($text, $level, $category, $timestamp) = $message;
        $level = Logger::getLevelName($level);
        if (!is_string($text)) {
            // exceptions may not be serializable if in the call stack somewhere is a Closure
            if ($text instanceof \Throwable || $text instanceof \Exception) {
                $text = "\n--------------------------\n".$text->getMessage().' in '.$text->getFile().':'.$text->getLine()."\n--------------------------\n";
            } else {
                $text = VarDumper::export($text);
            }
        }
        $prefix = $this->getMessagePrefix($message);
        return "[$category] $text";
    }
    public function export()
    {
        $lockFile = sys_get_temp_dir().'/email_error.lock';
        $lastMessage = @file_get_contents($lockFile);
        if (empty($this->message['subject'])) {
            $this->message['subject'] = 'Application Log';
        }
        $messages = array_map([$this, 'formatMessage'], $this->messages);
        if($messages[0] === $lastMessage && @filemtime($lockFile) > strtotime('-30 seconds')){ return; }
        file_put_contents($lockFile, $messages[0], LOCK_EX);
        $body = wordwrap(implode("\n", $messages), 70);
        $message = $this->composeMessage($body);
        if (!$message->send($this->mailer)) {
            throw new LogRuntimeException('Unable to export log through email!');
        }
    }
}