Skip to content
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8750f63
Notification Improvements Stage 1, 70%
TejasRGitHub Dec 26, 2024
1cd2224
Changes in the principal name
TejasRGitHub Dec 27, 2024
1728d52
Weekly email task
TejasRGitHub Dec 30, 2024
daa709e
Weekly notifications code and minor changes
TejasRGitHub Dec 31, 2024
84bf9fe
Glue Table change notifications
TejasRGitHub Jan 2, 2025
8c861ff
Additional comments and logs plus weekly reminder task
TejasRGitHub Jan 3, 2025
99ed2ec
Syncing changes from local deploy
TejasRGitHub Jan 10, 2025
c119c55
Adding new changes
TejasRGitHub Jan 14, 2025
f1e4079
Minor correction in the create bucket policy code when access to buck…
TejasRGitHub Jan 14, 2025
870a835
New changes
TejasRGitHub Jan 15, 2025
5b8ec01
Adding new changes for admin notifications
TejasRGitHub Jan 15, 2025
17158e2
Linting update
TejasRGitHub Jan 15, 2025
fd32987
Admin notification improvements
TejasRGitHub Jan 15, 2025
457ce82
Adding more refactoring changes
TejasRGitHub Jan 15, 2025
878082a
Refactoring and corrections
TejasRGitHub Jan 21, 2025
401b0de
Minor changes after testing
TejasRGitHub Jan 22, 2025
63dd9f1
Adding new changes and corrections
TejasRGitHub Jan 22, 2025
828edf8
Minor change and linting
TejasRGitHub Jan 22, 2025
8be4298
Formatting changes
TejasRGitHub Jan 22, 2025
a408553
Adding improvements after review comments
TejasRGitHub Jan 23, 2025
8b9b10c
Small slight changes
TejasRGitHub Jan 24, 2025
d83d85c
Weekly notification enums
TejasRGitHub Jan 24, 2025
215ebe4
Few corrections
TejasRGitHub Jan 24, 2025
7a92d9a
Minor corrections
TejasRGitHub Jan 28, 2025
60e0988
Merge branch 'main' into GH-1420-notification-improvements-1
Jan 28, 2025
f60e4ce
Resolving tests
TejasRGitHub Jan 28, 2025
83156c7
Filed reformatted by ruff
TejasRGitHub Jan 29, 2025
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
20 changes: 20 additions & 0 deletions backend/dataall/base/feature_toggle_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
"""

import functools
import logging
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is a part of PR

from typing import List, Any, Optional, Callable

from dataall.base.config import config
from dataall.base.utils.decorator_utls import process_func

log = logging.getLogger(__name__)


def is_feature_enabled(config_property: str):
def decorator(f):
Expand Down Expand Up @@ -56,3 +59,20 @@ def decorated(*args, **kwargs):
return fn_decorator(decorated)

return decorator


def is_config_active(config_property: str, default_value: Any):
def decorator(f):
fn, fn_decorator = process_func(f)

@functools.wraps(fn)
def decorated(*args, **kwargs):
value = config.get_property(config_property, default_value)
if not value:
log.info(f'Config - {config_property} is inactive')
return
return fn(*args, **kwargs)

return fn_decorator(decorated)

return decorator
2 changes: 2 additions & 0 deletions backend/dataall/core/groups/db/constants.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should we also explicitly import db in the __init__ file? (at dataall/backend/dataall/core/groups/__init__.py) -- think right now it is implicitly imported via api

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't mind it getting imported implicitly. With a blank init all the group_models and constants file will be imported.

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class DataallGroups:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is a part of PR

admin = 'DAAdministrators'
8 changes: 8 additions & 0 deletions backend/dataall/modules/catalog/tasks/catalog_indexer_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from dataall.base.db import get_engine
from dataall.base.loader import load_modules, ImportMode
from dataall.base.utils.alarm_service import AlarmService
from dataall.modules.notifications.services.admin_notifications import AdminNotificationService
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is a part of PR


log = logging.getLogger(__name__)

Expand All @@ -31,7 +32,14 @@ def index_objects(cls, engine, with_deletes='False'):
CatalogIndexerTask._delete_old_objects(indexed_object_uris)
return len(indexed_object_uris)
except Exception as e:
error_log = f'Error occurred while indexing objects during the cataloging task. Exception: {e}'
log.error(error_log)
AlarmService().trigger_catalog_indexing_failure_alarm(error=str(e))
AdminNotificationService().notify_admins_with_error_log(
process_error='Exception occurred during cataloging task',
error_logs=[error_log],
process_name=cls.__name__,
)
raise e

@classmethod
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import logging
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is a part of PR

from typing import List

from dataall.base.feature_toggle_checker import is_config_active
from dataall.core.groups.db.constants import DataallGroups
from dataall.modules.notifications.services.ses_email_notification_service import SESEmailNotificationService

log = logging.getLogger(__name__)


class AdminNotificationService:
"""
Send email notifications to Admin Group i.e. DAAdministrators in data.all
Args -
1. process_error - string describing in short the error / exception details
2. error_logs - List of all the exception error logs
3. process_name - Code where the exception occurred. Example, inside an ECS task like cataloging task, etc or inside a graphql service
"""

@staticmethod
@is_config_active(
config_property='modules.datasets_base.features.share_notifications.email.parameters.admin_notifications',
default_value=False,
)
def notify_admins_with_error_log(process_error: str, error_logs: List[str], process_name: str = ''):
subject = f'Data.all alert | Attention Required | Failure in : {process_name}'
email_message = f"""
Following error occurred - <br><br> {process_error}
"""
email_message += '<br><br>'.join(error_logs)
email_message += '<br><br> Please check the logs in cloudwatch for more details'

SESEmailNotificationService.create_and_send_email_notifications(
subject=subject, msg=email_message, recipient_groups_list=[DataallGroups.admin]
)
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Email Notification Provider implements the email notification service abstract method
import logging

from dataall.base.aws.cognito import Cognito
from dataall.base.aws.ses import Ses
from dataall.base.config import config
from dataall.base.services.service_provider_factory import ServiceProviderFactory
from dataall.core.groups.db.constants import DataallGroups
from dataall.modules.notifications.services.base_email_notification_service import BaseEmailNotificationService

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -37,19 +38,29 @@ def send_email_task(subject, message, recipient_groups_list, recipient_email_lis
email_provider = SESEmailNotificationService.get_email_provider_instance(
recipient_groups_list, recipient_email_list
)
identityProvider = ServiceProviderFactory.get_service_provider_instance()
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is a part of PR

try:
identityProvider = ServiceProviderFactory.get_service_provider_instance()

email_ids_to_send_emails = email_provider.get_email_ids_from_groupList(
email_provider.recipient_group_list, identityProvider
)
email_ids_to_send_emails = set()
if len(recipient_groups_list) > 0:
email_ids_to_send_emails = email_provider.get_email_ids_from_groupList(
email_provider.recipient_group_list, identityProvider
)

if len(recipient_email_list) > 0:
email_ids_to_send_emails.update(recipient_email_list)

SESEmailNotificationService.send_email_to_users(email_ids_to_send_emails, email_provider, message, subject)

except Exception as e:
email_ids_to_send_emails = email_provider.get_email_ids_from_groupList(
[DataallGroups.admin], identityProvider
)
SESEmailNotificationService.send_email_to_users(
email_ids_to_send_emails,
email_provider,
f'Error sending email due to: {e}',
'Data.all alert | Attention Required | Failure in: Email Notification Service',
)
raise e
else:
return True
Expand All @@ -60,3 +71,29 @@ def send_email_to_users(email_list, email_provider, message, subject):
# https://aws.amazon.com/blogs/messaging-and-targeting/how-to-send-messages-to-multiple-recipients-with-amazon-simple-email-service-ses/
for emailId in email_list:
email_provider.send_email([emailId], message, subject)

@staticmethod
def create_and_send_email_notifications(subject, msg, recipient_groups_list=None, recipient_email_ids=None):
"""
Method to directly send email notification instead of creating an SQS Task
This approach is used while sending email notifications in an ECS task ( e.g. persistent email reminder task, share expiration task, etc )
Emails send to groups mentioned in recipient_groups_list and / or emails mentioned in recipient_email_ids
"""
if recipient_groups_list is None:
recipient_groups_list = []
if recipient_email_ids is None:
recipient_email_ids = []

if share_notification_config := config.get_property(
'modules.datasets_base.features.share_notifications', default=None
):
for share_notification_config_type, n_config in share_notification_config.items():
if n_config.get('active', False):
if share_notification_config_type == 'email':
SESEmailNotificationService.send_email_task(
subject, msg, recipient_groups_list, recipient_email_ids
)
else:
log.info(f'Notification type : {share_notification_config_type} is not active')
else:
log.info('Notifications are not active')
Empty file.
Loading