3 Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
4 Copyright [2016-2024] EMBL-European Bioinformatics Institute
6 Licensed under the Apache License, Version 2.0 (the
"License");
7 you may not use
this file except in compliance with the License.
8 You may obtain a copy of the License at
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an
"AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License
for the specific language governing permissions and
16 limitations under the License.
28 A library to
interface eHive with
Slack
32 package Bio::EnsEMBL::Hive::Utils::Slack;
37 use Exporter
'import';
38 our @EXPORT_OK = qw(send_message_to_slack send_beekeeper_message_to_slack);
41 =head2 send_message_to_slack
43 Description: A core method to send a message to a
Slack webhook.
44 The payload should be a hash-structure that can be encoded in
45 JSON and follows
Slack's message structure. See more details at
46 <https://api.slack.com/incoming-webhooks> and
47 <https://api.slack.com/docs/formatting>
51 sub send_message_to_slack {
52 my ($slack_webhook, $payload) = @_;
54 require HTTP::Request::Common;
55 require LWP::UserAgent;
58 # Fix the channel name (it *must* start with a hash)
59 $payload->{'channel
'} = '#
'.$payload->{'channel
'} if ($payload->{'channel
'} || '') =~ /^[^#@]/;
61 my $json_payload = JSON::encode_json($payload);
62 my $req = HTTP::Request::Common::POST($slack_webhook, ['payload
' => $json_payload]);
64 my $ua = LWP::UserAgent->new;
66 my $resp = $ua->request($req);
68 if ($resp->is_success) {
71 # All taken from https://api.slack.com/changelog/2016-05-17-changes-to-errors-for-incoming-webhooks
72 if ($resp->code == 400) {
73 if ($resp->content eq 'invalid_payload
') {
74 _pretty_die($resp, 'The data sent in your request cannot be understood as presented; verify your content body matches your content type and is structurally valid
'. "\n$json_payload");
75 } elsif ($resp->content eq 'user_not_found
') {
76 _pretty_die($resp, 'The user used in your request does not actually exist
' . "\n$json_payload");
78 } elsif ($resp->code == 403) {
79 if ($resp->content eq 'action_prohibited
') {
80 _pretty_die($resp, 'The team associated with your request has some kind of restriction on the webhook posting in
this context.
'. "\n$json_payload");
82 } elsif ($resp->code == 404) {
83 if ($resp->content eq 'channel_not_found
') {
84 _pretty_die($resp, sprintf('The channel associated with your request (%s) does not exist
', $payload->{'channel
'}));
86 } elsif ($resp->code == 405) {
87 if ($resp->content eq 'channel_is_archived
') {
88 _pretty_die($resp, sprintf(q{The channel '%s
' has been archived and doesn't accept further messages, even from your incoming webhook.}, $payload->{
'channel'}));
90 } elsif ($resp->code == 500) {
91 if ($resp->content eq
'rollup_error') {
92 _pretty_die($resp,
'Something strange and unusual happened that was likely not your fault at all.'.
"\n$json_payload");
95 _pretty_die($resp, $resp->content);
102 Description: Helper method to have uniform error messages
107 my ($resp, $explanation) = @_;
108 die sprintf(
"Got a %d error (%s): %s\n", $resp->code, $resp->message, $explanation);
112 =head2 send_beekeeper_message_to_slack
114 Arg [1] : $slack_webhook (
string URL)
116 Arg [3] : $is_error (non-zero
if message should be displayed as an error)
117 Arg [4] : $is_exit (non-zero
if message should be displayed as an exit -
118 a non-zero $is_error overrides $is_exit)
119 Arg [5] : $beekeeper_message (
string)
120 Arg [6] : (optional) $loop_until (
string) beekeeper
's loop_until setting
121 Description : Formats and packages a message from the beekeeper, then sends to Slack.
125 sub send_beekeeper_message_to_slack {
126 my ($slack_webhook, $hive_pipeline, $is_error, $is_exit, $beekeeper_message, $loop_until) = @_;
129 my $error_fallback = "this beekeeper has detected an error condition";
130 my $exit_fallback = "this beekeeper has stopped";
132 $beekeeper_message =~ s/###,/###\n/g;
134 $beekeeper_message .= "\nBeekeeper's loop_until set to
'$loop_until'";
139 'fallback' => $error_fallback,
140 'title' => 'Beekeeper encountered an error',
141 'text' => $beekeeper_message,
145 'color' => 'warning',
146 'fallback' => $exit_fallback,
147 'title' => 'Beekeeper has exited',
148 'text' => $beekeeper_message,
151 # FIXME: this can never happen because $is_exit is always set to 1
154 'fallback' => 'beekeeper sent a non-error, non-exit message',
155 'title' => 'Beekeeper message',
156 'text' => $beekeeper_message,
160 my $dbc = $hive_pipeline->hive_dba()->dbc();
162 'text' => sprintf('Message from %s@%s:%s', $hive_pipeline->hive_pipeline_name, $dbc->host, $dbc->port),
163 'attachments' => \@attachments,
165 send_message_to_slack($slack_webhook, $payload);