File Coverage

blib/lib/WebService/DataDog/Alert.pm
Criterion Covered Total %
statement 18 98 18.3
branch 0 44 0.0
condition 0 54 0.0
subroutine 6 16 37.5
pod 7 7 100.0
total 31 219 14.1


line stmt bran cond sub pod time code
1             package WebService::DataDog::Alert;
2              
3 1     1   13259 use strict;
  1         1  
  1         27  
4 1     1   3 use warnings;
  1         1  
  1         30  
5              
6 1     1   6 use base qw( WebService::DataDog );
  1         2  
  1         320  
7 1     1   5 use Carp qw( carp croak );
  1         1  
  1         41  
8 1     1   4 use Data::Dumper;
  1         1  
  1         38  
9 1     1   4 use Try::Tiny;
  1         1  
  1         994  
10              
11              
12             =head1 NAME
13              
14             WebService::DataDog::Alert - Interface to Alert functions in DataDog's API.
15              
16             =head1 VERSION
17              
18             Version 1.0.1
19              
20             =cut
21              
22             our $VERSION = '1.0.1';
23              
24              
25             =head1 SYNOPSIS
26              
27             This module allows you interact with the Alert endpoint of the DataDog API.
28              
29             Per DataDog: "Alerts allow you to watch a particular metric query and receive a
30             notification when the value either exceeds or falls below the pre-defined threshold."
31              
32              
33             =head1 METHODS
34              
35             =head2 retrieve_all()
36              
37             Retrieve details for all alerts.
38              
39             my $alert = $datadog->build('Alert');
40             my $alert_list = $alert->retrieve_all();
41            
42             Parameters: None
43              
44             =cut
45              
46             sub retrieve_all
47             {
48 0     0 1   my ( $self, %args ) = @_;
49 0           my $verbose = $self->verbose();
50            
51 0           my $url = $WebService::DataDog::API_ENDPOINT . 'alert';
52            
53 0           my $response = $self->_send_request(
54             method => 'GET',
55             url => $url,
56             data => { '' => [] }
57             );
58            
59 0 0 0       if ( !defined($response) || !defined($response->{'alerts'}) )
60             {
61 0           croak "Fatal error. No response or 'alerts' missing from response.";
62             }
63            
64 0           return $response->{'alerts'};
65             }
66              
67              
68             =head2 create()
69              
70             Create new DataDog alert for specified metric query.
71             If successful, returns created alert id.
72              
73             NOTE: 'silenced' seems to have no effect in create mode, but works fine in update/edit mode.
74              
75             my $alert = $datadog->build('Alert');
76             my $alert_id = $alert->create(
77             query => $query, # Metric query to alert on
78             name => $alert_name, # Optional. default=dynamic, based on query
79             message => $message, # Optional. default=None
80             silenced => $boolean, # Optional. default=0
81             );
82            
83             Example:
84             my $alert_id = $alert->create(
85             query => "sum(last_1d):sum:system.net.bytes_rcvd{host:host0} > 100",
86             name => "Bytes received on host0",
87             message => "We may need to add web hosts if this is consistently high.",
88             );
89            
90             Parameters:
91              
92             =over 4
93              
94             =item * query
95              
96             Metric query to alert on.
97              
98             =item * name
99              
100             Optional. Name of the alert. Default = dynamic, based on query.
101              
102             =item * message
103              
104             Optional. A message to include with notifications for this alert. Email
105             notifications can be sent to specific users by using the same '@username'
106             notation as events.
107              
108             =item * silenced
109              
110             Optional. Default = false. Whether the alert should notify by email and in the
111             event stream. An alert with 'silenced' set to True is effectively muted. The
112             alert will continue to detect state changes, but they will only be visible on
113             the alert list page.
114              
115             =back
116              
117             =cut
118              
119             sub create
120             {
121 0     0 1   my ( $self, %args ) = @_;
122 0           my $verbose = $self->verbose();
123            
124             # Check for mandatory parameters
125 0           foreach my $arg ( qw( query ) )
126             {
127 0 0 0       croak "ERROR - Argument '$arg' is required for create()."
128             if !defined( $args{$arg} ) || ( $args{$arg} eq '' );
129             }
130            
131             # Error checks, common to create() and update()
132 0           $self->_error_checks( %args );
133            
134 0           my $url = $WebService::DataDog::API_ENDPOINT . 'alert';
135            
136 0           my $data =
137             {
138             query => $args{'query'},
139             };
140            
141 0 0 0       if ( defined( $args{'name'} ) && $args{'name'} ne '' )
142             {
143 0           $data->{'name'} = $args{'name'};
144             }
145            
146 0 0 0       if ( defined( $args{'message'} ) && $args{'message'} ne '' )
147             {
148 0           $data->{'message'} = $args{'message'};
149             }
150            
151 0 0 0       if ( defined( $args{'silenced'} ) && $args{'silenced'} ne '' )
152             {
153             # You must use references to integers in order to have JSON.pm properly
154             # encode these as JSON boolean values. Without this, JSON will encode integer
155             # value as string...which is how I found this fix, when it happened to me.
156             # Reference: http://stackoverflow.com/questions/1087308/why-cant-i-properly-encode-a-boolean-from-postgresql-via-jsonxs-via-perl
157 0 0         $data->{'silenced'} = ( $args{'silenced'} == 0 ? \0: \1 );
158             }
159            
160 0           my $response = $self->_send_request(
161             method => 'POST',
162             url => $url,
163             data => $data,
164             );
165            
166 0 0 0       if ( !defined($response) || !defined($response->{'state'}) || $response->{'state'} ne 'OK' )
      0        
167             {
168 0           croak "Fatal error. No response or missing/invalid state in response.";
169             }
170            
171 0           return $response->{'id'};
172             }
173              
174              
175              
176             =head2 retrieve()
177              
178             Retrieve details for specified alert.
179             NOTE: a 404 response typically indicates you specified an incorrect alert id.
180              
181             my $alert = $datadog->build('Alert');
182             my $alert_data = $alert->retrieve( id => $alert_id );
183            
184             Parameters:
185              
186             =over 4
187              
188             =item * id
189              
190             Id of alert you want to retrieve the details for.
191              
192             =back
193              
194             =cut
195              
196             sub retrieve
197             {
198 0     0 1   my ( $self, %args ) = @_;
199 0           my $verbose = $self->verbose();
200            
201             # Check for mandatory parameters
202 0           foreach my $arg ( qw( id ) )
203             {
204 0 0 0       croak "ERROR - Argument '$arg' is required."
205             if !defined( $args{$arg} ) || ( $args{$arg} eq '' );
206             }
207            
208             # Check that id specified is a number
209 0 0         croak "ERROR - invalid 'id' >" . $args{'id'} . "<. Alert id must be a number."
210             unless $args{'id'} =~ /^\d+$/;
211            
212 0           my $url = $WebService::DataDog::API_ENDPOINT . 'alert' . '/' . $args{'id'};
213            
214 0           my $response = $self->_send_request(
215             method => 'GET',
216             url => $url,
217             data => { '' => [] }
218             );
219            
220 0 0 0       if ( !defined($response) || !defined($response->{'id'}) )
221             {
222 0           croak "Fatal error. No response or alert 'id' missing from response.";
223             }
224            
225 0           return $response;
226             }
227              
228              
229             =head2 update()
230              
231             Update existing DataDog alert for specified alert id.
232             NOTE: a 404 response typically indicates you specified an incorrect alert id.
233              
234             my $alert = $datadog->build('Alert');
235             $alert->update(
236             id => $alert_id, # ID of alert to modify
237             query => $query, # Metric query to alert on
238             name => $alert_name, # Optional.
239             message => $message, # Optional.
240             silenced => $boolean, # Optional.
241             );
242            
243             Example:
244             # Change name of existing alert
245             $alert->update(
246             id => $alert_id,
247             name => "Bytes received on host0",
248             );
249            
250             Parameters:
251              
252             =over 4
253              
254             =item * id
255              
256             ID of alert you want to modify.
257              
258             =item * query
259              
260             Metric query to alert on.
261              
262             =item * name
263              
264             Optional. Name of the alert.
265              
266             =item * message
267              
268             Optional. A message to include with notifications for this alert. Email
269             notifications can be sent to specific users by using the same '@username'
270             notation as events.
271              
272             =item * silenced
273              
274             Optional.Whether the alert should notify by email and in the
275             event stream. An alert with 'silenced' set to True is effectively muted. The
276             alert will continue to detect state changes, but they will only be visible on
277             the alert list page.
278              
279             =back
280              
281             =cut
282              
283             sub update
284             {
285 0     0 1   my ( $self, %args ) = @_;
286 0           my $verbose = $self->verbose();
287            
288             # Check for mandatory parameters
289 0           foreach my $arg ( qw( id query ) )
290             {
291 0 0 0       croak "ERROR - Argument '$arg' is required for update()."
292             if !defined( $args{$arg} ) || ( $args{$arg} eq '' );
293             }
294            
295             # Error checks, common to create() and update()
296 0           $self->_error_checks( %args );
297            
298 0           my $original_alert = $self->retrieve( id => $args{'id'} );
299            
300 0           my $url = $WebService::DataDog::API_ENDPOINT . 'alert' . '/' . $args{'id'};
301            
302             # Populate with original details, otherwise the values will be lost
303 0           my $data =
304             {
305             query => $args{'query'},
306             name => $original_alert->{'name'},
307             message => $original_alert->{'message'},
308             silenced => $original_alert->{'silenced'},
309             };
310            
311             # Overwrite original details with any updated fields
312 0 0 0       if ( defined( $args{'name'} ) && $args{'name'} ne '' )
313             {
314 0           $data->{'name'} = $args{'name'};
315             }
316            
317 0 0 0       if ( defined( $args{'message'} ) && $args{'message'} ne '' )
318             {
319 0           $data->{'message'} = $args{'message'};
320             }
321            
322 0 0 0       if ( defined( $args{'silenced'} ) && $args{'silenced'} ne '' )
323             {
324             # You must use references to integers in order to have JSON.pm properly
325             # encode these as JSON boolean values. Without this, JSON will encode integer
326             # value as string...which is how I found this fix, when it happened to me.
327             # Reference: http://stackoverflow.com/questions/1087308/why-cant-i-properly-encode-a-boolean-from-postgresql-via-jsonxs-via-perl
328 0 0         $data->{'silenced'} = ( $args{'silenced'} == 0 ? \0: \1 );
329             }
330            
331 0           my $response = $self->_send_request(
332             method => 'PUT',
333             url => $url,
334             data => $data,
335             );
336            
337 0 0 0       if ( !defined($response) || !defined($response->{'state'}) || $response->{'state'} ne 'OK' )
      0        
338             {
339 0           croak "Fatal error. No response or missing/invalid state in response.";
340             }
341            
342 0           return;
343             }
344              
345              
346             =head2 mute_all()
347              
348             Mute all alerts.
349             "Muting will prevent all alerts from notifying through email and posts to the
350             event stream. State changes will only be visible by checking the alert page."
351              
352             my $alert = $datadog->build('Alert');
353             $alert->mute_all();
354            
355             Parameters: None
356              
357             =cut
358              
359             sub mute_all
360             {
361 0     0 1   my ( $self, %args ) = @_;
362 0           my $verbose = $self->verbose();
363            
364 0           my $url = $WebService::DataDog::API_ENDPOINT . 'mute_alerts';
365            
366 0           $self->_send_request(
367             method => 'POST',
368             url => $url,
369             data => { '' => [] }
370             );
371            
372 0           return;
373             }
374              
375              
376             =head2 unmute_all()
377              
378             Unmute all alerts.
379              
380             my $alert = $datadog->build('Alert');
381             $alert->unmute_all();
382            
383             Parameters: None
384              
385             =cut
386              
387             sub unmute_all
388             {
389 0     0 1   my ( $self, %args ) = @_;
390 0           my $verbose = $self->verbose();
391            
392 0           my $url = $WebService::DataDog::API_ENDPOINT . 'unmute_alerts';
393            
394 0           $self->_send_request(
395             method => 'POST',
396             url => $url,
397             data => { '' => [] }
398             );
399            
400 0           return;
401             }
402              
403              
404             =head2 delete()
405              
406             Delete specified alert.
407              
408             my $alert = $datadog->build('Alert');
409             $alert->delete( id => $alert_id );
410            
411             Parameters:
412              
413             =over 4
414              
415             =item * id
416              
417             Dashboard id you want to delete.
418              
419             =back
420              
421             =cut
422              
423             sub delete
424             {
425 0     0 1   my ( $self, %args ) = @_;
426            
427 0           my $verbose = $self->verbose();
428            
429             # Check for mandatory parameters
430 0           foreach my $arg ( qw( id ) )
431             {
432 0 0 0       croak "ERROR - Argument '$arg' is required for delete()."
433             if !defined( $args{$arg} ) || ( $args{$arg} eq '' );
434             }
435            
436             # Check that id specified is a number
437 0 0         croak "ERROR - invalid 'id' >" . $args{'id'} . "<. Alert id must be a number."
438             unless $args{'id'} =~ /^\d+$/;
439            
440 0           my $url = $WebService::DataDog::API_ENDPOINT . 'alert' . '/' . $args{'id'};
441            
442 0           my $should_croak;
443             try
444             {
445 0     0     $self->_send_request(
446             method => 'DELETE',
447             url => $url,
448             data => { '' => [] }
449             );
450             }
451             catch
452             {
453 0 0   0     if ( /404/ )
454             {
455 0           $should_croak = "Error 404 deleting alert id >" . $args{'id'} . "<. Are you sure this is the correct alert id?";
456             }
457 0           };
458 0 0         croak $should_croak if $should_croak;
459            
460 0           return;
461             }
462              
463              
464             =head1 INTERNAL FUNCTIONS
465              
466             =head2 _error_checks()
467              
468             Common error checking for creating/updating alerts.
469              
470             =cut
471              
472             sub _error_checks
473             {
474 0     0     my ( $self, %args ) = @_;
475 0           my $verbose = $self->verbose();
476            
477             # Check that name is <= 80 characters. Undocumented limitation. A name of 81 chars results in '400 Bad Request'.
478 0 0 0       croak( "ERROR - invalid 'name' >" . $args{'name'} . "<. Name must be 80 characters or less." )
479             if ( defined( $args{'name'} ) && length( $args{'name'} ) > 80 );
480            
481             # Check that 'silenced' is a boolean.
482 0 0 0       croak( "ERROR - invalid 'silenced' value >" . $args{'silenced'} . "<. Must specify 0 (false) or 1 (true).")
483             if ( defined( $args{'silenced'} ) && $args{'silenced'} !~ /^[01]$/ );
484            
485 0           return;
486             }
487              
488              
489             1;