Error reporter, with Mechanic.

Mechanic is a development and ecommerce automation platform for Shopify. :)

Error reporter

Use this task to get email or Slack notifications when errors occur with any events, tasks, and actions in Mechanic. Use this task out of the box, customize it, or borrow logic for your more advanced error reporting tasks.

Runs Occurs when an event fails, Occurs when a task fails, and Occurs when an action fails. Configuration includes notification methods, email recipients, slack account, and slack channel id .

15-day free trial – unlimited tasks

Documentation

Use this task to get email or Slack notifications when errors occur with any events, tasks, and actions in Mechanic. Use this task out of the box, customize it, or borrow logic for your more advanced error reporting tasks.

Read more about error events.

IMPORTANT: To use Slack notifications, you must install the Mechanic Slack app in your Slack workspace (Settings → Authentication → Slack) and confiure a Slack account and Slack channel ID in this task. If the configured channel is private, then you will need to add the Mechanic bot to the channel before it can post messages (/invite @mechanic).

Developer details

Mechanic is designed to benefit everybody: merchants, customers, developers, agencies, Shopifolks, everybody.

That’s why we make it easy to configure automation without code, why we make it easy to tweak the underlying code once tasks are installed, and why we publish it all here for everyone to learn from.

(By the way, have you seen our documentation? Have you joined the Slack community?)

Open source
View on GitHub to contribute to this task
Subscriptions
mechanic/errors/event
mechanic/errors/task
mechanic/errors/action
Tasks use subscriptions to sign up for specific kinds of events. Learn more
Options
notification methods (multiselect, o1, email, o2, slack, required) , email recipients (array) , slack account , slack channel id
Code
{% assign notification_methods = options.notification_methods__multiselect_o1_email_o2_slack_required %}
{% assign email_recipients = options.email_recipients__array %}
{% assign slack_account = options.slack_account %}
{% assign slack_channel_id = options.slack_channel_id_ %}

{% if notification_methods contains "email" and email_recipients == blank %}
  {% error "Configure one or more email recipients when choosing the email notification method" %}
{% endif %}

{% if notification_methods contains "slack" and slack_account == blank or slack_channel_id == blank %}
  {% error "Configure a slack account and channel ID when choosing the slack notification method" %}
{% endif %}

{% comment %}
  -- define thresholds for repeat error sending
{% endcomment %}

{% assign error_thresholds = array %}
{% assign error_thresholds[0] = 10 %}
{% assign error_thresholds[1] = 25 %}
{% assign error_thresholds[2] = 50 %}
{% assign error_thresholds[3] = 100 %}
{% assign error_thresholds[4] = 200 %}

{% comment %}
  -- fingerprint the error, to know if it has been received recently
  -- See: https://learn.mechanic.dev/techniques/debouncing-events#fingerprinting
{% endcomment %}

{% assign fingerprint_parts = hash %}
{% assign fingerprint_parts["topic"] = event.topic %}
{% assign fingerprint_parts["message"] = error.message %}
{% assign fingerprint_parts["task_id"] = error.task.id %}
{% assign fingerprint_parts["action_type"] = error.action.type %}
{% assign fingerprint = fingerprint_parts | json | sha256 %}
{% assign error_count_cache_key = "errors/" | append: fingerprint %}

{% comment %}
  -- send notification if the same error message from same task has not been cached recently or if matches one of the thresholds for reoccurrence
{% endcomment %}

{% assign recent_error_count = cache[error_count_cache_key] | default: 0 | plus: 1 %}

{% comment %}
  -- increment recent error count for this error
{% endcomment %}

{% action "cache" %}
  {
    "incr": {
      "key": {{ error_count_cache_key | json }},
      "ttl": 600
    }
  }
{% endaction %}

{% unless recent_error_count == 1 or error_thresholds contains recent_error_count %}
  {%- capture log_message -%}
    There have been {{ recent_error_count }} errors of this type from this task ({{ error.task.name }}) in the last 10 minutes. Waiting until the next threshold before sending another notification.
  {%- endcapture -%}

  {% log log_message %}

  {% break %}
{% endunless %}

{%- capture event_url -%}
  {{ shop.admin_url }}apps/mechanic/events/{{ error.event.id }}
{%- endcapture -%}

{% if notification_methods contains "email" %}
  {% capture email_subject -%}
    Mechanic error on {{ shop.name }}
  {%- endcapture %}

  {% capture email_body %}
    <p><small>This is an automated error notification from your Mechanic error reporting task.</small></p>
    {% if error_thresholds contains recent_error_count %}
      <p><em>There have been {{ recent_error_count }} errors of this type in the last 10 minutes.</em></p>
    {% endif %}
    <p><strong>Error topic:</strong> {{ event.topic }}</p>
    {% if error.action -%}
      <p><strong>Action type:</strong> {{ error.action.type }}</p>
    {% endif %}
    <p>
      <strong>Error message:</strong>
      <pre>{{ error.message }}</pre>
    </p>
    {% if event.preview %}
      <p>View error details</p>
    {% else %}
      <p><a href="{{ event_url }}">View error details</a></p>
    {% endif %}
    <p>Thanks,<br><br>{{ shop.name }} via Mechanic</p>
  {% endcapture %}

  {% action "email" %}
    {
      "to": {{ email_recipients | json  }},
      "subject": {{ email_subject | json }},
      "body": {{ email_body | json }},
      "reply_to": {{ shop.customer_email | json }},
      "from_display_name": {{ shop.name | json }}
    }
  {% endaction %}
{% endif %}

{% if notification_methods contains "slack" %}
  {% if event.topic == "mechanic/errors/event" %}
    {% assign message_header = "Error in filter" %}
  {% else %}
    {% assign message_header = "Error in task: " | append: error.task.name %}
  {% endif %}

  {% action "slack" %}
    {
      "account": {{ slack_account | json }},
      "method": "POST",
      "url_path": "/chat.postMessage",
      "headers": {
        "Content-Type": "application/json"
      },
      "body": {
        "channel": {{ slack_channel_id | json }},
        "text": {{ shop.name | prepend: "Error on " | json }},
        "blocks": [
          {
            "type": "header",
            "text": {
              "type": "plain_text",
              "text": {{ message_header | slice: 0, 150 | json }}
            }
          },
          {
            "type": "context",
            "elements": [
              {
                "type": "plain_text",
                "text": "This is an automated error notification from your Mechanic error reporting task."
              }
            ]
          },
          {
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": {{ shop.name | prepend: "*Shop:* " | json }}
            }
          },
          {
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": {{ event.topic | prepend: "*Error topic:* " | json }}
            }
          },
          {% if error.action -%}
            {
              "type": "section",
              "text": {
                "type": "mrkdwn",
                "text": {{ error.action.type | prepend: "*Action type:* " | json }}
              }
            },
          {% endif %}
          {% if error_thresholds contains recent_error_count -%}
            {
              "type": "context",
              "elements": [
                {
                  "type": "plain_text",
                  "text": "There have been {{ recent_error_count }} errors of this type from this task in the last 10 minutes."
                }
              ]
            },
          {%- endif %}
          {
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": "*Error message:*"
            }
          },
          {
            "type": "rich_text",
            "elements": [
              {
                "type": "rich_text_preformatted",
                "elements": [
                  {
                    "type": "text",
                    "text": {{ error.message | json }}
                  }
                ]
              }
            ]
          },
          {
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": "<{{ event_url }}|View error details in Mechanic>"
            }
          }
        ]
      }
    }
  {% endaction %}
{% endif %}
Task code is written in Mechanic Liquid, an extension of open-source Liquid enhanced for automation. Learn more