11import json
2- import logging
32from typing import Any
43
54import requests
5+ import structlog
66from django .core .serializers .json import DjangoJSONEncoder
77
88from audit .models import AuditLog
1111from features .models import FeatureState
1212from integrations .common .wrapper import AbstractBaseEventIntegrationWrapper
1313
14- logger = logging . getLogger ( __name__ )
14+ logger = structlog . get_logger ( "sentry_change_tracking" )
1515
1616
1717class SentryChangeTracking (AbstractBaseEventIntegrationWrapper ):
@@ -59,17 +59,19 @@ def generate_event_data(audit_log_record: AuditLog) -> dict[str, Any]:
5959 "id" : getattr (audit_log_record .author , "email" , "app@flagsmith.com" ),
6060 "type" : "email" ,
6161 },
62+ "change_id" : str (feature_state .pk ),
6263 }
6364
64- if action == "updated" :
65- inner_payload ["change_id" ] = str (feature_state .pk )
66-
6765 return inner_payload
6866
6967 def _track_event (self , event : dict [str , Any ]) -> None :
7068 action = event ["action" ]
7169 feature_name = event ["flag" ]
72- logger .debug ("Sending '%s' (%s) to Sentry..." , feature_name , action )
70+
71+ log = logger .bind (
72+ sentry_action = action ,
73+ feature_name = feature_name ,
74+ )
7375
7476 payload = {
7577 "data" : [event ],
@@ -82,21 +84,33 @@ def _track_event(self, event: dict[str, Any]) -> None:
8284 "X-Sentry-Signature" : sign_payload (json_payload , self .secret ),
8385 }
8486
85- response = requests .post (
87+ log .debug (
88+ "sending" ,
8689 url = self .webhook_url ,
8790 headers = headers ,
88- data = json_payload ,
91+ payload = payload ,
8992 )
9093
9194 try :
92- response .raise_for_status ()
95+ response = requests .post (
96+ url = self .webhook_url ,
97+ headers = headers ,
98+ data = json_payload ,
99+ )
100+ response .raise_for_status () # NOTE: This is for future-proofing, as Sentry won't respond 4xx.
93101 except requests .exceptions .RequestException as error :
94- # TODO: Should we retry, or ultimately notify the admin of a persisting issue?
95- logger .error (
96- "Error sending '%s' (%s) to Sentry: %s" ,
97- feature_name ,
98- action ,
99- repr (error ),
102+ log .warning (
103+ "request-failure" ,
104+ error = error ,
100105 )
101- else :
102- logger .debug ("Sent '%s' (%s) to Sentry" , feature_name , action )
106+ return
107+
108+ if not response .text : # This is fragile and undocumented. ¯\_(ツ)_/¯
109+ log .info ("success" )
110+ return
111+
112+ log .warning (
113+ "integration-error" ,
114+ sentry_response_status = response .status_code ,
115+ sentry_response_body = response .text ,
116+ )
0 commit comments