1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
19: namespace Fluent\Logger;
20:
21: 22: 23:
24: class FileLogger extends BaseLogger
25: {
26: const MAX_WRITE_RETRY = 10;
27:
28: protected $tag;
29: protected $path;
30:
31: 32: 33: 34: 35: 36:
37: public function __construct($path)
38: {
39: $this->path = $path;
40: $fp = fopen($path, "c");
41:
42: if (is_resource($fp)) {
43: $this->fp = $fp;
44: } else {
45: throw new \Exception("could not open file {$path}");
46: }
47: }
48:
49: 50: 51: 52: 53:
54: public static function open($path)
55: {
56: $logger = new self($path);
57: return $logger;
58: }
59:
60: 61: 62: 63: 64: 65:
66: public function post($tag,array $data)
67: {
68: $entity = new Entity($tag, $data);
69: return $this->postImpl($entity);
70: }
71:
72: 73: 74: 75: 76:
77: public function post2(Entity $entity)
78: {
79: return $this->postImpl($entity);
80: }
81:
82: protected function postImpl(Entity $entity)
83: {
84: $packed = json_encode($entity->getData());
85: $wbuffer = $wbuffer = sprintf("%s\t%s\t%s\n",
86: date(\DateTime::ISO8601,
87: $entity->getTime()),
88: $entity->getTag(),
89: $packed
90: );
91:
92: $data = $wbuffer;
93: $length = strlen($data);
94: $written = 0;
95:
96: try {
97: if (!flock($this->fp, LOCK_EX)) {
98: throw new \Exception('could not obtain LOCK_EX');
99: }
100: fseek($this->fp,-1, SEEK_END);
101:
102: while ($written < $length) {
103: $nwrite = fwrite($this->fp, $wbuffer);
104: if ($nwrite === false) {
105: throw new \Exception("could not write message");
106: } else if ($nwrite === "") {
107: throw new \Exception("connection aborted");
108: } else if ($nwrite === 0) {
109: if ($retry > self::MAX_WRITE_RETRY) {
110: throw new \Exception("failed fwrite retry: max retry count");
111: }
112: $retry++;
113: }
114: $written += $nwrite;
115: $wbuffer = substr($wbuffer,$written);
116: }
117:
118: flock($this->fp, LOCK_UN);
119: } catch (\Exception $e) {
120: $this->processError($this, $entity, $e->getMessage());
121: return false;
122: }
123: }
124: }
125: