========================
Slack Driven Development
========================
.. image:: /_images/image_slack.png
:width: 150pt
.. raw:: html
Date: **2016-06-15**
Since I am always sitting in a slack channel, I wanted to share a tool I use to track exceptions across my cloud and other environments.
This repository_ is an example for posting: exceptions, tracking environment errors, and sending targeted debugging messages to a Slack channel to help decrease time spent finding + fixing bugs.
I built this because I was tired of tail-ing and grep-ing through logs. Now I just wait for exceptions and errors to be published into a **debugging** Slack channel so I can quickly view: what ``environment`` had the error, the ``associated message``, and the ``source code line number``.
.. _repository: https://github.com/jay-johnson/slack-driven-development
.. role:: bash(code)
:language: bash
Setup
-----
This repository only works with Python 2.
1. Install the official Slack Python API
.. note:: Please refer to the official `Slack repository`_ for more information
::
sudo pip install slackclient
.. _Slack repository: https://github.com/slackhq/python-slackclient
Getting Started
---------------
#. Create a Slack channel for debugging messages
This demo uses a channel with the name: ``#debugging``
#. Create a named Slack bot if you do not have one already
This demo uses a bot with the name: ``bugbot``
#. Record the Slack bot's API Token
This demo uses a bot with an API token: ``xoxb-51351043345-oHKTiT5sXqIAlxwYzQspae54``
#. Invite the Slack bot to your debugging channel
Type this into the debugging channel and hit enter:
::
/invite bugbot
.. warning:: If you do not invite the bot into the channel it can be difficult to debug
#. Edit the configuration for your needs
The example file slack_driven_development.py_ uses a configuration `dictionary object`_ where you can assign these keys based off your needs:
+-----------------+------------------------------------------------------------+
| Key Name | Purpose and Where to find the Value |
+=================+============================================================+
| **BotName** | Name of the Slack bot that will post messages |
+-----------------+------------------------------------------------------------+
| **ChannelName** | Name of the channel where messages are posted |
+-----------------+------------------------------------------------------------+
| **NotifyUser** | Name of the Slack user that gets notified for messages |
+-----------------+------------------------------------------------------------+
| **Token** | Slack API Token for the bot |
+-----------------+------------------------------------------------------------+
| **EnvName** | A logical name for showing which environment had the error |
+-----------------+------------------------------------------------------------+
#. Test the bot works
The included slack_driven_development.py_ file will throw an exception that will report the exception into the channel using the bot based off the simple dictionary configuration in the file.
::
$ ./slack_driven_development.py
Testing an Exception that shows up in Slack
Sending an error message to Slack for Exception(name 'testing_how_this_looks_from_slack' is not defined)
Done
$
#. Confirm the debugging message shows up in Slack channel
.. image:: /_images/image_07SlackDrivenDevelopmentExample.png
.. _dictionary object: https://github.com/jay-johnson/slack-driven-development/blob/78ced381ce1a1594e735943a8a9ab145425fe7d1/slack_driven_development.py#L5-L11
.. _slack_driven_development.py: https://github.com/jay-johnson/slack-driven-development/blob/master/slack_driven_development.py
Screenshots for Getting Started
-------------------------------
Here are the screenshots (as of **06-15-2016**) for getting this demo integrated with your Slack channel and bot:
**1. Create a new Slack App Integration**
.. image:: /_images/image_01SlackAddANewIntegration.png
**2. Build a new Integration**
.. image:: /_images/image_02SlackBuild.png
**3. Make a Custom Integration**
.. image:: /_images/image_03SlackMakeCustomIntegration.png
**4. Create a new Bot**
.. image:: /_images/image_04SlackBotCreateNewBot.png
**5. Name and Add Bot**
.. image:: /_images/image_05SlackNameAndAddBot.png
**6. Record the Bot API Token in the Dictionary Configuration**
.. image:: /_images/image_06SlackRecordBotAPIToken.png
**7. Run the Slack Driven Development Demo**
.. image:: /_images/image_07SlackDrivenDevelopmentExample.png
How does this work?
-------------------
1. By using a `try/catch block`_ we can capture the exception, and pass it into a `handler method`_.
.. code-block:: python
:linenos:
try:
print "Testing an Exception that shows up in Slack"
testing_how_this_looks_from_slack
except Exception,k:
print "Sending an error message to Slack for the expected Exception(" + str(k) + ")"
slack_msg.handle_send_slack_internal_ex(k)
# end of try/ex
.. _try/catch block: https://github.com/jay-johnson/slack-driven-development/blob/3d81ffe3084f91fbdead00218d07f8ec3cc231f5/slack_driven_development.py#L15-L21
.. _handler method: https://github.com/jay-johnson/slack-driven-development/blob/3d81ffe3084f91fbdead00218d07f8ec3cc231f5/slack_messenger.py#L19-L33
2. `Prepare the exception`_
.. _Prepare the exception: https://github.com/jay-johnson/slack-driven-development/blob/3d81ffe3084f91fbdead00218d07f8ec3cc231f5/slack_messenger.py#L19-L33
3. `Inspect the exception`_
Python has a great little feature where it can `inspect the stacktrace`_ from an exception outside of the calling objects and even files. Once the file with the exception has been found, we can open the file and goto the `exact line that caused the exception`_ and `build an error report with the source code and the line number`_.
.. code-block:: python
:linenos:
def get_exception_error_message(self, ex, exc_type, exc_obj, exc_tb):
path_to_file = str(exc_tb.tb_frame.f_code.co_filename)
last_line = int(exc_tb.tb_lineno)
gh_line_number = int(last_line) - 1
file_name = str(os.path.split(exc_tb.tb_frame.f_code.co_filename)[1])
path_to_file = str(exc_tb.tb_frame.f_code.co_filename)
py_file = open(path_to_file).readlines()
line = ""
for line_idx,cur_line in enumerate(py_file):
if line_idx == gh_line_number:
line = cur_line
if str(exc_obj.message) != "":
ex_details_msg = str(exc_obj.message)
else:
ex_details_msg = str(ex)
send_error_log_to_slack = ""
if line != "":
send_error_log_to_slack = " File: *" + str(path_to_file) + "* on Line: *" + str(last_line) + "* Code: \n```" + str(line) + "``` \n"
else:
send_error_log_to_slack = "Error on Line Number: " + str(last_line)
return send_error_log_to_slack
# end of get_exception_error_message
.. _Inspect the exception: https://github.com/jay-johnson/slack-driven-development/blob/3d81ffe3084f91fbdead00218d07f8ec3cc231f5/slack_messenger.py#L36-L61
.. _inspect the stacktrace: https://github.com/jay-johnson/slack-driven-development/blob/3d81ffe3084f91fbdead00218d07f8ec3cc231f5/slack_messenger.py#L38-L42
.. _exact line that caused the exception: https://github.com/jay-johnson/slack-driven-development/blob/3d81ffe3084f91fbdead00218d07f8ec3cc231f5/slack_messenger.py#L42-L47
.. _build an error report with the source code and the line number: https://github.com/jay-johnson/slack-driven-development/blob/3d81ffe3084f91fbdead00218d07f8ec3cc231f5/slack_messenger.py#L54-L58
4. `Send the message to the Slack channel`_
Post the message to the Slack channel and handle any exceptions.
.. note:: If your configuration `dictionary object`_ is misconfigured you will likely see an ``unauthorized`` error
.. _Send the message to the Slack channel: https://github.com/jay-johnson/slack-driven-development/blob/3d81ffe3084f91fbdead00218d07f8ec3cc231f5/slack_messenger.py#L70-L76
.. _dictionary object: https://github.com/jay-johnson/slack-driven-development/blob/78ced381ce1a1594e735943a8a9ab145425fe7d1/slack_driven_development.py#L5-L11
License
-------
This repository is licensed under the MIT license.
.. Thanks!!
**Thanks for reading,**
Jay
Want to learn more?
-------------------
* .. raw:: html
Email me
* `Contact Information`_
.. _Contact Information: https://jaypjohnson.com/contact.html
.. SEO Metadata
SEO_SET_HEADER_URL="https://jaypjohnson.com/2016-06-15-slack-driven-development.html"
SEO_SET_HEADER_SITENAME="Slack Driven Development - An Integrated Debugging Tool"
SEO_SET_HEADER_TITLE="Slack Driven Development - An Integrated Debugging Tool"
SEO_SET_HEADER_DESC="A repository for posting: exceptions, tracking environment errors, and sending targeted debugging messages to a Slack channel to help decrease time spent finding and fixing bugs"
SEO_SET_HEADER_KEYWORDS="software, devops, python, debugging, slack, slack tools, tracking exceptions, helping debug errors, help fixing bugs with slack"
SEO_SET_HEADER_TYPE="website"
SEO_SET_HEADER_TWITTER_CREATOR="@jayphjohnson"
SEO_SET_HEADER_TWITTER_SITE="@jayphjohnson"
SEO_SET_HEADER_SEEALSO="https://jaypjohnson.com/"
SEO_SET_HEADER_FAVICON="/favicon.png"
SEO_SET_HEADER_IMAGE="/_images/image_slack.png"
SEO_SET_HEADER_CARD="summary"
SEO_SET_HEADER_AUTHOR="Jay Johnson"