2
# Kernel/Modules/SystemStats.pm - show stats of otrs
3
# Copyright (C) 2001-2005 Martin Edenhofer <martin+code@otrs.org>
5
# $Id: SystemStats.pm,v 1.24 2005/08/26 15:55:29 martin Exp $
7
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
8
# the enclosed file COPYING for license information (GPL). If you
9
# did not receive this file, see http://www.gnu.org/licenses/gpl.txt.
12
package Kernel::Modules::SystemStats;
16
use vars qw($VERSION);
17
$VERSION = '$Revision: 1.24 $ ';
18
$VERSION =~ s/^\$.*:\W(.*)\W.+?$/$1/;
25
# allocate new hash for object
30
foreach (keys %Param) {
31
$Self->{$_} = $Param{$_};
34
# check all needed objects
35
foreach (qw(ParamObject DBObject LayoutObject ConfigObject LogObject UserObject)) {
36
die "Got no $_" if (!$Self->{$_});
39
# if we need to do a fultext search on an external mirror database
40
if ($Self->{ConfigObject}->Get('Stats::DB::DSN')) {
41
my $ExtraDatabaseObject = Kernel::System::DB->new(
42
LogObject => $Param{LogObject},
43
ConfigObject => $Param{ConfigObject},
44
DatabaseDSN => $Self->{ConfigObject}->Get('Stats::DB::DSN'),
45
DatabaseUser => $Self->{ConfigObject}->Get('Stats::DB::User'),
46
DatabasePw => $Self->{ConfigObject}->Get('Stats::DB::Password'),
47
) || die $DBI::errstr;
48
$Self->{TicketObject} = Kernel::System::Ticket->new(
50
DBObject => $ExtraDatabaseObject,
60
if ($Self->{Subaction} eq '' || !$Self->{Subaction}) {
62
my $Output = $Self->{LayoutObject}->Header();
63
$Output .= $Self->{LayoutObject}->NavigationBar();
65
my %Config = %{$Self->{ConfigObject}->Get('SystemStatsMap')};
66
foreach my $Stats (sort keys %Config) {
67
if ($Self->{MainObject}->Require($Config{$Stats}->{Module})) {
68
my $StatsModule = $Config{$Stats}->{Module}->new(%{$Self});
70
my %OutputFormat = ();
71
foreach (@{$Config{$Stats}->{Output}}) {
72
$OutputFormat{$_} = $_;
74
$Param{OutputFormat} = $Self->{LayoutObject}->OptionStrgHashRef(
75
Data => \%OutputFormat,
77
SelectedID => $Config{$Stats}->{OutputDefault} || '',
79
$Self->{LayoutObject}->Block(
84
Param => $ParamString,
87
my @Params = $StatsModule->Param();
88
foreach my $ParamItem (@Params) {
89
$Self->{LayoutObject}->Block(
92
Param => $ParamItem->{Frontend},
93
Field => $Self->{LayoutObject}->OptionStrgHashRef(
94
Data => $ParamItem->{Data},
95
Name => $ParamItem->{Name},
96
SelectedID => $Config{$Stats}->{"$ParamItem->{Name}Default"} || $ParamItem->{SelectedID} || '',
97
Multiple => $ParamItem->{Multiple} || 0,
98
Size => $ParamItem->{Size} || '',
107
return $Self->{LayoutObject}->FatalError();
111
$Output .= $Self->{LayoutObject}->Output(
112
TemplateFile => 'SystemStats',
115
$Output .= $Self->{LayoutObject}->Footer();
118
elsif ($Self->{Subaction} eq 'Output') {
119
my $Module = $Self->{ParamObject}->GetParam(Param => 'Module');
120
my $Format = $Self->{ParamObject}->GetParam(Param => 'Format');
121
my %Config = %{$Self->{ConfigObject}->Get('SystemStatsMap')};
123
foreach my $Stats (sort keys %Config) {
124
if ($Config{$Stats}->{Module} eq $Module) {
125
%ConfigItem = %{$Config{$Stats}};
129
return $Self->{LayoutObject}->ErrorScreen(
130
Message => "No Config found for '$Module'!",
131
Comment => 'Please contact your admin'
134
if ($Self->{MainObject}->Require($Module)) {
136
my $StatsModule = $Module->new(%{$Self});
137
my @Params = $StatsModule->Param();
138
foreach my $ParamItem (@Params) {
139
if (!$ParamItem->{Multiple}) {
140
$GetParam{$ParamItem->{Name}} = $Self->{ParamObject}->GetParam(
141
Param => $ParamItem->{Name},
145
$GetParam{$ParamItem->{Name}} = [$Self->{ParamObject}->GetArray(
146
Param => $ParamItem->{Name},
152
# use result cache if configured
153
if ($ConfigItem{UseResultCache}) {
154
@Data = $Self->ReadResultCache(
155
GetParam => \%GetParam,
156
Config => \%ConfigItem,
159
# try to get data if noting is there
161
@Data = $StatsModule->Run(%GetParam,
165
$Self->WriteResultCache(
166
GetParam => \%GetParam,
167
Config => \%ConfigItem,
171
my $TitleArrayRef = shift (@Data);
172
my $Title = $TitleArrayRef->[0];
173
my $HeadArrayRef = shift (@Data);
174
if ($Format !~ /^Graph/) {
176
if ($ConfigItem{SumRow}) {
177
push (@{$HeadArrayRef}, 'Sum');
178
foreach my $Col (@Data) {
181
if ($_ =~ /^[0-9]{1,7}$/) {
185
push (@{$Col}, $Sum);
189
if ($ConfigItem{SumCol}) {
191
foreach my $Col (@Data) {
193
foreach my $Dig (@{$Col}) {
195
if ($Dig =~ /^[0-9]{1,7}$/) {
197
$R1[$Count] = $R1[$Count] + $Dig;
206
if (!defined($R1[0])) {
213
if ($Format eq 'CSV') {
214
$ConfigItem{Module} =~ s/^.*::(.+?)$/$1/;
215
my $Output = "$ConfigItem{Name}: $Title\n";
216
$Output .= $Self->{LayoutObject}->OutputCSV(
217
Head => $HeadArrayRef,
220
# return csv to download
221
my ($s,$m,$h, $D,$M,$Y) = $Self->{TimeObject}->SystemTime2Date(
222
SystemTime => $Self->{TimeObject}->SystemTime(),
224
$M = sprintf("%02d", $M);
225
$D = sprintf("%02d", $D);
226
$h = sprintf("%02d", $h);
227
$m = sprintf("%02d", $m);
228
return $Self->{LayoutObject}->Attachment(
229
Filename => "$ConfigItem{Module}"."_"."$Y-$M-$D"."_"."$h-$m.csv",
230
ContentType => "text/csv",
235
elsif ($Format =~ /^Graph(|Line|Bars|Pie)$/) {
238
my $Output = $Self->{LayoutObject}->Header();
239
$Output .= $Self->{LayoutObject}->Warning(
240
Message => 'No data for this time selection available!',
241
Comment => 'Please contact your admin'
243
$Output .= $Self->{LayoutObject}->Footer();
248
$GDBackend = 'GD::Graph::bars';
250
elsif ($1 eq 'Pie') {
251
$GDBackend = 'GD::Graph::pie';
254
$GDBackend = 'GD::Graph::lines';
257
foreach my $Module ('GD', 'GD::Graph', $GDBackend) {
258
if (!$Self->{MainObject}->Require($Module)) {
259
return $Self->{LayoutObject}->FatalError();
262
# remove first y/x position
263
my $XLable = shift (@{$HeadArrayRef});
264
# get first col for legend
266
foreach my $Tmp (@Data) {
267
push (@YLine, $Tmp->[0]);
271
my @PData = ($HeadArrayRef, @Data);
272
my ($XSize, $YSize) = split(/x/, $GetParam{GraphSize});
273
my $graph = $GDBackend->new($XSize || 550, $YSize || 350);
276
# y_label => 'YLable',
277
title => "$ConfigItem{Name}: $Title",
279
# y_tick_number => 16,
281
# x_tick_number => 8,
291
accentclr => 'black',
292
shadowclr => 'black',
293
legendclr => 'black',
295
dclrs => [ qw(red green blue yellow black purple orange pink marine cyan lgray lblue lyellow lgreen lred lpurple lorange lbrown) ],
297
x_label_position => 1/2, y_label_position => 1/2,
298
x_labels_vertical => 31,
301
legend_placement => 'BC', legend_spacing => 4,
302
legend_marker_width => 12, legend_marker_height => 8,
304
# set legend (y-line)
305
if ($Format ne 'GraphPie') {
306
$graph->set_legend(@YLine);
308
# return csv to download
309
my ($s,$m,$h, $D,$M,$Y) = $Self->{TimeObject}->SystemTime2Date(
310
SystemTime => $Self->{TimeObject}->SystemTime(),
312
$M = sprintf("%02d", $M);
313
$D = sprintf("%02d", $D);
314
$h = sprintf("%02d", $h);
315
$m = sprintf("%02d", $m);
316
$ConfigItem{Module} =~ s/^.*::(.+?)$/$1/;
319
if (!$graph->can('png')) {
323
$Ext = $graph->export_format;
324
$Self->{LogObject}->Log(
325
Priority => 'notice',
326
Message => "Can't write png! Write: $Ext",
329
# return image to bowser
330
return $Self->{LayoutObject}->Attachment(
331
Filename => "$ConfigItem{Module}"."_"."$Y-$M-$D"."_"."$h-$m.$Ext",
332
ContentType => "image/$Ext",
333
Content => $graph->plot(\@PData)->$Ext(),
339
my $Output = $Self->{LayoutObject}->PrintHeader(Value => $ConfigItem{Name});
340
$Output .= "$ConfigItem{Name}: $Title";
341
$Output .= $Self->{LayoutObject}->OutputHTMLTable(
342
Head => $HeadArrayRef,
346
$Output .= $Self->{LayoutObject}->PrintFooter();
351
return $Self->{LayoutObject}->FatalError();
355
$Self->{LogObject}->Log(
356
Message => 'No Subaction!!',
357
Comment => 'Please contact your admin'
359
return $Self->{LayoutObject}->ErrorScreen(
360
Message => 'No Subaction!!',
361
Comment => 'Please contact your admin'
366
sub WriteResultCache {
369
my %GetParam = %{$Param{GetParam}};
370
my %Config = %{$Param{Config}};
371
my @Data = @{$Param{Data}};
373
# check if we should cache this result
374
my ($s,$m,$h, $D,$M,$Y) = $Self->{TimeObject}->SystemTime2Date(
375
SystemTime => $Self->{TimeObject}->SystemTime(),
377
if ($GetParam{Year} && $GetParam{Month}) {
378
if ($Y > $GetParam{Year}) {
381
elsif ($GetParam{Year} == $Y && $GetParam{Month} <= $M) {
382
if ($GetParam{Month} < $M) {
385
if ($GetParam{Month} == $M && $GetParam{Day} && $GetParam{Day} < $D) {
390
# format month and day params
391
foreach (qw(Month Day)) {
392
$GetParam{$_} = sprintf("%02d", $GetParam{$_}) if ($GetParam{$_});
396
my $Path = $Self->{ConfigObject}->Get('TempDir');
397
my $File = $Config{Module};
399
if ($GetParam{Year}) {
400
$File .= "-$GetParam{Year}";
402
if ($GetParam{Month}) {
403
$File .= "-$GetParam{Month}";
405
if ($GetParam{Day}) {
406
$File .= "-$GetParam{Day}";
410
if (open (DATA, "> $Path/$File")) {
411
foreach my $Row (@Data) {
420
$Self->{LogObject}->Log(
422
Message => "Can't write: $Path/$File: $!",
429
sub ReadResultCache {
432
my %GetParam = %{$Param{GetParam}};
433
my %Config = %{$Param{Config}};
435
# format month and day params
436
foreach (qw(Month Day)) {
437
$GetParam{$_} = sprintf("%02d", $GetParam{$_}) if ($GetParam{$_});
440
my $Path = $Self->{ConfigObject}->Get('TempDir');
441
my $File = $Config{Module};
443
if ($GetParam{Year}) {
444
$File .= "-$GetParam{Year}";
446
if ($GetParam{Month}) {
447
$File .= "-$GetParam{Month}";
449
if ($GetParam{Day}) {
450
$File .= "-$GetParam{Day}";
453
if (open (DATA, "< $Path/$File")) {
455
my @Row = split(/;;/, $_);
461
$Self->{LogObject}->Log(
463
Message => "Can't open: $Path/$File: $!",