source: perl/lib/BarnOwl/Logging.pm @ 50a3240

Last change on this file since 50a3240 was 50a3240, checked in by Jason Gross <jgross@mit.edu>, 9 years ago
Log to subfolders of a base path A different subfolder for each protocol.
  • Property mode set to 100644
File size: 8.2 KB
Line 
1use strict;
2use warnings;
3
4package BarnOwl::Logging;
5
6=head1 BarnOwl::Logging
7
8=head1 DESCRIPTION
9
10C<BarnOwl::Logging> implements the internals of logging.  All customizations
11to logging should be done in the appropriate subclass of L<BarnOwl::Message>.
12
13=head2 USAGE
14
15Modules wishing to customize how messages are logged should override the
16relevant subroutines in the appropriate subclass of L<BarnOwl::Message>.
17
18Modules wishing to log errors sending outgoing messages should call
19L<BarnOwl::Logging::log_outgoing_error> with the message that failed
20to be sent.
21
22=head2 EXPORTS
23
24None by default.
25
26=cut
27
28use Exporter;
29
30our @EXPORT_OK = qw();
31
32our %EXPORT_TAGS = (all => [@EXPORT_OK]);
33
34use File::Spec;
35
36$BarnOwl::Hooks::newMessage->add("BarnOwl::Logging::log");
37$BarnOwl::Hooks::startup->add("BarnOwl::Logging::_register_variables");
38
39sub _register_variables {
40    BarnOwl::new_variable_bool('logging',
41        {
42            default     => 0,
43            summary     => 'turn personal logging on or off',
44            description => "If this is set to on, personal messages are\n"
45                         . "logged in the directory specified\n"
46                         . "by the 'logpath' variable.  The filename in that\n"
47                         . "directory is derived from the sender of the message."
48        });
49
50    BarnOwl::new_variable_bool('classlogging',
51        {
52            default     => 0,
53            summary     => 'turn class logging on or off',
54            description => "If this is set to on, class messages are\n"
55                         . "logged in the directory specified by the\n"
56                         . "'classpath' variable.  The filename in that\n"
57                         . "directory is derived from the class to which\n"
58                         . "the message was sent."
59        });
60
61    BarnOwl::new_variable_string('logfilter',
62        {
63            default     => '',
64            summary     => 'name of a filter controlling which messages to log',
65            description => "If non empty, any messages matching the given filter will be logged.\n"
66                         . "This is a completely separate mechanism from the other logging\n"
67                         . "variables like logging, classlogging, loglogins, loggingdirection,\n"
68                         . "etc.  If you want this variable to control all logging, make sure\n"
69                         . "all other logging variables are in their default state."
70        });
71
72    BarnOwl::new_variable_bool('loglogins',
73        {
74            default     => 0,
75            summary     => 'enable logging of login notifications',
76            description => "When this is enabled, BarnOwl will log login and logout notifications\n"
77                         . "for AIM, zephyr, or other protocols.  If disabled BarnOwl will not print\n"
78                         . "login or logout notifications."
79        });
80
81    BarnOwl::new_variable_enum('loggingdirection',
82        {
83            default       => 'both',
84            validsettings => [qw(in out both)],
85            summary       => "specifies which kind of messages should be logged",
86            description   => "Can be one of 'both', 'in', or 'out'.  If 'in' is\n"
87                           . "selected, only incoming messages are logged, if 'out'\n"
88                           . "is selected only outgoing messages are logged.  If 'both'\n"
89                           . "is selected both incoming and outgoing messages are\n"
90                           . "logged."
91        });
92
93    BarnOwl::new_variable_string('logbasepath',
94        {
95            default       => '~/zlog',
96            validsettings => '<path>',
97            summary       => 'path for logging non-zephyr messages',
98            description   => "Specifies a directory which must exist.\n"
99                           . "Each non-zephyr protocol gets its own subdirectory in\n"
100                           . "logbasepath, and messages get logged there."
101        });
102
103    BarnOwl::new_variable_string('logpath',
104        {
105            default       => '~/zlog/people',
106            validsettings => '<path>',
107            summary       => 'path for logging personal messages',
108            description   => "Specifies a directory which must exist.\n"
109                            . "Files will be created in the directory for each sender."
110        });
111
112    BarnOwl::new_variable_string('classlogpath',
113        {
114            default       => '~/zlog/class',
115            validsettings => '<path>',
116            summary       => 'path for logging class zephyrs',
117            description   => "Specifies a directory which must exist.\n"
118                           . "Files will be created in the directory for each class."
119        });
120}
121
122=head2 sanitize_filename BASE_PATH FILENAME
123
124Sanitizes C<FILENAME> and concatenates it with C<BASE_PATH>.
125
126In any filename, C<"/"> and any control characters (characters which
127match C<[:cntrl:]> get replaced by underscores.  If the resulting
128filename is empty or equal to C<"."> or C<"..">, it is replaced with
129C<"weird">.
130
131=cut
132
133sub sanitize_filename {
134    my $base_path = BarnOwl::Internal::makepath(shift);
135    my $filename = shift;
136    $filename =~ s/[[:cntrl:]\/]/_/g;
137    if ($filename eq '' || $filename eq '.' || $filename eq '..') {
138        $filename = 'weird';
139    }
140    # The original C code also removed characters less than '!' and
141    # greater than or equal to '~', marked file names beginning with a
142    # non-alphanumeric or non-ASCII character as 'weird', and rejected
143    # filenames longer than 35 characters.
144    return File::Spec->catfile($base_path, $filename);
145}
146
147=head2 get_filenames MESSAGE
148
149Returns a list of filenames in which to log the passed message.
150
151This method calls C<log_filenames> on C<MESSAGE> to determine the list
152of filenames to which C<MESSAGE> gets logged.  All filenames are
153relative to C<MESSAGE->log_path>.  If C<MESSAGE->log_to_all_file>
154returns true, then the filename C<"all"> is appended to the list of
155filenames.
156
157Filenames are sanitized by C<sanitize_filename>.
158
159=cut
160
161sub get_filenames {
162    my ($m) = @_;
163    my @filenames = $m->log_filenames;
164    push @filenames, 'all' if $m->log_to_all_file;
165    return map { sanitize_filename($m->log_path, $_) } @filenames;
166}
167
168=head2 should_log_message MESSAGE
169
170Determines whether or not the passed message should be logged.
171
172To customize the behavior of this method, override
173L<BarnOwl::Message::should_log>.
174
175=cut
176
177sub should_log_message {
178    my ($m) = @_;
179    # If there's a logfilter and this message matches it, log.
180    # pass quiet=1, because we don't care if the filter doesn't exist
181    return 1 if BarnOwl::message_matches_filter($m, BarnOwl::getvar('logfilter'), 1);
182    # otherwise we do things based on the logging variables
183    # skip login/logout messages if appropriate
184    return 0 if $m->is_loginout && BarnOwl::getvar('loglogins') eq 'off';
185    # check direction
186    return 0 if $m->is_outgoing && BarnOwl::getvar('loggingdirection') eq 'in';
187    return 0 if $m->is_incoming && BarnOwl::getvar('loggingdirection') eq 'out';
188    return $m->should_log;
189}
190
191=head2 log MESSAGE
192
193Call this method to (potentially) log a message.
194
195To customize the behavior of this method for your messages, override
196L<BarnOwl::Message::log>, L<BarnOwl::Message::should_log>,
197L<BarnOwl::Message::log_base_path>, and/or
198L<BarnOwl::Message::log_filenames>.
199
200=cut
201
202sub log {
203    my ($m) = @_;
204    return unless defined $m;
205    return unless BarnOwl::Logging::should_log_message($m);
206    my $log_text = $m->log;
207    foreach my $filename (BarnOwl::Logging::get_filenames($m)) {
208        BarnOwl::Logging::enqueue_text($log_text, $filename);
209    }
210}
211
212=head2 log_outgoing_error MESSAGE
213
214Call this method to (potentially) log an error in sending an
215outgoing message.  Errors get logged to the same file(s) as
216successful messages.
217
218To customize the behavior of this method for your messages, override
219L<BarnOwl::Message::log_outgoing_error>,
220L<BarnOwl::Message::should_log>,
221L<BarnOwl::Message::log_base_path>, and/or
222L<BarnOwl::Message::log_filenames>.
223
224=cut
225
226sub log_outgoing_error {
227    my ($m) = @_;
228    return unless BarnOwl::Logging::should_log_message($m);
229    my $log_text = $m->log_outgoing_error;
230    foreach my $filename (BarnOwl::Logging::get_filenames($m)) {
231        BarnOwl::Logging::enqueue_text($log_text, $filename);
232    }
233}
234
2351;
Note: See TracBrowser for help on using the repository browser.