I have a working Flask endpoint decorated with flasgger.swag_from decorator:
from flasgger import swag_from
@app.route("/jobs", methods=["GET"])
@swag_from('swagger/get_jobs.yml')
def get_jobs(request_id):
# ...
This works as expected.
I'm using DataDog and would like to time every call to this endpoint. Based on this documentation, this can easily be achieved by adding the timed decorator:
from flasgger import swag_from
from datadog import statsd
@app.route("/jobs", methods=["GET"])
@swag_from('swagger/get_jobs.yml')
@statsd.timed("api_call.duration")
def get_jobs(request_id):
# ...
However - once I do that, I get an error when trying to render the Swagger page:
The log shows the error is a FileNotFoundError caused by Swagger looking for the yml file in the wrong location:
FileNotFoundError: [Errno 2] No such file or directory: '/usr/local/lib/python3.7/site-packages/datadog/dogstatsd/swagger/backup_sources.yml'
Based on this post, this error sometimes happens when Flask's "static_folder" is configured incorrectly. I've tried changing it, using Flask(__name__, static_folder='./'), but the same issue persists.

Found the issue.
Turns out that if you provide a relative path to
@swag_from(as I do above:swagger/get_jobs.yml), Flassger "guesses" the root path by calling:When I added the
@statsd.timeddecorator below the@swag_fromdecorator, I'm basically running the statsd decorator "before" the Flassger one - i.e. the Flassger decorator runs over a wrapper function generated by statsd, which means theobj.__globals__['__file__']is the statsd source file, which will make Flassger look for the swagger file under/usr/local/lib/python3.7/site-packages/datadog/dogstatsd.The simple workaround is to reverse the decorator order, i.e. running the Flasgger decorator "before" the statsd one, by placing it second:
There might be other solutions - providing an absolute path in
swag_fromor somehow setting aroot_pathattribute on theget_jobsmethod (not sure how to do that).