解析日志文件的模式

时间:2012-03-05 17:50:08

标签: php parsing design-patterns

我有一个PHP 5.3.4项目,我需要解析日志文件并向用户显示摘要。日志文件格式(在我无法控制的范围内)看起来大致如下:

BEGIN GROUP: my group
<TESTCASE ID=1>
*** Test Name: Some Test
</TESTCASE RESULT="PASSED">
END GROUP: my group
BEGIN GROUP: another group
<TESTCASE ID=1>
*** Test Name: Some other Test
</TESTCASE RESULT="PASSED">
BEGIN GROUP: sub group
<TESTCASE ID=2>
*** Test Name: Foo
</TESTCASE RESULT="FAILED">
END GROUP: sub group
<TESTCASE ID=3>
*** Test Name: Bar
</TESTCASE RESULT="PASSED">
END GROUP: another group

我想我首先要将日志文件解析为一组这样的对象:

abstract class ResultBase
{
    // name of this result element
    private $name_ = null;
    // line number in the result log corresponding ot this element
    private $line_ = null;

    // ...
}

// defines a Group element from the logfile
class Group extends ResultBase
{
    // array of ResultBase-derived child elements belonging to this group.
    private $children_ = null;

    // ...
}

// defines a TestCase element from the logfile
class TestCase extends ResultBase
{
    // test case id
    private $id_ = null;
    // "passed" or "failed" result
    private $result_ = null;

    // ...
}

class LogFile
{
    // array of ResultBase-derived elements that constitute the log
    private $elements_ = null;
}

然后打印对象:

function Print( $log_file )
{
    // some recursive print algorithm...
}

我是PHP的新手,所以如果以上是错误的方向,请告诉我。

我正在寻找一些应用模式以及一些关于如何实现它的伪代码建议。

function Parse( $log_file_name )
{
    $logfile = new LogFile();
    // what goes here???
    return $logfile;
}

Print(Parse('C:\mylogfile.log'));

1 个答案:

答案 0 :(得分:0)

你可以这样做:

$log = new LogFile('C:\mylogfile.log');
$log->parse();
printf("Log has %d groups.\n", $log->getGroups()); # Log has 3 groups.

LogFile只是从SplFileObject延伸:

class LogFile extends SplFileObject {
    private $groups;
    public function rewind() {
        $this->groups = 0;
        parent::rewind();
    }
    public function current() {
        $line = parent::current();
        if (substr($line, 0, 13) === 'BEGIN GROUP: ') $this->groups++;
        return $line;
    }
    public function parse() {
        foreach($this as $line);
    }
    public function getGroups() {
        return $this->groups;
    }
}

也许这会给你一些指示。一个更好的变体是装饰器,它接受任何迭代器,这样可以使事情变得更加灵活:

$log = new SplFileObject($logFileName);
$parser = new LogFileParser($log);
$parser->parse();
printf("Log has %d groups.\n", $parser->getGroups());

class LogFileParser extends IteratorIterator
{
    private $groups;
    public function rewind() {
        $this->groups = 0;
        parent::rewind();
    }
    public function current() {
        $line = parent::current();
        if (substr($line, 0, 13) === 'BEGIN GROUP: ') $this->groups++;
        return $line;
    }
    public function parse() {
        foreach($this as $line);
    }
    public function getGroups() {
        return $this->groups;
    }
}