88from . import Integration
99
1010try :
11- from flask_login import current_user as current_user_proxy
11+ import flask_login
1212except ImportError :
13- current_user_proxy = None
13+ flask_login = None
1414
1515from flask import Flask , _request_ctx_stack , _app_ctx_stack
1616from flask .signals import (
1717 appcontext_pushed ,
1818 appcontext_tearing_down ,
1919 got_request_exception ,
20+ request_started ,
2021)
2122
2223
@@ -29,6 +30,7 @@ def __init__(self):
2930 def install (self , client ):
3031 appcontext_pushed .connect (_push_appctx )
3132 appcontext_tearing_down .connect (_pop_appctx )
33+ request_started .connect (_request_started )
3234 got_request_exception .connect (_capture_exception )
3335
3436 old_app = Flask .__call__
@@ -45,61 +47,25 @@ def _push_appctx(*args, **kwargs):
4547 # always want to push scope regardless of whether WSGI app might already
4648 # have (not the case for CLI for example)
4749 get_current_hub ().push_scope ()
50+ get_current_hub ().add_event_processor (_make_user_event_processor )
4851
49- app = getattr (_app_ctx_stack .top , "app" , None )
5052
51- try :
52- weak_request = weakref .ref (_request_ctx_stack .top .request )
53- except AttributeError :
54- weak_request = lambda : None
53+ def _pop_appctx (* args , ** kwargs ):
54+ get_current_hub ().pop_scope_unsafe ()
5555
56- try :
57- weak_user = weakref .ref (current_user_proxy ._get_current_object ())
58- except (AttributeError , RuntimeError , TypeError ):
59- weak_user = lambda : None
6056
57+ def _request_started (sender , ** kwargs ):
58+ weak_request = weakref .ref (_request_ctx_stack .top .request )
59+ app = _app_ctx_stack .top .app
6160 get_current_hub ().add_event_processor (
62- lambda : _make_event_processor (app , weak_request , weak_user )
61+ lambda : _make_request_event_processor (app , weak_request )
6362 )
6463
6564
66- def _pop_appctx (* args , ** kwargs ):
67- get_current_hub ().pop_scope_unsafe ()
68-
69-
7065def _capture_exception (sender , exception , ** kwargs ):
7166 capture_exception (exception )
7267
7368
74- def _make_event_processor (app , weak_request , weak_user ):
75- client_options = get_current_hub ().client .options
76-
77- def event_processor (event ):
78- request = weak_request ()
79-
80- # if the request is gone we are fine not logging the data from
81- # it. This might happen if the processor is pushed away to
82- # another thread.
83- if request is not None :
84- if "transaction" not in event :
85- try :
86- event ["transaction" ] = request .url_rule .endpoint
87- except Exception :
88- pass
89-
90- with _internal_exceptions ():
91- FlaskRequestExtractor (request ).extract_into_event (event , client_options )
92-
93- if _should_send_default_pii ():
94- with _internal_exceptions ():
95- _set_user_info (request , weak_user (), event )
96-
97- with _internal_exceptions ():
98- _process_frames (app , event )
99-
100- return event_processor
101-
102-
10369def _process_frames (app , event ):
10470 for frame in event .iter_frames ():
10571 if "in_app" in frame :
@@ -139,28 +105,57 @@ def size_of_file(self, file):
139105 return file .content_length
140106
141107
142- def _set_user_info (request , user , event ):
143- if "user" in event :
144- return
145-
146- if request :
147- try :
148- ip_address = request .access_route [0 ]
149- except IndexError :
150- ip_address = request .remote_addr
151- else :
152- ip_address = None
153-
154- user_info = {"id" : None , "ip_address" : ip_address }
155-
156- try :
157- user_info ["id" ] = user .get_id ()
158- # TODO: more configurable user attrs here
159- except AttributeError :
160- # might happen if:
161- # - flask_login could not be imported
162- # - flask_login is not configured
163- # - no user is logged in
164- pass
108+ def _make_request_event_processor (app , weak_request ):
109+ client_options = get_current_hub ().client .options
110+
111+ def inner (event ):
112+ with _internal_exceptions ():
113+ _process_frames (app , event )
114+
115+ request = weak_request ()
116+
117+ # if the request is gone we are fine not logging the data from
118+ # it. This might happen if the processor is pushed away to
119+ # another thread.
120+ if request is None :
121+ return
122+
123+ if "transaction" not in event :
124+ try :
125+ event ["transaction" ] = request .url_rule .endpoint
126+ except Exception :
127+ pass
128+
129+ with _internal_exceptions ():
130+ FlaskRequestExtractor (request ).extract_into_event (event , client_options )
131+
132+ return inner
133+
134+
135+ def _make_user_event_processor ():
136+ def inner (event ):
137+ if flask_login is None or not _should_send_default_pii ():
138+ return
139+
140+ user = flask_login .current_user
141+ if user is None :
142+ return
143+
144+ with _internal_exceptions ():
145+ # Access this object as late as possible as accessing the user
146+ # is relatively costly
147+
148+ user_info = event .setdefault ("user" , {})
149+
150+ if user_info .get ("id" , None ) is None :
151+ try :
152+ user_info ["id" ] = user .get_id ()
153+ # TODO: more configurable user attrs here
154+ except AttributeError :
155+ # might happen if:
156+ # - flask_login could not be imported
157+ # - flask_login is not configured
158+ # - no user is logged in
159+ pass
165160
166- event [ "user" ] = user_info
161+ return inner
0 commit comments