1

I currently have a script that is tailing our error log and sending logs to our slack channel. How can I get it to send an entire error and not line by line. This is what I have currently and one error gets sent as hundreds of single line posts.

    #!/bin/bash
tail -f "$1" | while read LINE; do
  (echo "$LINE") && curl -X POST --silent --data-urlencode \
    "payload={\"text\": \"\`\`\`$1  $(echo $LINE | sed "s/\"/'/g")\`\`\`\"}" "$2";
done

Is there a way I can get bash to do this?

This is how it looks in slack:

```/var/log/php_error_log  Stack trace:```
```/var/log/php_error_log  #0 /opt/library/Zend/Mail/Protocol/Smtp.php(167): Zend_Mail_Protocol_Abstract->_connect('tcp://mail...')```
```/var/log/php_error_log  #1 /opt/library/Zend/Mail/Transport/Smtp.php(199): Zend_Mail_Protocol_Smtp->connect()```
```/var/log/php_error_log  #2 /opt/library/Zend/Mail/Transport/Abstract.php(348): Zend_Mail_Transport_Smtp->_sendMail()```
```/var/log/php_error_log  #3 /opt/library/Zend/Mail.php(1197): Zend_Mail_Transport_Abstract->send(Object(Zend_Mail))```
```/var/log/php_error_log  #4 /opt//cronjobs/automate_ro.php(472): Zend_Mail->send(Object(Zend_Mail_Transport_Smtp))```
```/var/log/php_error_log  #5 {main}```

This is how its meant to be formatted

```/var/log/php_error_log  Stack trace:
/var/log/php_error_log  #0 /opt/library/Zend/Mail/Protocol/Smtp.php(167): Zend_Mail_Protocol_Abstract->_connect('tcp://mail.grat...')
/var/log/php_error_log  #1 /opt/library/Zend/Mail/Transport/Smtp.php(199): Zend_Mail_Protocol_Smtp->connect()
/var/log/php_error_log  #2 /opt/library/Zend/Mail/Transport/Abstract.php(348): Zend_Mail_Transport_Smtp->_sendMail()
/var/log/php_error_log  #3 /opt/library/Zend/Mail.php(1197): Zend_Mail_Transport_Abstract->send(Object(Zend_Mail))
/var/log/php_error_log  #4 /opt//cronjobs/automate_ro.php(472): Zend_Mail->send(Object(Zend_Mail_Transport_Smtp))
/var/log/php_error_log  #5 {main}```
Jed
  • 929
  • 2
  • 19
  • 32
  • 1
    What would constitute an "Entire Error". Would that be the whole log? Or just lines from the log since the last send? Or something else entirely? – JNevill Jul 02 '18 at 13:10
  • This is how it formats a multiline error – Jed Jul 02 '18 at 14:22

2 Answers2

1

Use jq to create the payload instead of trying to escape things yourself.

post_log () {
  log=$1
  url=$2

  json=$( jq --argjson t "$log" '{text: "```\($t)```"}' )

  curl -X POST --silent --data-urlencode "payload=$json" "$url"
}

tail -f "$1" | while read LINE; do
  echo "$LINE"
  post_log "$LINE" "$2"
done
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Fair enough but is this code to change the way it reads line by line I don't think it is. – Jed Jul 02 '18 at 18:31
  • Oh, multiple input lines per log message. Well, what signals the end of a stack trace? – chepner Jul 02 '18 at 18:33
  • Its a normal php error log I am not sure what signals the end of the trace – Jed Jul 03 '18 at 14:41
  • Then it's going to be difficult to programmatically bunch up the required lines into a single request. – chepner Jul 03 '18 at 15:08
0

why not implement monolog in the application? This approach seems a goldberg machine to me (no offense).

https://seldaek.github.io/monolog/doc/02-handlers-formatters-processors.html#send-alerts-and-emails

  • SlackbotHandler: Logs records to a Slack account using the Slackbot incoming hook.
  • SlackWebhookHandler: Logs records to a Slack account using Slack Webhooks.
  • SlackHandler: Logs records to a Slack account using the Slack API (complex setup).
m47730
  • 2,061
  • 2
  • 24
  • 30
  • No offence taken at all. I needed the fastest implementation possible and that was the fastest until I had time to add monolog. This is just for the short term – Jed Jul 02 '18 at 18:12
  • @Jed so if you want a dirt approach: why not `cat file` and send to slack? after that simply truncate, blank or remove. – m47730 Jul 03 '18 at 10:50
  • Yes I am thinking I am going to have to go this way for now. I was hoping there was a way to do it with a tail like feature – Jed Jul 03 '18 at 14:42