1212def init_sentry () -> bool :
1313 """
1414 Initialize Sentry SDK if SENTRY_DSN is configured.
15-
15+
1616 Returns:
1717 bool: True if Sentry was initialized, False otherwise
1818 """
1919 sentry_dsn = os .getenv ("SENTRY_DSN" )
20-
20+
2121 if not sentry_dsn :
2222 print ("ℹ️ Sentry DSN not configured - error tracking disabled" )
2323 return False
24-
24+
2525 try :
2626 import sentry_sdk
2727 from sentry_sdk .integrations .fastapi import FastApiIntegration
2828 from sentry_sdk .integrations .starlette import StarletteIntegration
29-
29+
3030 environment = os .getenv ("ENVIRONMENT" , "development" )
31-
31+
3232 sentry_sdk .init (
3333 dsn = sentry_dsn ,
3434 environment = environment ,
35-
35+
3636 # Performance monitoring - sample rate based on environment
3737 traces_sample_rate = 0.1 if environment == "production" else 1.0 ,
38-
38+
3939 # Profile sampled transactions
4040 profiles_sample_rate = 0.1 if environment == "production" else 1.0 ,
41-
41+
4242 # Send PII for debugging (user IDs, emails)
4343 send_default_pii = True ,
44-
44+
4545 # Integrations
4646 integrations = [
4747 FastApiIntegration (transaction_style = "endpoint" ),
4848 StarletteIntegration (transaction_style = "endpoint" ),
4949 ],
50-
50+
5151 # Filter noisy events
5252 before_send = _filter_events ,
53-
53+
5454 # Debug mode for development
5555 debug = environment == "development" ,
56-
56+
5757 # Attach stack traces to messages
5858 attach_stacktrace = True ,
59-
59+
6060 # Include local variables in stack traces
6161 include_local_variables = True ,
6262 )
63-
63+
6464 print (f"✅ Sentry initialized (environment: { environment } )" )
6565 return True
66-
66+
6767 except ImportError :
6868 print ("⚠️ sentry-sdk not installed - error tracking disabled" )
6969 return False
@@ -74,26 +74,26 @@ def init_sentry() -> bool:
7474
7575def _filter_events (event , hint ):
7676 """Filter out noisy events before sending to Sentry."""
77-
77+
7878 # Don't send health check errors
7979 request_url = event .get ("request" , {}).get ("url" , "" )
8080 if "/health" in request_url :
8181 return None
82-
82+
8383 # Don't send 404s for common bot paths
8484 exception_values = event .get ("exception" , {}).get ("values" , [])
8585 if exception_values :
8686 exception_value = str (exception_values [0 ].get ("value" , "" ))
8787 bot_paths = ["/wp-admin" , "/wp-login" , "/.env" , "/config" , "/admin" , "/phpmyadmin" , "/.git" ]
8888 if any (path in exception_value for path in bot_paths ):
8989 return None
90-
90+
9191 # Don't send validation errors (they're expected)
9292 if exception_values :
9393 exception_type = exception_values [0 ].get ("type" , "" )
9494 if exception_type in ("RequestValidationError" , "ValidationError" ):
9595 return None
96-
96+
9797 return event
9898
9999
@@ -104,7 +104,7 @@ def _filter_events(event, hint):
104104def set_user_context (user_id : Optional [str ] = None , email : Optional [str ] = None ):
105105 """
106106 Set user context for error tracking.
107-
107+
108108 DEPRECATED: Use from services.observability import set_user_context
109109 """
110110 try :
@@ -117,7 +117,7 @@ def set_user_context(user_id: Optional[str] = None, email: Optional[str] = None)
117117def capture_exception (error : Exception , ** extra_context ):
118118 """
119119 Manually capture an exception with additional context.
120-
120+
121121 DEPRECATED: Use from services.observability import capture_exception
122122 """
123123 try :
@@ -133,7 +133,7 @@ def capture_exception(error: Exception, **extra_context):
133133def capture_message (message : str , level : str = "info" , ** extra_context ):
134134 """
135135 Capture a message (not an exception) for tracking.
136-
136+
137137 DEPRECATED: Use from services.observability import get_logger
138138 """
139139 try :
@@ -149,7 +149,7 @@ def capture_message(message: str, level: str = "info", **extra_context):
149149def set_operation_context (operation : str , ** tags ):
150150 """
151151 Set operation context for the current scope.
152-
152+
153153 DEPRECATED: Use from services.observability import trace_operation
154154 """
155155 try :
@@ -159,3 +159,19 @@ def set_operation_context(operation: str, **tags):
159159 sentry_sdk .set_tag (key , str (value ))
160160 except ImportError :
161161 pass
162+
163+
164+ def capture_http_exception (request , exc : Exception , status_code : int ):
165+ """
166+ Capture HTTP exception with request context for error tracking.
167+ """
168+ try :
169+ import sentry_sdk
170+ with sentry_sdk .push_scope () as scope :
171+ scope .set_extra ("status_code" , status_code )
172+ scope .set_extra ("path" , str (request .url .path ))
173+ scope .set_extra ("method" , request .method )
174+ sentry_sdk .capture_exception (exc )
175+ except ImportError :
176+ pass
177+ pass
0 commit comments