8
8
from . import Integration
9
9
10
10
try :
11
- from flask_login import current_user as current_user_proxy
11
+ import flask_login
12
12
except ImportError :
13
- current_user_proxy = None
13
+ flask_login = None
14
14
15
15
from flask import Flask , _request_ctx_stack , _app_ctx_stack
16
16
from flask .signals import (
17
17
appcontext_pushed ,
18
18
appcontext_tearing_down ,
19
19
got_request_exception ,
20
+ request_started ,
20
21
)
21
22
22
23
@@ -29,6 +30,7 @@ def __init__(self):
29
30
def install (self , client ):
30
31
appcontext_pushed .connect (_push_appctx )
31
32
appcontext_tearing_down .connect (_pop_appctx )
33
+ request_started .connect (_request_started )
32
34
got_request_exception .connect (_capture_exception )
33
35
34
36
old_app = Flask .__call__
@@ -45,61 +47,25 @@ def _push_appctx(*args, **kwargs):
45
47
# always want to push scope regardless of whether WSGI app might already
46
48
# have (not the case for CLI for example)
47
49
get_current_hub ().push_scope ()
50
+ get_current_hub ().add_event_processor (_make_user_event_processor )
48
51
49
- app = getattr (_app_ctx_stack .top , "app" , None )
50
52
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 ()
55
55
56
- try :
57
- weak_user = weakref .ref (current_user_proxy ._get_current_object ())
58
- except (AttributeError , RuntimeError , TypeError ):
59
- weak_user = lambda : None
60
56
57
+ def _request_started (sender , ** kwargs ):
58
+ weak_request = weakref .ref (_request_ctx_stack .top .request )
59
+ app = _app_ctx_stack .top .app
61
60
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 )
63
62
)
64
63
65
64
66
- def _pop_appctx (* args , ** kwargs ):
67
- get_current_hub ().pop_scope_unsafe ()
68
-
69
-
70
65
def _capture_exception (sender , exception , ** kwargs ):
71
66
capture_exception (exception )
72
67
73
68
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
-
103
69
def _process_frames (app , event ):
104
70
for frame in event .iter_frames ():
105
71
if "in_app" in frame :
@@ -139,28 +105,57 @@ def size_of_file(self, file):
139
105
return file .content_length
140
106
141
107
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
165
160
166
- event [ "user" ] = user_info
161
+ return inner
0 commit comments