JBlond/apache_log_parser

View on GitHub
ApacheLogParser.php

Summary

Maintainability
B
5 hrs
Test Coverage
<?php

namespace jblond\Apache_Log_Parser;

/**
 * Class apache_log_parser
 */
class ApacheLogParser
{
    /**
     * @var String
     * @access private
     */
    protected string $file = "";

    /**
     * @var String
     * @access private
     */
    protected $content = "";

    /**
     * @var array
     * @access private
     */
    protected array $data = array();

    /**
     * @var array
     * @access public
     */
    protected array $stats = array();

    /**
     * @param String $file
     * @access public
     */
    public function __construct(string $file)
    {
        $this->file = $file;
        $this->content = file_get_contents($this->file);
        if (!$this->content) {
            echo "Can not open file: '" . $this->file . "' <br>Check the file name!";
            return;
        }
        $this->paralyseLog();
    }

    /**
     * Parse raw data and keep only errors
     * @access private
     * @return void
     */
    protected function parseData(): void
    {
        $input = explode("\n", $this->content);
        $this->stats['rows'] = 0;
        $array_size = sizeof($input);
        for ($i = 0; $i < $array_size; $i++) {
            $this->stats['rows']++;
            $back = explode(" ", $input[$i]);
            if (!isset($back['8'])) { //new line in file / empty line
                continue;
            }
            if (
                //these are not errors
                $back['8'] == '200' || // OK
                $back['8'] == '206' || //Partial Content
                $back['8'] == '301' || // Moved Permanently (redirect permanently)
                $back['8'] == '302' || // Found (in cache / or redirect after POST or so)
                $back['8'] == '304' // Not Modified (in cache)
            ) {
                continue;
            }
            $output = array('type' => $back['8'], 'date' => $back['3'], 'info' => $back['0'], 'detail' => $back['6']);
            $this->data[] = $output;
        }
    }

    /**
     * parse the log file
     * @access private
     * @return void
     */
    protected function paralyseLog(): void
    {
        $this->parseData();
        $type = array();
        $detail = array();

        $size_of_data = sizeof($this->data);
        for ($a = 0; $a < $size_of_data; $a++) {
            if (isset($type[$this->data[$a]['type']])) {
                $type[$this->data[$a]['type']]++;
            } else {
                $type[$this->data[$a]['type']] = 1;
            }

            if (isset($detail[$this->data[$a]['detail']])) {
                $detail[$this->data[$a]['detail']]++;
            } else {
                $detail[$this->data[$a]['detail']] = 1;
                $this->stats['content_type'][$this->data[$a]['detail']] = $this->data[$a]['type'];
            }
        }
        // statistics + types
        $this->stats['analyzed_rows'] = sizeof($this->data);
        $key = array_keys($type);
        $this->stats['rowtypeCount'] = sizeof($key);
        for ($x = 0; $x < $this->stats['rowtypeCount']; $x++) {
            $temp = array(
                'name' => $key[$x],
                'value' => $type[$key[$x]],
                'pro' => round(($type[$key[$x]] * 100 / $this->stats['analyzed_rows']), 4) . ' %'
            );
            $this->stats['rowtype'][] = $temp;
        }

        $this->stats['errCount'] = sizeof($detail);
        array_multisort($detail, SORT_DESC, SORT_NUMERIC);
        $this->stats['err'] = $detail;
    }

    /**
     * @access public
     * @return String $out
     */
    public function table(): string
    {
        $out = '<br /><br />Parsed '
            . $this->stats['rows']
            . ' lines. Found <b>'
            . $this->stats['analyzed_rows']
            . '</b> errors with <b>'
            . $this->stats['rowtypeCount']
            . '</b> type(s)<br /><br />';
        $out .= '<table>';
        $out .= '<tr><td><b>Name</b></td><td><b>Value</b></td><td><b>Percent</b></td></tr>';
        foreach ($this->stats['rowtype'] as $val) {
            $out .= '<tr><td>' . $val['name'] . '</td><td>' . $val['value'] . '</td><td>' . $val['pro'] . '</td></tr>';
        }
        $out .= '</table>';
        $out .= '<br /><br />Listed the 50 most counted errors ( overall '
            . $this->stats['errCount']
            . ' different errors ).<br /><br />';
        $out .= '<table>';
        $out .= '<tr><td><b>Rank</b></td><td><b>count</b></td><td><b>type</b></td><td><b>Error</b></td></tr>';
        $keys = array_keys($this->stats['err']);
        $keycount = count($keys);
        if ($keycount > 50) {
            $keycount = 50; /* limit to 50 errors shown */
        }
        for ($y = 0; $y < $keycount; $y++) {
            if (trim($this->stats['err'][$keys[$y]]) == '') {
                continue;
            }
            $out .= '<tr><td>' . ($y + 1) . '</td><td>'
                . $this->stats['err'][$keys[$y]] . '</td><td>'
                . $this->stats['content_type'][$keys[$y]] . '</td><td>' . htmlentities($keys[$y]) . '</td></tr>' . "\n";
        }
        $out .= '</table>';
        return $out;
    }

    /**
     * @access public
     * @return String $out
     */
    public function output(): string
    {
        return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' .
            '<html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>apache log parser</title>
        <style type="text/css">
        * {
            font-family: verdana,serif;
            font-size: 11px;
            background-color: #EFEFEF;
            color: #101010;
            border:0;
            margin:0;
        }
        body {
            padding:20px;
        }
        table {
            /* border:1px solid #000000; */
            padding: 0;
        }
        td {
            border-bottom:1px solid #000000;
            border-right:1px solid #000000;
            border-top:1px solid #000000;
        }

        tr > td {
            border-left:1px solid #000000;
        }
        </style></head><body>' . $this->table() . '</body></html>';
    }
}