1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package Log;
require 5.006_001;
use strict;
use warnings;
use Sys::Hostname;
#initialize
my $VESPA_LOG_TARGET = $ENV{VESPA_LOG_TARGET} || "fd:2";
my $VESPA_LOG_LEVELS = $ENV{VESPA_LOG_LEVELS} || "all -debug -spam";
my $SERVICE = $ENV{VESPA_SERVICE_NAME} || "-";
my $HOST = hostname;
my %LEVEL = ( error => 0x01,
warning => 0x02,
info => 0x04,
config => 0x08,
debug => 0x10,
spam => 0x20,
all => 0x3f);
my %instance = ();
my $VESPA_LOG_FILTER;
foreach (split(/\s+/, $VESPA_LOG_LEVELS)) {
/(-?)(\S+)/ || die "Log level parse error: $_";
my ($inv, $value) = ($1, $LEVEL{$2});
die "Unknown level: $2" unless $value;
if ($inv) {
$VESPA_LOG_FILTER &= ~$value;
} else {
$VESPA_LOG_FILTER |= $value;
}
}
if ($VESPA_LOG_TARGET =~ /fd:(\d+)/) {
open(TARGET, ">&=$1") || die $!;
} elsif ($VESPA_LOG_TARGET =~ /file:(.+)/) {
open(TARGET, ">>$1") || die $!;
} else {
die "Illegal target $VESPA_LOG_TARGET";
}
select(TARGET); $| = 1;
sub new {
my ($self, $name) = @_;
my $type = ref($self) || $self;
$instance{$name} = bless { component => $name } unless $instance{$name};
return $instance{$name};
}
sub open_target {
return unless $VESPA_LOG_TARGET =~ /file:(.+)/;
close(TARGET);
open(TARGET, ">>$1") || die $!;
select(TARGET); $| = 1;
}
sub escape_message {
$_ = shift;
s/\n/\\n/g;
s/\r/\\r/g;
s/\t/\\t/g;
s/([\x80-\xFF])/sprintf("\\x%x",ord($1))/eg;
return $_;
}
sub log {
my ($this, $level, $msg) = @_;
my $component = ref($this) ? $this->{component} : "-";
die "Unknown logging level: '$level'" unless $LEVEL{$level};
return unless $VESPA_LOG_FILTER & $LEVEL{$level};
open_target;
$msg = escape_message($msg);
# format: time host pid service component level message
print TARGET (time()."\t$HOST\t$$\t$SERVICE\t$component\t$level\t$msg\n");
}
sub error { &log(shift, "error", @_); }
sub warning { &log(shift, "warning", @_); }
sub info { &log(shift, "info", @_); }
sub config { &log(shift, "config", @_); }
sub debug { &log(shift, "debug", @_); }
sub spam { &log(shift, "spam", @_); }
$SIG{__DIE__} = sub { Log->log("error", @_); };
$SIG{__WARN__} = sub { Log->log("warning", @_); };
|