1# --
2# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/
3# --
4# This software comes with ABSOLUTELY NO WARRANTY. For details, see
5# the enclosed file COPYING for license information (GPL). If you
6# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
7# --
8
9package Kernel::System::GenericInterface::DebugLog;
10
11use strict;
12use warnings;
13
14use Kernel::System::VariableCheck qw(:all);
15
16our @ObjectDependencies = (
17    'Kernel::System::Cache',
18    'Kernel::System::DB',
19    'Kernel::System::Log',
20);
21
22=head1 NAME
23
24Kernel::System::GenericInterface::DebugLog - log interface for generic interface
25
26=head1 DESCRIPTION
27
28All log functions.
29
30=head1 PUBLIC INTERFACE
31
32=head2 new()
33
34create a debug log object. Do not use it directly, instead use:
35
36    my $DebugLogObject = $Kernel::OM->Get('Kernel::System::GenericInterface::DebugLog');
37
38=cut
39
40sub new {
41    my ( $Type, %Param ) = @_;
42
43    # allocate new hash for object
44    my $Self = {};
45    bless( $Self, $Type );
46
47    $Self->{CacheType} = 'GenericInterfaceDebugLog';
48    $Self->{CacheTTL}  = 60 * 60 * 24 * 20;
49
50    return $Self;
51}
52
53=head2 LogAdd()
54
55add a communication bit to database
56if we don't already have a communication chain, create it
57
58returns 1 on success or undef on error
59
60    my $Success = $DebugLogObject->LogAdd(
61        CommunicationID   => '6f1ed002ab5595859014ebf0951522d9',
62        CommunicationType => 'Provider',        # 'Provider' or 'Requester'
63        Data              => 'additional data' # optional
64        DebugLevel        => 'info',           # 'debug', 'info', 'notice', 'error'
65        RemoteIP          => '192.168.0.1',    # optional, must be valid IPv4 or IPv6 address
66        Summary           => 'description of log entry',
67        WebserviceID      => 1,
68    );
69
70=cut
71
72sub LogAdd {
73    my ( $Self, %Param ) = @_;
74
75    # check needed params
76    NEEDED:
77    for my $Needed (qw(CommunicationID CommunicationType DebugLevel Summary WebserviceID))
78    {
79        next NEEDED if IsStringWithData( $Param{$Needed} );
80
81        $Kernel::OM->Get('Kernel::System::Log')->Log(
82            Priority => 'error',
83            Message  => "Need $Needed as a string!",
84        );
85        return;
86    }
87
88    # param syntax check
89    if ( !IsMD5Sum( $Param{CommunicationID} ) ) {
90        $Kernel::OM->Get('Kernel::System::Log')->Log(
91            Priority => 'error',
92            Message  => 'CommunicationID is not an md5sum!',
93        );
94        return;
95    }
96    if ( $Param{CommunicationType} !~ m{ \A (?: Provider | Requester ) \z }xms ) {
97        $Kernel::OM->Get('Kernel::System::Log')->Log(
98            Priority => 'error',
99            Message  => "CommunicationType '$Param{CommunicationType}' is not valid!",
100        );
101        return;
102    }
103    if (
104        defined $Param{RemoteIP} &&
105        $Param{RemoteIP} ne ''
106        )
107    {
108        if ( !IsStringWithData( $Param{RemoteIP} ) ) {
109            $Kernel::OM->Get('Kernel::System::Log')->Log(
110                Priority => 'error',
111                Message  => "RemoteIP '$Param{RemoteIP}' is not a valid IPv4 or IPv6 address!",
112            );
113            return;
114        }
115        if ( !IsIPv4Address( $Param{RemoteIP} ) && !IsIPv6Address( $Param{RemoteIP} ) ) {
116            $Kernel::OM->Get('Kernel::System::Log')->Log(
117                Priority => 'error',
118                Message  => "RemoteIP '$Param{RemoteIP}' is not a valid IPv4 or IPv6 address!",
119            );
120            return;
121        }
122    }
123    if ( !IsPositiveInteger( $Param{WebserviceID} ) ) {
124        $Kernel::OM->Get('Kernel::System::Log')->Log(
125            Priority => 'error',
126            Message  => 'WebserviceID is not a positive integer!',
127        );
128        return;
129    }
130    KEY:
131    for my $Key (qw(Data DebugLevel Summary)) {
132        next KEY if !defined $Param{$Key};
133        if ( !IsString( $Param{$Key} ) ) {
134            $Kernel::OM->Get('Kernel::System::Log')->Log(
135                Priority => 'error',
136                Message  => "$Key is not a string!",
137            );
138            return;
139        }
140    }
141
142    # check if we have a communication chain already
143    my $LogData = $Self->LogGet(
144        CommunicationID => $Param{CommunicationID},
145    );
146    if ( !IsHashRefWithData($LogData) ) {
147
148        # no entry yet, create one
149        return if !$Self->_LogAddChain(
150            CommunicationID   => $Param{CommunicationID},
151            CommunicationType => $Param{CommunicationType},
152            RemoteIP          => $Param{RemoteIP},
153            WebserviceID      => $Param{WebserviceID},
154        );
155        $LogData = $Self->LogGet(
156            CommunicationID => $Param{CommunicationID},
157        );
158    }
159    else {
160
161        # match param against existing chain
162        KEY:
163        for my $Key (qw(CommunicationType RemoteIP WebserviceID)) {
164            next KEY if !defined $Param{$Key};
165            next KEY if $Param{$Key} eq $LogData->{$Key};
166
167            $Kernel::OM->Get('Kernel::System::Log')->Log(
168                Priority => 'error',
169                Message  => "$Key does not match current value for this CommunicationID!",
170            );
171            return;
172        }
173    }
174
175    # create entry
176    if (
177        !$Kernel::OM->Get('Kernel::System::DB')->Do(
178            SQL =>
179                'INSERT INTO gi_debugger_entry_content'
180                . ' (content, create_time, debug_level, gi_debugger_entry_id, subject)'
181                . ' VALUES (?, current_timestamp, ?, ?, ?)',
182            Bind => [
183                \$Param{Data}, \$Param{DebugLevel}, \$LogData->{LogID}, \$Param{Summary},
184            ],
185        )
186        )
187    {
188        $Kernel::OM->Get('Kernel::System::Log')->Log(
189            Priority => 'error',
190            Message  => 'Could not create debug entry in db!',
191        );
192        return;
193    }
194
195    return 1;
196}
197
198=head2 LogGet()
199
200get communication chain data
201
202    my $LogData = $DebugLogObject->LogGet(
203        CommunicationID => '6f1ed002ab5595859014ebf0951522d9',
204    );
205
206    $LogData = {
207        CommunicationID   => '6f1ed002ab5595859014ebf0951522d9',
208        CommunicationType => 'Provider',
209        Created           => '2011-02-15 16:47:28',
210        LogID             => 1,
211        RemoteIP          => '192.168.0.1', # optional
212        WebserviceID      => 1,
213    };
214
215=cut
216
217sub LogGet {
218    my ( $Self, %Param ) = @_;
219
220    # check needed param
221    if ( !IsMD5Sum( $Param{CommunicationID} ) ) {
222        $Kernel::OM->Get('Kernel::System::Log')->Log(
223            Priority => 'error',
224            Message  => 'CommunicationID is not an md5sum!',
225        );
226        return;
227    }
228
229    # check cache
230    my $Cache = $Kernel::OM->Get('Kernel::System::Cache')->Get(
231        Type => $Self->{CacheType},
232        Key  => 'LogGet::' . $Param{CommunicationID},
233    );
234    return $Cache if $Cache;
235
236    # get database object
237    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
238
239    # prepare db request
240    if (
241        !$DBObject->Prepare(
242            SQL =>
243                'SELECT communication_id, communication_type, create_time, id, remote_ip,'
244                . ' webservice_id FROM gi_debugger_entry WHERE communication_id = ?',
245            Bind  => [ \$Param{CommunicationID} ],
246            Limit => 1,
247        )
248        )
249    {
250        $Kernel::OM->Get('Kernel::System::Log')->Log(
251            Priority => 'error',
252            Message  => 'Could not prepare db query!',
253        );
254        return;
255    }
256
257    # read data
258    my %LogData;
259    while ( my @Row = $DBObject->FetchrowArray() ) {
260        %LogData = (
261            CommunicationID   => $Row[0],
262            CommunicationType => $Row[1],
263            Created           => $Row[2],
264            LogID             => $Row[3],
265            RemoteIP          => $Row[4] || '',
266            WebserviceID      => $Row[5],
267        );
268    }
269
270    return if !%LogData;
271
272    # set cache
273    $Kernel::OM->Get('Kernel::System::Cache')->Set(
274        Type  => $Self->{CacheType},
275        TTL   => $Self->{CacheTTL},
276        Key   => 'LogGet::' . $Param{CommunicationID},
277        Value => \%LogData,
278    );
279
280    return \%LogData;
281}
282
283=head2 LogGetWithData()
284
285get all individual entries for a communication chain
286
287    my $LogData = $DebugLogObject->LogGetWithData(
288        CommunicationID => '6f1ed002ab5595859014ebf0951522d9',
289    );
290
291    $LogData = {
292        CommunicationID   => '6f1ed002ab5595859014ebf0951522d9',
293        CommunicationType => 'Provider',
294        Created           => '2011-02-15 16:47:28',
295        LogID             => 1,
296        RemoteIP          => '192.168.0.1', # optional
297        WebserviceID      => 1,
298        Data              => [
299            {
300                Created    => '2011-02-15 17:00:06',
301                Data       => 'some logging specific data or structure', # optional
302                DebugLevel => 'info',
303                Summary    => 'a log bit',
304            },
305            ...
306        ],
307    };
308
309=cut
310
311sub LogGetWithData {
312    my ( $Self, %Param ) = @_;
313
314    # check needed param
315    if ( !IsMD5Sum( $Param{CommunicationID} ) ) {
316        $Kernel::OM->Get('Kernel::System::Log')->Log(
317            Priority => 'error',
318            Message  => 'CommunicationID is not an md5sum!',
319        );
320        return;
321    }
322
323    # check if we have data for this communication id
324    my $LogData = $Self->LogGet(
325        CommunicationID => $Param{CommunicationID},
326    );
327    if ( !IsHashRefWithData($LogData) ) {
328        $Kernel::OM->Get('Kernel::System::Log')->Log(
329            Priority => 'error',
330            Message  => 'Could not get communication chain!',
331        );
332        return;
333    }
334
335    # get database object
336    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
337
338    # prepare db request
339    if (
340        !$DBObject->Prepare(
341            SQL =>
342                'SELECT create_time, content, debug_level, subject'
343                . ' FROM gi_debugger_entry_content WHERE gi_debugger_entry_id = ?'
344                . ' ORDER BY create_time ASC, id ASC',
345            Bind => [ \$LogData->{LogID} ],
346        )
347        )
348    {
349        $Kernel::OM->Get('Kernel::System::Log')->Log(
350            Priority => 'error',
351            Message  => 'Could not prepare db query!',
352        );
353        return;
354    }
355
356    # read data
357    my @LogDataEntries;
358    while ( my @Row = $DBObject->FetchrowArray() ) {
359        my %SingleEntry = (
360            Created    => $Row[0],
361            Data       => $Row[1] || '',
362            DebugLevel => $Row[2],
363            Summary    => $Row[3],
364        );
365        push @LogDataEntries, \%SingleEntry;
366    }
367
368    $LogData->{Data} = \@LogDataEntries;
369    return $LogData;
370}
371
372=head2 LogDelete()
373
374delete a complete communication chain
375
376returns 1 if successful or undef otherwise
377
378    my $Success = $DebugLogObject->LogDelete(
379        NoErrorIfEmpty  => 1,                                  # optional
380        CommunicationID => '6f1ed002ab5595859014ebf0951522d9', # optional
381        WebserviceID    => 1,                                  # optional
382                                                               # exactly one id parameter required
383    );
384
385=cut
386
387sub LogDelete {
388    my ( $Self, %Param ) = @_;
389
390    # check needed params
391    my $CommunicationIDValid = IsMD5Sum( $Param{CommunicationID} );
392    if ( $Param{CommunicationID} && !$CommunicationIDValid ) {
393        $Kernel::OM->Get('Kernel::System::Log')->Log(
394            Priority => 'error',
395            Message  => 'CommunicationID is not an md5sum!',
396        );
397        return;
398    }
399    my $WebserviceIDValid = IsPositiveInteger( $Param{WebserviceID} );
400    if ( $Param{WebserviceID} && !$WebserviceIDValid ) {
401        $Kernel::OM->Get('Kernel::System::Log')->Log(
402            Priority => 'error',
403            Message  => 'WebserviceID is not a positive integer!',
404        );
405        return;
406    }
407    if (
408        ( !$CommunicationIDValid && !$WebserviceIDValid )
409        ||
410        ( $CommunicationIDValid && $WebserviceIDValid )
411        )
412    {
413        $Kernel::OM->Get('Kernel::System::Log')->Log(
414            Priority => 'error',
415            Message  => 'Need exactly one of CommunicationID or WebserviceID!',
416        );
417        return;
418    }
419
420    # check if we have data for this param
421    if ($CommunicationIDValid) {
422        my $LogData = $Self->LogGet(
423            CommunicationID => $Param{CommunicationID},
424        );
425        if ( !IsHashRefWithData($LogData) ) {
426            return 1 if $Param{NoErrorIfEmpty};
427            $Kernel::OM->Get('Kernel::System::Log')->Log(
428                Priority => 'error',
429                Message  => 'Communication chain does not exist!',
430            );
431            return;
432        }
433    }
434    else {
435        my $LogData = $Self->LogSearch(
436            Limit        => 1,
437            WebserviceID => $Param{WebserviceID},
438        );
439        if ( !IsArrayRefWithData($LogData) ) {
440            return 1 if $Param{NoErrorIfEmpty};
441            $Kernel::OM->Get('Kernel::System::Log')->Log(
442                Priority => 'error',
443                Message  => 'Communication chain does not exist!',
444            );
445            return;
446        }
447    }
448
449    # delete individual entries first
450    my $SQLIndividual =
451        'DELETE FROM gi_debugger_entry_content
452        WHERE gi_debugger_entry_id in( SELECT id FROM gi_debugger_entry ';
453    my @BindIndividual;
454    if ($CommunicationIDValid) {
455        $SQLIndividual .= 'WHERE communication_id = ?';
456        push @BindIndividual, \$Param{CommunicationID};
457    }
458    else {
459        $SQLIndividual .= 'WHERE  webservice_id = ?';
460        push @BindIndividual, \$Param{WebserviceID};
461    }
462    $SQLIndividual .= ' )';
463
464    # get database object
465    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
466
467    if (
468        !$DBObject->Do(
469            SQL  => $SQLIndividual,
470            Bind => \@BindIndividual,
471        )
472        )
473    {
474        $Kernel::OM->Get('Kernel::System::Log')->Log(
475            Priority => 'error',
476            Message  => 'Could not remove entries of communication chain in db!',
477        );
478        return;
479    }
480
481    # delete main entry
482    my $SQLMain = 'DELETE FROM gi_debugger_entry WHERE';
483    my @BindMain;
484    if ($CommunicationIDValid) {
485        $SQLMain .= ' communication_id = ?';
486        push @BindMain, \$Param{CommunicationID};
487    }
488    else {
489        $SQLMain .= ' webservice_id = ?';
490        push @BindMain, \$Param{WebserviceID};
491    }
492    if (
493        !$DBObject->Do(
494            SQL  => $SQLMain,
495            Bind => \@BindMain,
496        )
497        )
498    {
499        $Kernel::OM->Get('Kernel::System::Log')->Log(
500            Priority => 'error',
501            Message  => 'Could not remove communication chain in db!',
502        );
503        return;
504    }
505
506    # clean cache
507    $Kernel::OM->Get('Kernel::System::Cache')->CleanUp(
508        Type => $Self->{CacheType},
509    );
510
511    return 1;
512}
513
514=head2 LogSearch()
515
516search for log chains based on several criteria
517when the parameter 'WithData' is set, the complete communication chains will be returned
518
519    my $LogData = $DebugLogObject->LogSearch(
520        CommunicationID   => '6f1ed002ab5595859014ebf0951522d9', # optional
521        CommunicationType => 'Provider',     # optional, 'Provider' or 'Requester'
522        CreatedAtOrAfter  => '2011-01-01 00:00:00', # optional
523        CreatedAtOrBefore => '2011-12-31 23:59:59', # optional
524        Limit             => 1000, # optional, default 100
525        RemoteIP          => '192.168.0.1', # optional, must be valid IPv4 or IPv6 address
526        WebserviceID      => 1, # optional
527        WithData          => 0, # optional
528        Sort              => 'ASC', # optional. 'ASC' (default) or 'DESC'
529    );
530
531    $LogData = [
532        {
533            CommunicationID   => '6f1ed002ab5595859014ebf0951522d9',
534            CommunicationType => 'Provider',
535            Created           => '2011-02-15 16:47:28',
536            LogID             => 1,
537            RemoteIP          => '192.168.0.1', # optional
538            WebserviceID      => 1,
539            Data              => [ # only when 'WithData' is set
540                {
541                    Created    => '2011-02-15 17:00:06',
542                    Data       => 'some logging specific data or structure', # optional
543                    DebugLevel => 'info',
544                    Summary    => 'a log bit',
545                },
546                ...
547            ],
548        },
549        ...
550    ];
551
552=cut
553
554sub LogSearch {
555    my ( $Self, %Param ) = @_;
556
557    # param check
558    KEY:
559    for my $Key (
560        qw(CommunicationID CommunicationType CreatedAtOrAfter CreatedAtOrBefore Limit RemoteIP WebserviceID WithData)
561        )
562    {
563        next KEY if !defined $Param{$Key};
564        next KEY if IsStringWithData( $Param{$Key} );
565
566        $Kernel::OM->Get('Kernel::System::Log')->Log(
567            Priority => 'error',
568            Message  => "Need $Key as a string!",
569        );
570        return;
571    }
572
573    # param syntax check
574    if ( $Param{CommunicationID} && !IsMD5Sum( $Param{CommunicationID} ) ) {
575        $Kernel::OM->Get('Kernel::System::Log')->Log(
576            Priority => 'error',
577            Message  => 'CommunicationID is not an md5sum!',
578        );
579        return;
580    }
581    if (
582        $Param{CommunicationType}
583        && $Param{CommunicationType} !~ m{ \A (?: Provider | Requester ) \z }xms
584        )
585    {
586        $Kernel::OM->Get('Kernel::System::Log')->Log(
587            Priority => 'error',
588            Message  => "CommunicationType '$Param{CommunicationType}' is not valid!",
589        );
590        return;
591    }
592    KEY:
593    for my $Key (qw(CreatedAtOrAfter CreatedAtOrBefore)) {
594        next KEY if !$Param{$Key};
595        next KEY if $Param{$Key} =~ m{
596                \A \d{4} - \d{2} - \d{2} [ ] \d{2} : \d{2} : \d{2} \z
597            }xms;
598
599        $Kernel::OM->Get('Kernel::System::Log')->Log(
600            Priority => 'error',
601            Message  => "$Key '$Param{$Key}' is not valid!",
602        );
603        return;
604    }
605    if ( $Param{Limit} && !IsPositiveInteger( $Param{Limit} ) ) {
606        $Kernel::OM->Get('Kernel::System::Log')->Log(
607            Priority => 'error',
608            Message  => 'Limit is not a positive integer!',
609        );
610        return;
611    }
612    if (
613        defined $Param{RemoteIP} &&
614        $Param{RemoteIP} ne ''
615        )
616    {
617        if ( !IsStringWithData( $Param{RemoteIP} ) ) {
618            $Kernel::OM->Get('Kernel::System::Log')->Log(
619                Priority => 'error',
620                Message  => "RemoteIP '$Param{RemoteIP}' is not a valid IPv4 or IPv6 address!",
621            );
622            return;
623        }
624        if ( !IsIPv4Address( $Param{RemoteIP} ) && !IsIPv6Address( $Param{RemoteIP} ) ) {
625            $Kernel::OM->Get('Kernel::System::Log')->Log(
626                Priority => 'error',
627                Message  => "RemoteIP '$Param{RemoteIP}' is not a valid IPv4 or IPv6 address!",
628            );
629            return;
630        }
631    }
632    if ( $Param{WebserviceID} && !IsPositiveInteger( $Param{WebserviceID} ) ) {
633        $Kernel::OM->Get('Kernel::System::Log')->Log(
634            Priority => 'error',
635            Message  => 'WebserviceID is not a positive integer!',
636        );
637        return;
638    }
639    if ( $Param{WithData} && $Param{WithData} !~ m{ \A [01] \z }xms ) {
640        $Kernel::OM->Get('Kernel::System::Log')->Log(
641            Priority => 'error',
642            Message  => 'WebserviceID is not a positive integer!',
643        );
644        return;
645    }
646    if (
647        IsStringWithData( $Param{Sort} )
648        && $Param{Sort} ne 'ASC'
649        && $Param{Sort} ne 'DESC'
650        )
651    {
652        $Kernel::OM->Get('Kernel::System::Log')->Log(
653            Priority => 'error',
654            Message  => "Sort must be 'DESC' or 'ASC'!",
655        );
656        return;
657    }
658
659    # prepare db request
660    my $SQL =
661        'SELECT communication_id, communication_type, id, remote_ip, webservice_id, create_time'
662        . ' FROM gi_debugger_entry';
663    my @Bind     = ();
664    my $SQLExt   = '';
665    my %NameToDB = (
666        CommunicationID   => 'communication_id',
667        CommunicationType => 'communication_type',
668        RemoteIP          => 'remote_ip',
669        WebserviceID      => 'webservice_id',
670    );
671
672    OPTION:
673    for my $Option (qw(CommunicationID CommunicationType RemoteIP WebserviceID)) {
674        next OPTION if !$Param{$Option};
675        my $Type = $SQLExt ? 'AND' : 'WHERE';
676        $SQLExt .= " $Type $NameToDB{$Option} = ?";
677        push @Bind, \$Param{$Option};
678    }
679
680    if ( $Param{CreatedAtOrAfter} ) {
681        my $Type = $SQLExt ? 'AND' : 'WHERE';
682        $SQLExt .= " $Type create_time >= ?";
683        push @Bind, \$Param{CreatedAtOrAfter};
684    }
685
686    if ( $Param{CreatedAtOrBefore} ) {
687        my $Type = $SQLExt ? 'AND' : 'WHERE';
688        $SQLExt .= " $Type create_time <= ?";
689        push @Bind, \$Param{CreatedAtOrBefore};
690    }
691
692    my $SQLSort = IsStringWithData( $Param{Sort} ) ? $Param{Sort} : 'ASC';
693    $SQLExt .= ' ORDER BY create_time ' . $SQLSort;
694
695    # get database object
696    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
697
698    if (
699        !$DBObject->Prepare(
700            SQL   => $SQL . $SQLExt,
701            Bind  => \@Bind,
702            Limit => $Param{Limit} || 100,
703        )
704        )
705    {
706        $Kernel::OM->Get('Kernel::System::Log')->Log(
707            Priority => 'error',
708            Message  => 'Could not prepare db query!',
709        );
710        return;
711    }
712
713    # read data
714    my @LogEntries;
715    while ( my @Row = $DBObject->FetchrowArray() ) {
716        my %SingleEntry = (
717            CommunicationID   => $Row[0],
718            CommunicationType => $Row[1],
719            LogID             => $Row[2],
720            RemoteIP          => $Row[3] || '',
721            WebserviceID      => $Row[4],
722            Created           => $Row[5],
723        );
724        push @LogEntries, \%SingleEntry;
725    }
726
727    # done if we only need main entries
728    return \@LogEntries if !$Param{WithData};
729
730    # we need individual entries
731    my @LogEntriesWithData;
732    for my $Entry (@LogEntries) {
733        my $LogData = $Self->LogGetWithData(
734            CommunicationID => $Entry->{CommunicationID},
735        );
736        return if !$LogData;
737        push @LogEntriesWithData, $LogData;
738    }
739
740    return \@LogEntriesWithData;
741}
742
743=head2 LogCleanup()
744
745removes all log entries (including content) from a given time and before.
746
747returns 1 if successful or undef otherwise
748
749    my $Success = $DebugLogObject->LogCleanup(
750        CreatedAtOrBefore => '2011-12-31 23:59:59',
751    );
752
753=cut
754
755sub LogCleanup {
756    my ( $Self, %Param ) = @_;
757
758    if ( !$Param{CreatedAtOrBefore} ) {
759        $Kernel::OM->Get('Kernel::System::Log')->Log(
760            Priority => 'error',
761            Message  => "Need CreatedAtOrBefore",
762        );
763
764        return;
765    }
766
767    if ( $Param{CreatedAtOrBefore} !~ m{ \A \d{4} - \d{2} - \d{2} [ ] \d{2} : \d{2} : \d{2} \z }xms ) {
768
769        $Kernel::OM->Get('Kernel::System::Log')->Log(
770            Priority => 'error',
771            Message  => "CreatedAtOrBefore is not valid!",
772        );
773        return;
774    }
775
776    my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime');
777    my $Success        = $DateTimeObject->Set( String => $Param{CreatedAtOrBefore} );
778    if ( !$Success ) {
779
780        $Kernel::OM->Get('Kernel::System::Log')->Log(
781            Priority => 'error',
782            Message  => "CreatedAtOrBefore is not valid!",
783        );
784        return;
785    }
786
787    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
788
789    # Get main debug log entries to delete
790    if (
791        !$DBObject->Prepare(
792            SQL  => 'SELECT id FROM gi_debugger_entry WHERE create_time <= ?',
793            Bind => [ \$Param{CreatedAtOrBefore} ],
794        )
795        )
796    {
797        $Kernel::OM->Get('Kernel::System::Log')->Log(
798            Priority => 'error',
799            Message  => 'Could not prepare db query!',
800        );
801        return;
802    }
803    my @LogEntryIDs;
804    while ( my @Row = $DBObject->FetchrowArray() ) {
805        push @LogEntryIDs, $Row[0];
806    }
807
808    return 1 if !@LogEntryIDs;
809
810    my $LogEntryIDsStr = join ',', @LogEntryIDs;
811
812    # Remove debug log entries contents.
813    if (
814        !$DBObject->Do(
815            SQL => "
816            DELETE FROM gi_debugger_entry_content
817            WHERE gi_debugger_entry_id in( $LogEntryIDsStr )",
818        )
819        )
820    {
821        $Kernel::OM->Get('Kernel::System::Log')->Log(
822            Priority => 'error',
823            Message  => 'Could not remove entries of communication chains in db!',
824        );
825        return;
826    }
827
828    # Remove debug log entries.
829    if (
830        !$DBObject->Do(
831            SQL => "
832            DELETE FROM gi_debugger_entry
833            WHERE id in( $LogEntryIDsStr )",
834        )
835        )
836    {
837        $Kernel::OM->Get('Kernel::System::Log')->Log(
838            Priority => 'error',
839            Message  => 'Could not remove communication chains in db!',
840        );
841        return;
842    }
843
844    return 1;
845}
846
847=begin Internal:
848
849=cut
850
851=head2 _LogAddChain()
852
853establish communication chain in database
854
855returns 1 on success or undef on error
856
857    my $Success = $DebugLogObject->_LogAddChain(
858        CommunicationID   => '6f1ed002ab5595859014ebf0951522d9',
859        CommunicationType => 'Provider',     # 'Provider' or 'Requester'
860        RemoteIP          => '192.168.0.1', # optional, must be valid IPv4 or IPv6 address
861        WebserviceID      => 1,
862    );
863
864=cut
865
866sub _LogAddChain {
867    my ( $Self, %Param ) = @_;
868
869    # check needed params
870    NEEDED:
871    for my $Needed (qw(CommunicationID CommunicationType WebserviceID)) {
872        next NEEDED if IsStringWithData( $Param{$Needed} );
873
874        $Kernel::OM->Get('Kernel::System::Log')->Log(
875            Priority => 'error',
876            Message  => "Need $Needed as a string!",
877        );
878        return;
879    }
880
881    # param syntax check
882    if ( !IsMD5Sum( $Param{CommunicationID} ) ) {
883        $Kernel::OM->Get('Kernel::System::Log')->Log(
884            Priority => 'error',
885            Message  => 'CommunicationID is not an md5sum!',
886        );
887        return;
888    }
889    if ( $Param{CommunicationType} !~ m{ \A (?: Provider | Requester ) \z }xms ) {
890        $Kernel::OM->Get('Kernel::System::Log')->Log(
891            Priority => 'error',
892            Message  => "CommunicationType '$Param{CommunicationType}' is not valid!",
893        );
894        return;
895    }
896    if (
897        defined $Param{RemoteIP} &&
898        $Param{RemoteIP} ne ''
899        )
900    {
901        if ( !IsStringWithData( $Param{RemoteIP} ) ) {
902            $Kernel::OM->Get('Kernel::System::Log')->Log(
903                Priority => 'error',
904                Message  => "RemoteIP '$Param{RemoteIP}' is not a valid IPv4 or IPv6 address!",
905            );
906            return;
907        }
908        if ( !IsIPv4Address( $Param{RemoteIP} ) && !IsIPv6Address( $Param{RemoteIP} ) ) {
909            $Kernel::OM->Get('Kernel::System::Log')->Log(
910                Priority => 'error',
911                Message  => "RemoteIP '$Param{RemoteIP}' is not a valid IPv4 or IPv6 address!",
912            );
913            return;
914        }
915    }
916    if ( !IsPositiveInteger( $Param{WebserviceID} ) ) {
917        $Kernel::OM->Get('Kernel::System::Log')->Log(
918            Priority => 'error',
919            Message  => 'WebserviceID is not a positive integer!',
920        );
921        return;
922    }
923
924    if (
925        !$Kernel::OM->Get('Kernel::System::DB')->Do(
926            SQL =>
927                'INSERT INTO gi_debugger_entry'
928                . ' (communication_id, communication_type, create_time, remote_ip,'
929                . '  webservice_id)'
930                . ' VALUES (?, ?, current_timestamp, ?, ?)',
931            Bind => [
932                \$Param{CommunicationID}, \$Param{CommunicationType},
933                \$Param{RemoteIP},        \$Param{WebserviceID},
934            ],
935        )
936        )
937    {
938        $Kernel::OM->Get('Kernel::System::Log')->Log(
939            Priority => 'error',
940            Message  => 'Could not create debug entry chain in db!',
941        );
942        return;
943    }
944
945    return 1;
946}
947
9481;
949
950=end Internal:
951
952=head1 TERMS AND CONDITIONS
953
954This software is part of the OTRS project (L<https://otrs.org/>).
955
956This software comes with ABSOLUTELY NO WARRANTY. For details, see
957the enclosed file COPYING for license information (GPL). If you
958did not receive this file, see L<https://www.gnu.org/licenses/gpl-3.0.txt>.
959
960=cut
961