Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Documentation for notification feature extension #29191

Merged
merged 4 commits into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions airflow/provider.yaml.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@
"type": "string"
}
},
"notifications": {
"type": "array",
"description": "Notification class names",
"items": {
"type": "string"
}
},
"plugins": {
"type": "array",
"description": "Plugins exposed by the provider",
Expand Down
7 changes: 7 additions & 0 deletions airflow/provider_info.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@
"type": "string"
}
},
"notifications": {
"type": "array",
"description": "Notification class names",
"items": {
"type": "string"
}
},
"task-decorators": {
"type": "array",
"description": "Apply custom decorators to the TaskFlow API. Can be accessed by users via '@task.<name>'",
Expand Down
3 changes: 3 additions & 0 deletions airflow/providers/slack/provider.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,6 @@ connection-types:
connection-type: slack
- hook-class-name: airflow.providers.slack.hooks.slack_webhook.SlackWebhookHook
connection-type: slackwebhook

notifications:
- airflow.providers.slack.notifications.slack_notifier.SlackNotifier
29 changes: 29 additions & 0 deletions docs/apache-airflow-providers/core-extensions/notifications.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

.. http://www.apache.org/licenses/LICENSE-2.0

.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.

Notifications
-------------
This is a summary of all Apache Airflow Community provided implementations of notifications.

Notifications allow you to send messages to external systems when a task instance/DAG run changes state.

Notifications are explained in :doc:`apache-airflow:howto/notifications` and here you can also see all the
notifications provided by the community-managed providers:

.. airflow-notifications::
:tags: None
:header-separator: "
9 changes: 9 additions & 0 deletions docs/apache-airflow-providers/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ than from its own Database.
You can see all secret backends available via community-managed providers in
:doc:`/core-extensions/secrets-backends`.

Notifications
'''''''''''''

The providers can add custom notifications, that allow you to configure the way how you would like to receive
notifications about the status of your tasks/DAGs.

You can see all the notifications available via community-managed providers in
:doc:`/core-extensions/notifications`.


Installing and upgrading providers
----------------------------------
Expand Down
1 change: 1 addition & 0 deletions docs/apache-airflow/howto/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ configuring an Airflow environment.
Using the CLI <usage-cli>
add-dag-tags
add-owner-links
notifications
set-config
set-up-database
operator/index
Expand Down
77 changes: 77 additions & 0 deletions docs/apache-airflow/howto/notifications.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

.. http://www.apache.org/licenses/LICENSE-2.0

.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.

Creating a notifier
===================
The :class:`~airflow.notifications.basenotifier.BaseNotifier` is an abstract class that provides a basic
structure for sending notifications in Airflow using the various ``on_*__callback``.
It is intended for providers to extend and customize for their specific needs.

To extend the BaseNotifier class, you will need to create a new class that inherits from it. In this new class,
you should override the ``notify`` method with your own implementation that sends the notification. The ``notify``
method takes in a single parameter, the Airflow context, which contains information about the current task and execution.

You can also set the ``template_fields`` attribute to specify which attributes should be rendered as templates.

Here's an example of how you can create a Notifier class:

.. code-block:: python

from airflow.notifications.basenotifier import BaseNotifier
from my_provider import send_message


class MyNotifier(BaseNotifier):
template_fields = ("message",)

def __init__(self, message):
self.message = message

def notify(self, context):
# Send notification here, below is an example
title = f"Task {context['task_instance'].task_id} failed"
send_message(title, self.message)

Using a notifier
----------------
Once you have a notifier implementation, you can use it in your ``DAG`` definition by passing it as an argument to
the ``on_*_callbacks``. For example, you can use it with ``on_success_callback`` or ``on_failure_callback`` to send
notifications based on the status of a task or a DAG run.

Here's an example of using the above notifier:

.. code-block:: python

from airflow import DAG
from myprovider.notifier import MyNotifier
from datetime import datetime

with DAG(
dag_id="example_notifier",
start_date=datetime(2022, 1, 1),
schedule_interval=None,
on_success_callback=MyNotifier(message="Success!"),
on_failure_callback=MyNotifier(message="Failure!"),
):
task = BashOperator(
task_id="example_task",
bash_command="exit 1",
on_success_callback=MyNotifier(message="Task Succeeded!"),
)

For a list of community-managed notifiers, see
:doc:`apache-airflow-providers:core-extensions/notifications`.
5 changes: 5 additions & 0 deletions docs/apache-airflow/public-airflow-interface.rst
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,11 @@ Email notifications
Airflow has a built-in way of sending email notifications and it allows to extend it by adding custom
email notification classes. You can read more about email notifications in :doc:`howto/email-config`.

Notifications
-------------
Airflow has a built-in extensible way of sending notifications using the various ``on_*_callback``. You can read more
about notifications in :doc:`howto/notifications`.

Cluster Policies
----------------

Expand Down
27 changes: 27 additions & 0 deletions docs/exts/notifications.rst.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{#
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
#}
{%for provider, provider_dict in items.items() %}
{{ provider_dict['name'] }}
{{ header_separator * (provider_dict['name']|length) }}

{% for notification in provider_dict['notifications'] -%}
- :class:`~{{ notification }}`
{% endfor -%}

{% endfor %}
30 changes: 30 additions & 0 deletions docs/exts/operators_and_hooks_ref.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,26 @@ def _render_extra_links_content(*, header_separator: str):
return _render_template("extra_links.rst.jinja2", items=tabular_data, header_separator=header_separator)


def _prepare_notifications_data():
package_data = load_package_data()
all_notifiers = {}
for provider in package_data:
notifications = provider.get("notifications")
if notifications:
package_name = provider["package-name"]
all_notifiers[package_name] = {
"name": provider["name"],
"notifications": notifications,
}
return all_notifiers


def _render_notification_content(*, header_separator: str):
tabular_data = _prepare_notifications_data()

return _render_template("notifications.rst.jinja2", items=tabular_data, header_separator=header_separator)


class BaseJinjaReferenceDirective(Directive):
"""The base directive for OperatorsHooksReferenceDirective and TransfersReferenceDirective"""

Expand Down Expand Up @@ -367,6 +387,15 @@ def render_content(self, *, tags: set[str] | None, header_separator: str = DEFAU
)


class NotificationsDirective(BaseJinjaReferenceDirective):
"""Generate list of notifiers"""

def render_content(self, *, tags: set[str] | None, header_separator: str = DEFAULT_HEADER_SEPARATOR):
return _render_notification_content(
header_separator=header_separator,
)


def setup(app):
"""Setup plugin"""
app.add_directive("operators-hooks-ref", OperatorsHooksReferenceDirective)
Expand All @@ -376,6 +405,7 @@ def setup(app):
app.add_directive("airflow-secrets-backends", SecretsBackendDirective)
app.add_directive("airflow-connections", ConnectionsDirective)
app.add_directive("airflow-extra-links", ExtraLinksDirective)
app.add_directive("airflow-notifications", NotificationsDirective)

return {"parallel_read_safe": True, "parallel_write_safe": True}

Expand Down