Loeblich, Doku wollte ich schon immer haben.
[kivitendo-erp.git] / SL / LXDebug.pm
1 package LXDebug;
2
3 use constant NONE   => 0;
4 use constant INFO   => 1;
5 use constant DEBUG1 => 2;
6 use constant DEBUG2 => 4;
7 use constant QUERY  => 8;
8 use constant TRACE  => 16;
9 use constant ALL    => 31;
10
11 use constant FILE_TARGET   => 0;
12 use constant STDERR_TARGET => 1;
13
14 use POSIX qw(strftime);
15
16 my $data_dumper_available;
17
18 BEGIN {
19   eval("use Data::Dumper");
20   $data_dumper_available = $@ ? 0 : 1;
21
22   $global_level      = NONE;
23 }
24
25 sub new {
26   my $type = shift;
27   my $self = {};
28
29   $self->{"calldepth"}  = 0;
30   $self->{"file"}       = "/tmp/lx-office-debug.log";
31   $self->{"target"}     = FILE_TARGET;
32   $self->{"level"}      = 0;
33
34   while ($_[0]) {
35     $self->{ $_[0] } = $_[1];
36     shift;
37     shift;
38   }
39
40   bless($self, $type);
41 }
42
43 sub set_target {
44   my ($self, $target, $file) = @_;
45
46   if ((FILE_TARGET == $target) && $file) {
47     $self->{"file"}   = $file;
48     $self->{"target"} = FILE_TARGET;
49
50   } elsif (STDERR_TARGET == $target) {
51     $self->{"target"} = STDERR_TARGET;
52   }
53 }
54
55 sub enter_sub {
56   my ($self, $level) = @_;
57   $level *= 1;
58
59   return 1 unless ($global_level & TRACE);          # ignore if traces aren't active
60   return 1 if $level && !($global_level & $level);  # ignore if level of trace isn't active
61
62   my ($package, $filename, $line, $subroutine) = caller(1);
63   my ($dummy1, $self_filename, $self_line) = caller(0);
64
65   my $indent = " " x $self->{"calldepth"}++;
66
67   if (!defined($package)) {
68     $self->_write('sub' . $level, $indent . "\\ top-level?\n");
69   } else {
70     $self->_write('sub' . $level, $indent
71                     . "\\ ${subroutine} in "
72                     . "${self_filename}:${self_line} called from "
73                     . "${filename}:${line}\n");
74   }
75   return 1;
76 }
77
78 sub leave_sub {
79   my ($self, $level) = @_;
80   $level *= 1;
81
82   return 1 unless ($global_level & TRACE);           # ignore if traces aren't active
83   return 1 if $level && !($global_level & $level);   # ignore if level of trace isn't active
84
85   my ($package, $filename, $line, $subroutine) = caller(1);
86   my ($dummy1, $self_filename, $self_line) = caller(0);
87
88   my $indent = " " x --$self->{"calldepth"};
89
90   if (!defined($package)) {
91     $self->_write('sub' . $level, $indent . "/ top-level?\n");
92   } else {
93     $self->_write('sub' . $level, $indent . "/ ${subroutine} in " . "${self_filename}:${self_line}\n");
94   }
95   return 1;
96 }
97
98 sub message {
99   my ($self, $level, $message) = @_;
100   $self->_write(level2string($level), $message) if (($self->{"level"} | $global_level) & $level || !$level);
101 }
102
103 sub dump {
104   my ($self, $level, $name, $variable) = @_;
105
106   if ($data_dumper_available) {
107     $self->message($level, "dumping ${name}:\n" . Dumper($variable));
108   } else {
109     $self->message($level,
110                    "dumping ${name}: Data::Dumper not available; "
111                      . "variable cannot be dumped");
112   }
113 }
114
115 sub enable_sub_tracing {
116   my ($self) = @_;
117   $self->{level} | TRACE;
118 }
119
120 sub disable_sub_tracing {
121   my ($self) = @_;
122   $self->{level} & ~ TRACE;
123 }
124
125 sub _write {
126   my ($self, $prefix, $message) = @_;
127   my $date = strftime("%Y-%m-%d %H:%M:%S $$ ${prefix}: ", localtime(time()));
128   local *FILE;
129
130   chomp($message);
131
132   if ((FILE_TARGET == $self->{"target"})
133       && open(FILE, ">>" . $self->{"file"})) {
134     print(FILE "${date}${message}\n");
135     close(FILE);
136
137       } elsif (STDERR_TARGET == $self->{"target"}) {
138     print(STDERR "${date}${message}\n");
139   }
140 }
141
142 sub level2string {
143   # use $_[0] as a bit mask and return levelstrings separated by /
144   join '/', qw(info debug1 debug2 query trace)[ grep { (reverse split //, sprintf "%05b", $_[0])[$_] } 0..4 ]
145 }
146
147 1;