Skip to content

Commit a0cdcc2

Browse files
committed
added request and response hook - may be very buggy
1 parent 634c2ac commit a0cdcc2

File tree

2 files changed

+52
-6
lines changed

2 files changed

+52
-6
lines changed

instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py

+35-4
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ def hello():
5858
from opentelemetry.propagate import extract
5959
from opentelemetry.util._time import _time_ns
6060
from opentelemetry.util.http import get_excluded_urls
61+
from opentelemetry.sdk.trace import Span
62+
63+
6164

6265
_logger = getLogger(__name__)
6366

@@ -69,6 +72,7 @@ def hello():
6972

7073
_excluded_urls = get_excluded_urls("FLASK")
7174

75+
"""FIND REPLACEMENT FOR Callable"""
7276

7377
def get_default_span_name():
7478
span_name = ""
@@ -78,6 +82,11 @@ def get_default_span_name():
7882
span_name = otel_wsgi.get_default_span_name(flask.request.environ)
7983
return span_name
8084

85+
def otel_request_hook_default(span, request):
86+
return "hi"
87+
88+
def otel_response_hook_default(span, request, response):
89+
return "hey"
8190

8291
def _rewrapped_app(wsgi_app):
8392
def _wrapped_app(wrapped_app_environ, start_response):
@@ -95,12 +104,17 @@ def _start_response(status, response_headers, *args, **kwargs):
95104
otel_wsgi.add_response_attributes(
96105
span, status, response_headers
97106
)
107+
if _InstrumentedFlask.otel_response_hook:
108+
_InstrumentedFlask.otel_response_hook(
109+
span, flask.request.environ, flask.Response
110+
)
98111
else:
99112
_logger.warning(
100113
"Flask environ's OpenTelemetry span "
101114
"missing at _start_response(%s)",
102115
status,
103116
)
117+
104118

105119
return start_response(status, response_headers, *args, **kwargs)
106120

@@ -109,13 +123,14 @@ def _start_response(status, response_headers, *args, **kwargs):
109123
return _wrapped_app
110124

111125

112-
def _wrapped_before_request(name_callback):
126+
def _wrapped_before_request(name_callback, otel_request_hook):
113127
def _before_request():
114128
if _excluded_urls.url_disabled(flask.request.url):
115129
return
116130

117131
flask_request_environ = flask.request.environ
118132
span_name = name_callback()
133+
# request_hook = otel_request_hook()
119134
token = context.attach(
120135
extract(flask_request_environ, getter=otel_wsgi.wsgi_getter)
121136
)
@@ -124,6 +139,7 @@ def _before_request():
124139

125140
span = tracer.start_span(
126141
span_name,
142+
# request_hook,
127143
kind=trace.SpanKind.SERVER,
128144
start_time=flask_request_environ.get(_ENVIRON_STARTTIME_KEY),
129145
)
@@ -143,6 +159,9 @@ def _before_request():
143159
flask_request_environ[_ENVIRON_ACTIVATION_KEY] = activation
144160
flask_request_environ[_ENVIRON_SPAN_KEY] = span
145161
flask_request_environ[_ENVIRON_TOKEN] = token
162+
163+
if _InstrumentedFlask.otel_request_hook:
164+
_InstrumentedFlask.otel_request_hook(span, flask_request_environ)
146165

147166
return _before_request
148167

@@ -171,6 +190,8 @@ def _teardown_request(exc):
171190
class _InstrumentedFlask(flask.Flask):
172191

173192
name_callback = get_default_span_name
193+
otel_request_hook = otel_request_hook_default
194+
otel_response_hook = otel_response_hook_default
174195

175196
def __init__(self, *args, **kwargs):
176197
super().__init__(*args, **kwargs)
@@ -179,7 +200,8 @@ def __init__(self, *args, **kwargs):
179200
self.wsgi_app = _rewrapped_app(self.wsgi_app)
180201

181202
_before_request = _wrapped_before_request(
182-
_InstrumentedFlask.name_callback
203+
_InstrumentedFlask.name_callback,
204+
_InstrumentedFlask.otel_request_hook,
183205
)
184206
self._before_request = _before_request
185207
self.before_request(_before_request)
@@ -193,15 +215,24 @@ class FlaskInstrumentor(BaseInstrumentor):
193215
See `BaseInstrumentor`
194216
"""
195217

218+
"""
219+
THIS SHOULD BE DONE
220+
"""
196221
def _instrument(self, **kwargs):
197222
self._original_flask = flask.Flask
223+
otel_request_hook = kwargs.pop("request_hook", None)
224+
otel_response_hook = kwargs.pop("response_hook", None)
198225
name_callback = kwargs.get("name_callback")
199226
if callable(name_callback):
200227
_InstrumentedFlask.name_callback = name_callback
228+
if callable(otel_request_hook):
229+
_InstrumentedFlask.otel_request_hook = otel_request_hook
230+
if callable(otel_response_hook):
231+
_InstrumentedFlask.otel_response_hook = otel_response_hook
201232
flask.Flask = _InstrumentedFlask
202233

203234
def instrument_app(
204-
self, app, name_callback=get_default_span_name
235+
self, app, name_callback=get_default_span_name, otel_request_hook=otel_request_hook_default
205236
): # pylint: disable=no-self-use
206237
if not hasattr(app, "_is_instrumented"):
207238
app._is_instrumented = False
@@ -210,7 +241,7 @@ def instrument_app(
210241
app._original_wsgi_app = app.wsgi_app
211242
app.wsgi_app = _rewrapped_app(app.wsgi_app)
212243

213-
_before_request = _wrapped_before_request(name_callback)
244+
_before_request = _wrapped_before_request(name_callback, otel_request_hook)
214245
app._before_request = _before_request
215246
app.before_request(_before_request)
216247
app.teardown_request(_teardown_request)

instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,23 @@ def setUp(self):
196196

197197
def custom_span_name():
198198
return "flask-custom-span-name"
199+
200+
# request_hook_args = ()
201+
# response_hook_args = ()
202+
203+
# def request_hook(span, request):
204+
# nonlocal request_hook_args
205+
# request_hook_args = (span, request)
206+
207+
# def response_hook(span, request, response):
208+
# nonlocal response_hook_args
209+
# response_hook_args = (span, request, response)
210+
# response["hook-header"] = "set by hook"
199211

200212
self.app = Flask(__name__)
201213

202214
FlaskInstrumentor().instrument_app(
203-
self.app, name_callback=custom_span_name
215+
self.app, name_callback=custom_span_name, otel_request_hook=request_hook
204216
)
205217

206218
self._common_initialization()
@@ -217,6 +229,9 @@ def test_custom_span_name(self):
217229
self.assertEqual(len(span_list), 1)
218230
self.assertEqual(span_list[0].name, "flask-custom-span-name")
219231

232+
def test_hooks(self):
233+
self.client.get("/hello/123")
234+
220235

221236
class TestProgrammaticCustomSpanNameCallbackWithoutApp(
222237
InstrumentationTest, TestBase, WsgiTestBase
@@ -227,7 +242,7 @@ def setUp(self):
227242
def custom_span_name():
228243
return "instrument-without-app"
229244

230-
FlaskInstrumentor().instrument(name_callback=custom_span_name)
245+
FlaskInstrumentor().instrument(name_callback=custom_span_name, otel_request_hook=custom_span_name)
231246
# pylint: disable=import-outside-toplevel,reimported,redefined-outer-name
232247
from flask import Flask
233248

0 commit comments

Comments
 (0)