cleaned up some debug prints
[urisagit/Stem.git] / lib / Stem / Log / Tail.pm
CommitLineData
4536f655 1# File: Stem/Log/Tail.pm
2
3# This file is part of Stem.
4# Copyright (C) 1999, 2000, 2001 Stem Systems, Inc.
5
6# Stem is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10
11# Stem is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15
16# You should have received a copy of the GNU General Public License
17# along with Stem; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20# For a license to use the Stem under conditions other than those
21# described here, to purchase support for this software, or to purchase a
22# commercial warranty contract, please contact Stem Systems at:
23
24# Stem Systems, Inc. 781-643-7504
25# 79 Everett St. info@stemsystems.com
26# Arlington, MA 02474
27# USA
28
29package Stem::Log::Tail ;
30
31use strict ;
32use IO::Seekable ;
33use Data::Dumper ;
34
35use Stem::Trace 'log' => 'stem_status', 'sub' => 'TraceStatus' ;
36use Stem::Trace 'log' => 'stem_error' , 'sub' => 'TraceError' ;
37
38my $attr_spec = [
39
40 {
41 'name' => 'path',
42 'required' => 1,
43 'help' => <<HELP,
44This is the full path to the file we want to tail.
45HELP
46 },
47
48 {
49 'name' => 'data_log',
50 'required' => 1,
51 'help' => <<HELP,
52This is the log which gets sent the data log entries.
53HELP
54 },
55
56 {
57 'name' => 'status_log',
58 'help' => <<HELP,
59This is the log which gets sent the status log entries.
60These include things like: Log has been rotated, deleted, moved, etc...
61HELP
62 },
63 {
64 'name' => 'label',
65 'default' => 'tail',
66 'help' => <<HELP,
67Label to tag tailed log entry.
68HELP
69 },
70 {
71 'name' => 'level',
72 'default' => '5',
73 'help' => <<HELP,
74Severity level for this tailed log entry.
75HELP
76 },
77 {
78 'name' => 'interval',
79 'help' => <<HELP,
80This specifies (in seconds) how often we check the log file for new
81data. If this is not specified, you need to call the tail_cmd method
82to check for new data.
83HELP
84 },
85 {
86 'name' => 'delay',
87 'default' => 10,
88 'help' => <<HELP,
89This specifies (in seconds) how long the delay is before the
90first repeated checking of the log file for new data.
91HELP
92 },
93] ;
94
95
96sub new {
97
98 my( $class ) = shift ;
99
100 my $self = Stem::Class::parse_args( $attr_spec, @_ ) ;
101 return $self unless ref $self ;
102
b3d3e68f 103#print "TAIL INT $self->{'interval'}\n" ;
4536f655 104
105 if ( my $interval = $self->{'interval'} ) {
106
107 $self->{'timer'} = Stem::Event::Timer->new(
108 'object' => $self,
109 'method' => 'tail_cmd',
110 'interval' => $interval,
111 'delay' => $self->{'delay'},
112 'repeat' => 1,
113 'hard' => 1,
114 ) ;
115
b3d3e68f 116#print "TIMER $self->{'timer'}\n" ;
4536f655 117
118 }
119
120 $self->{'prev_size'} = 0 ;
121 $self->{'prev_mtime'} = 0 ;
122 $self->{'prev_inode'} = -1 ;
123
124 return( $self ) ;
125}
126
127sub tail_cmd {
128
129 my( $self ) = @_ ;
130
b3d3e68f 131#print "TAILING\n" ;
4536f655 132
133 local( *LOG ) ;
134
135 my $path = $self->{'path'} ;
136
137 unless( open( LOG, $path ) ) {
138
139 return if $self->{'open_failed'} ;
140 $self->{'open_failed'} = 1 ;
141
142 if ( my $status_log = $self->{'status_log'} ) {
143
144 Stem::Log::Entry->new(
145 'logs' => $status_log,
146 'label' => 'LogTail status',
147 'text' =>
148 "LogTail: missing log $path $!\n",
149 ) ;
150 }
151 return ;
152 }
153
154 $self->{'open_failed'} = 0 ;
155
156 my( $inode, $size, $mtime ) = (stat LOG)[1, 7, 9] ;
157
158 TraceStatus "size $size mtime $mtime $inode" ;
159
160 my $prev_inode = $self->{'prev_inode'} ;
161 my $prev_size = $self->{'prev_size'} ;
162
163 if ( $prev_inode == -1 ) {
164
165 $self->{'prev_inode'} = $inode ;
166
167 if ( my $status_log = $self->{'status_log'} ) {
168
169 Stem::Log::Entry->new(
170 'logs' => $status_log,
171 'level' => 6,
172 'label' => 'LogTail status',
173 'text' =>
174 "LogTail: first open of $path\n",
175 ) ;
176 }
177 }
178 elsif ( $inode != $prev_inode ) {
179
180 $self->{'prev_inode'} = $inode ;
181
182 if ( my $status_log = $self->{'status_log'} ) {
183
184 Stem::Log::Entry->new(
185 'logs' => $status_log,
186 'level' => 6,
187 'label' => 'LogTail status',
188 'text' =>
189 "LogTail: $path has moved\n",
190 ) ;
191 }
192
193# tail the entire file as it is new
194
195 $prev_size = 0 ;
196
197 }
198 elsif ( $size < $prev_size ) {
199
200 if ( my $status_log = $self->{'status_log'} ) {
201
202 Stem::Log::Entry->new(
203 'logs' => $status_log,
204 'level' => 6,
205 'label' => 'LogTail status',
206 'text' =>
207 "LogTail: $path has shrunk\n",
208 ) ;
209 }
210
211# tail the entire file as it has shrunk
212
213 $prev_size = 0 ;
214 }
215 elsif ( $size == $prev_size ) {
216
217 TraceStatus "no changes" ;
218 return ;
219 }
220
221 $self->{'prev_size'} = $size ;
222
223 my $delta_size = $size - $prev_size ;
224
225 return unless $delta_size ;
226
227 my $read_buf ;
228
229 sysseek( *LOG, $prev_size, SEEK_SET ) ;
230 sysread( *LOG, $read_buf, $delta_size ) ;
231
232 Stem::Log::Entry->new(
233 'logs' => $self->{'data_log'},
234 'level' => $self->{'level'},
235 'label' => $self->{'label'},
236 'text' => $read_buf,
237 ) ;
238
239 return ;
240}
241
2421 ;