File Coverage

blib/lib/Siebel/Srvrmgr/OS/Unix.pm
Criterion Covered Total %
statement 48 52 92.3
branch 8 16 50.0
condition 2 9 22.2
subroutine 5 5 100.0
pod 1 1 100.0
total 64 83 77.1


line stmt bran cond sub pod time code
1             package Siebel::Srvrmgr::OS::Unix;
2              
3 2     2   1735 use Moose;
  2         427810  
  2         14  
4 2     2   10700 use Proc::ProcessTable;
  2         22990  
  2         101  
5 2     2   927 use namespace::autoclean;
  2         2411  
  2         13  
6              
7             =pod
8              
9             =head1 NAME
10              
11             Siebel::Srvrmgr::OS::Unix - module to recover information from OS processes of Siebel components
12              
13             =head1 SYNOPSIS
14              
15             use Siebel::Srvrmgr::OS::Unix;
16             my $procs = Siebel::Srvrmgr::OS::Unix->new(
17             {
18             enterprise_log => $enterprise_log,
19             cmd_regex => "^$path_to_siebel_dir",
20             parent_regex => 'Created\s(multithreaded\s)?server\sprocess\s\(OS\spid\s\=\s+\d+\s+\)\sfor\s\w+'
21             }
22             );
23             my $procs_ref = $procs->get_procs;
24             foreach my $comp_pid(keys(%{$procs_ref})) {
25              
26             print 'Component ', $procs_ref->{$comp_pid}->{comp_alias}, ' is using ', $procs_ref->{$comp_pid}->{pctcpu}, "% of CPU now\n";
27              
28             }
29              
30             =head1 DESCRIPTION
31              
32             This module is a L<Moose> class.
33              
34             It is responsible to recover information from a UNIX-like operation system to be able to merge with information
35             regarding Siebel components.
36              
37             This class represents the processes of a single Siebel Server and will recover processes information from C</proc> directory.
38              
39             Additionally, this class has a method to search the Siebel enterprise log file for processes information as well.
40              
41             =head1 ATTRIBUTES
42              
43             =head2 enterprise_log
44              
45             Required attribute.
46              
47             A string of the complete path name to the Siebel enterprise log file.
48              
49             =cut
50              
51             has enterprise_log => (
52             is => 'rw',
53             isa => 'Str',
54             reader => 'get_ent_log',
55             writer => 'set_ent_log',
56             required => 1
57             );
58              
59             =head2 parent_regex
60              
61             Required attribute.
62              
63             A string of the regular expression to match if the process recovered from the enterprise log file has children or not.
64              
65             Since the enterprise may contain different language settings, this parameter is required and will depend on the language set.
66              
67             This attribute is a string, not a compiled regular expression with C<qr>.
68              
69             =cut
70              
71             has parent_regex => (
72             is => 'rw',
73             isa => 'Str',
74             reader => 'get_parent_regex',
75             writer => 'set_parent_regex',
76             required => 1
77             );
78              
79             =head2 cmd_regex
80              
81             Required attribute.
82              
83             A string of the regular expression to match the command executed by the Siebel user from the C<cmdline> file in C</proc>.
84             This usually is the path included in the binary when you check with C<ps -aux> command.
85              
86             This attribute is a string, not a compiled regular expression with C<qr>.
87              
88             =cut
89              
90             has cmd_regex => (
91             is => 'rw',
92             isa => 'Str',
93             reader => 'get_cmd',
94             writer => 'set_cmd',
95             required => 1
96             );
97              
98             =head2 mem_limit
99              
100             Optional attribute.
101              
102             A integer representing the maximum bytes of RSS a Siebel process might have.
103              
104             If set together with C<limits_callback>, this class can execute some action when this threshold is exceeded.
105              
106             =cut
107              
108             has mem_limit => (
109             is => 'rw',
110             isa => 'Int',
111             reader => 'get_mem_limit',
112             writer => 'set_mem_limit',
113             default => 0
114             );
115              
116             =head2 cpu_limit
117              
118             Optional attribute.
119              
120             A integer representing the maximum CPU percentage a Siebel process might have.
121              
122             If set together with C<limits_callback>, this class can execute some action when this threshold is exceeded.
123              
124             =cut
125              
126             has cpu_limit => (
127             is => 'rw',
128             isa => 'Int',
129             reader => 'get_cpu_limit',
130             writer => 'set_cpu_limit',
131             default => 0
132             );
133              
134             =head2 limits_callback
135              
136             Optional attribute.
137              
138             A code reference that will be executed when one of the attributes C<mem_limit> and C<cpu_limit> threshold is exceeded.
139              
140             This is useful, for example, with you want to set a alarm or something like that.
141              
142             The code reference will receive a hash reference as parameter which keys and values will depend on the type of limit triggered:
143              
144             =over
145              
146             =item *
147              
148             memory:
149              
150             type => 'memory'
151             rss => <processes RSS>
152             vsz => <process VSZ>
153             pid => <process id>
154             fname => <process fname>,
155             cmd => <process cmndline>
156              
157             =item *
158              
159             CPU:
160              
161             type => 'cpu'
162             cpu => <process % of cpu>
163             pid => <process id>
164             fname => <process fname>
165             cmd => <process cmndline>
166              
167             =back
168              
169             =cut
170              
171             has limits_callback => (
172             is => 'rw',
173             isa => 'CodeRef',
174             reader => 'get_callback',
175             writer => 'set_callback'
176             );
177              
178             =head1 METHODS
179              
180             =head2 get_procs
181              
182             Searches through C</proc> and the Siebel Enterprise log file and returns an hash reference with the pids as keys and hashes references as values.
183             For those hash references, the following keys will be available:
184              
185             =over
186              
187             =item *
188              
189             fname: name of the process
190              
191             =item *
192              
193             pctcpu: % of server total CPU
194              
195             =item *
196              
197             pctmem: % of server total memory
198              
199             =item *
200              
201             rss: RSS
202              
203             =item *
204              
205             vsz: VSZ
206              
207             =item *
208              
209             comp_alias: alias of the Siebel Component
210              
211             =back
212              
213             The only process informations will be those match C<cmd_regex> and that have C<fname> equal one of the following values:
214              
215             =over
216              
217             =item *
218              
219             siebmtsh
220              
221             =item *
222              
223             siebmtshmw
224              
225             =item *
226              
227             siebproc
228              
229             =item *
230              
231             siebprocmw
232              
233             =item *
234              
235             siebsess
236              
237             =item *
238              
239             siebsh
240              
241             =item *
242              
243             siebshmw
244              
245             =back
246              
247             =cut
248              
249             sub get_procs {
250              
251 1     1 1 8 my $self = shift;
252 1         1 my $cmd_regex;
253              
254             {
255              
256 1         2 my $regex = $self->get_cmd;
  1         38  
257 1         32 $cmd_regex = qr/$regex/;
258              
259             }
260              
261 1         9 my %valid_proc_name = (
262             siebmtsh => 0,
263             siebmtshmw => 0,
264             siebproc => 0,
265             siebprocmw => 0,
266             siebsess => 0,
267             siebsh => 0,
268             siebshmw => 0
269             );
270              
271 1         14 my $t = Proc::ProcessTable->new( enable_ttys => 0 );
272              
273 1         1127 my %procs;
274              
275 1         3 for my $process ( @{ $t->table } ) {
  1         1471  
276              
277             next
278 11 100 66     128 unless ( exists( $valid_proc_name{ $process->fname } )
279             and ( $process->cmndline =~ $cmd_regex ) );
280              
281             # :WORKAROUND:22-03-2015 20:54:51:: forcing convertion to number
282 1         31 my $pctcpu = $process->pctcpu;
283 1         10 $pctcpu =~ s/\s//;
284 1         6 $pctcpu += 0;
285              
286 1         4 $procs{ $process->pid } = {
287             fname => $process->fname,
288             pctcpu => $pctcpu,
289             pctmem => ( $process->pctmem + 0 ),
290             rss => ( $process->rss + 0 ),
291             vsz => ( $process->size + 0 )
292             };
293              
294 1 50       93 if ( $self->get_mem_limit > 0 ) {
295              
296 0 0 0     0 if ( ( $process->rss > $self->get_mem_limit )
297             and ( defined( $self->get_callback ) ) )
298             {
299              
300 0         0 $self->get_callback->(
301             {
302             type => 'memory',
303             rss => $process->rss,
304             vsz => $process->size,
305             pid => $process->pid,
306             fname => $process->fname,
307             cmd => $process->cmndline
308             }
309             );
310              
311             }
312              
313             }
314              
315 1 50       50 if ( $self->get_cpu_limit > 0 ) {
316              
317 0 0 0     0 if ( ( $process->pctcpu > $self->get_cpu_limit )
318             and ( defined( $self->get_callback ) ) )
319             {
320              
321 0         0 $self->get_callback->(
322             {
323             type => 'cpu',
324             cpu => $process->pctcpu,
325             pid => $process->pid,
326             fname => $process->fname,
327             cmd => $process->cmndline
328             }
329             );
330              
331             }
332              
333             }
334              
335             }
336              
337 1         6 $self->_find_pid( \%procs );
338              
339 1         322 return \%procs;
340              
341             }
342              
343             sub _find_pid {
344              
345 1     1   2 my $self = shift;
346 1         1 my $procs_ref = shift;
347 1         1 my %comps;
348              
349             my $create_regex;
350              
351             {
352              
353 1         1 my $regex = $self->get_parent_regex;
  1         31  
354 1         53 $create_regex = qr/$regex/;
355              
356             }
357              
358 1         6 local $/ = "\015\012";
359              
360 1 50       39 open( my $in, '<', $self->get_ent_log )
361             or die( 'Cannot read ' . $self->get_ent_log . ': $!' );
362              
363 1         20 while ( my $line = <$in> ) {
364              
365 50         37 chomp($line);
366              
367 50 100       134 if ( $line =~ $create_regex ) {
368              
369 8         23 my @parts = split( /\t/, $line );
370 8         18 $parts[7] =~ s/\s(\w)+\s//;
371 8         7 $parts[7] =~ tr/)//d;
372              
373             # pid => component alias
374 8         26 $comps{$parts[6]} = $parts[7];
375              
376             }
377              
378             }
379              
380 1         7 close($in);
381              
382 1         2 foreach my $proc_pid ( keys( %{$procs_ref} ) ) {
  1         5  
383              
384 1 50       3 if ( exists( $comps{$proc_pid} ) ) {
385              
386 1         11 $procs_ref->{$proc_pid}->{comp_alias} = $comps{$proc_pid};
387              
388             }
389              
390             }
391              
392             }
393              
394             =head1 SEE ALSO
395              
396             =over
397              
398             =item *
399              
400             L<Moose>
401              
402             =item *
403              
404             L<Proc::ProcessTable>
405              
406             =back
407              
408             =head1 AUTHOR
409              
410             Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.orgE<gt>
411              
412             =head1 COPYRIGHT AND LICENSE
413              
414             This software is copyright (c) 2012 of Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.orgE<gt>
415              
416             This file is part of Siebel Monitoring Tools.
417              
418             Siebel Monitoring Tools is free software: you can redistribute it and/or modify
419             it under the terms of the GNU General Public License as published by
420             the Free Software Foundation, either version 3 of the License, or
421             (at your option) any later version.
422              
423             Siebel Monitoring Tools is distributed in the hope that it will be useful,
424             but WITHOUT ANY WARRANTY; without even the implied warranty of
425             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
426             GNU General Public License for more details.
427              
428             You should have received a copy of the GNU General Public License
429             along with Siebel Monitoring Tools. If not, see <http://www.gnu.org/licenses/>.
430              
431             =cut
432              
433             __PACKAGE__->meta->make_immutable;