Hé Snowflake, envoie-moi un e-mail
Snowflake peut désormais envoyer des e-mails. Créons donc une procédure stockée qui vous envoie les résultats d'une requête tous les matins, y compris s'il y a un jour férié quelque part dans le monde qui affecte vos chiffres.
Snowflake peut désormais envoyer des e-mails
Pour envoyer une notification par e-mail avec Snowflake, vous n'avez plus besoin que d'un seul appel SQL :
call system$send_email(
'my_email_int',
'[email protected], [email protected], [email protected]',
'This is the subject',
'This is the body'
);
Comment notifier les utilisateurs dans Snowflake ? ❄️ Flocon de neige en bref - Notifications par e-mail
L'objectif de cet article est de lier cette fonctionnalité à un planificateur et à du code de formatage. Ainsi, chaque matin du lundi au vendredi, nous pouvons obtenir les résultats d'une requête SQL, y compris les jours fériés à venir. Comme celui-ci:

Étape 1 : Développer une procédure stockée qui formate et envoie par e-mail le résultat de toute requête
Voici le code que j'ai écrit, tout en déboguant mes capacités à envoyer par e-mail un résultat de requête bien formaté :
with pretty_email_results as procedure()
returns string
language python
packages = ('snowflake-snowpark-python', 'tabulate')
handler = 'x'
as
$$
def x(session):
printed = session.sql(
"select * from table(result_scan(last_query_id(-1)))"
).to_pandas().to_markdown()
session.call('system$send_email',
'my_email_int',
'[email protected]',
'Email Alert: Task A has finished.',
printed)
$$
call pretty_email_results();
- Snowflake dispose désormais de « procédures anonymes » qui vous permettent de les définir et de les appeler en une seule étape. Vous n'avez pas besoin
create or replace
de premier etcall
plus tard, ce qui est particulièrement utile lors du débogage. - J'ai choisi d'écrire cette procédure en Python, pour utiliser la librairie
tabulate
. Cette bibliothèque formatera les résultats d'une requête, afin qu'ils soient jolis sur notre courrier électronique sortant. - La
tabulate
bibliothèque est déjà fournie par Anaconda dans Snowflake, nous pouvons donc l'utiliser avec la lignepackages = (‘tabulate’)
. - Avec
result_scan(last_query_id(-1)
Snowflake, vous pouvez accéder aux résultats de la dernière requête exécutée, ce qui permetpretty_email_results()
d'envoyer par e-mail les résultats obtenus à l'étape précédente. - Snowpark nous donne l'
session
objet dans notre procédure stockée, que nous pouvons utiliser pour exécuter l'analyse des résultats avecsession.sql()
. session.sql()
nous donne un Snowpark DataFrame, et l'appeler nous donne.to_pandas()
Pandas DataFrame. Pandas.to_markdown()
peut alors appelertabulate
- et il se plaindra à moins que vous ne demandiez pas explicitement ce paquet avecpackages=(...)
.
Une fois votre débogage interactif terminé, vous pouvez déplacer le code vers une procédure stockée permanente :
create or replace procedure email_last_results(send_to string, subject string)
returns string
language python
runtime_version=3.8
packages = ('snowflake-snowpark-python', 'tabulate')
handler = 'x'
execute as caller
as
$$
import snowflake
def x(session, send_to, subject):
try:
body = session.sql(
"select * from table(result_scan(last_query_id(-1))) limit 100"
).to_pandas().to_markdown()
except snowflake.snowpark.exceptions.SnowparkSQLException as e:
body = '%s\n%s' % (type(e), e)
session.call('system$send_email',
'my_email_int',
send_to,
subject,
body)
return 'email sent:\n%s' % body
$$;
execute as caller
est nécessaire ici pour que la procédure stockée puisse trouver l'historique des requêtes de l'utilisateur qui l'appelle.runtime_version=3.8
doit être explicite dans une procédure stockée permanente.- J'ai ajouté du code pour intercepter les exceptions et envoyer quand même un joli e-mail.
- J'ai déplacé le sujet et les destinataires vers les arguments de la procédure.
- J'ai ajouté un
limit 100
pour empêcher l'envoi d'e-mails de la taille d'un To.
call email_last_results('[email protected]', 'results from snowflake');
Désormais, une simple procédure stockée SQL peut exécuter une requête et demander à notre procédure Python d'envoyer les résultats par e-mail :
create or replace procedure run_query_and_email_it()
returns string
execute as caller
as
$$
begin
-- any query you'd like to run
select 'now' as what, to_char(current_timestamp) as value
union all
select 'upcoming', day || ' ' ||holiday
from table(fh_db.public.holidays('US', [year(current_date), year(current_date)+1]))
where day between current_date() and current_date()+60
;
-- call the stored procedure that formats and emails the results
call email_last_results('[email protected]', 'upcoming holidays');
return 'done';
end
$$
;
- Pour obtenir une table avec tous les jours fériés pour les 60 prochains jours , il appelle mon UDTF précédemment défini .
holidays
Génération de tous les jours fériés en SQL - avec un UDTF Python
call run_query_and_email_it();
Snowflake a un planificateur de tâches prêt pour vos demandes :
create or replace task email_me_frequently
warehouse = 's'
schedule = 'using cron 0 8 * * 1-5 America/Los_Angeles'
as call run_query_and_email_it();
Quelques notes:
- Je lui ai demandé d'utiliser mon entrepôt appelé "s". Snowflake propose également des tâches sans serveur , mais celles-ci n'exécutent pas de procédures stockées Python.
- J'ai dû modifier mon
holidays()
UDF en déplaçant les.zip
dépendances Python d'une étape utilisateur vers une étape nommée . Quand il vivait à l'intérieur de ma scène utilisateur, la tâche a généré l'erreurRemote file ‘holidays.zip’ was not found
. - Changez la planification en chaque
1 minute
si vous avez besoin de déboguer.
alter task email_me_frequently resume;
select *
from table(information_schema.task_history(
scheduled_time_range_start=>dateadd('hour',-48,current_timestamp()),
result_limit => 100));
Images generated by AI
Ne vous inquiétez pas trop de la création d'un système d'alerte - Snowflake est déjà en train de le développer ( actuellement en préversion privée ) :
CREATE ALERT Warehouse_Credit_Usage_Alert
WAREHOUSE = my_warehouse
SCHEDULE = ‘USING CRON 0 7 * * *UTC’ // everyday at 7 am
IF (EXISTS (SELECT
Warehouse_name,
SUM(CREDITS_USED) AS credits
FROM snowflake.account_usage.warehouse_metering_history
// aggregate warehouse Credit_used for the past 24 hours
WHERE datediff(hour, start_time, CURRENT_TIMESTAMP ())<=24
GROUP BY 1
HAVING credits > 10
ORDER BY 2 DESC))
THEN system$send_email (
‘My_email_notification_integration’,
‘admin1@company,com, [email protected]’,
‘Email Alert: Excessive warehouse usage!’,
‘Warehouse usage exceeds 10 credits in the past 24 hours’
)
- Essayez ceci avec un compte d'essai gratuit Snowflake - vous n'avez besoin que d'une adresse e-mail pour commencer.
- Jouez avec les options de formatage qu'offre
tabulate
.