diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..14a1bfc2 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +.tox +build diff --git a/charts/deckhand/templates/deployment.yaml b/charts/deckhand/templates/deployment.yaml index ddfa972a..5d40bbe1 100644 --- a/charts/deckhand/templates/deployment.yaml +++ b/charts/deckhand/templates/deployment.yaml @@ -78,8 +78,16 @@ spec: mountPath: /etc/deckhand/policy.yaml subPath: policy.yaml readOnly: true +{{ if .Values.conf.deckhand.DEFAULT.profiler }} + - name: tmp-profiles + mountPath: /tmp/profiles +{{ end }} {{ if $mounts_deckhand.volumeMounts }}{{ toYaml $mounts_deckhand.volumeMounts | indent 12 }}{{ end }} volumes: +{{ if .Values.conf.deckhand.DEFAULT.profiler }} + - name: tmp-profiles + emptyDir: {} +{{ end }} - name: etc-deckhand emptyDir: {} - name: deckhand-etc diff --git a/charts/deckhand/values.yaml b/charts/deckhand/values.yaml index d3c40dcf..05c615f1 100644 --- a/charts/deckhand/values.yaml +++ b/charts/deckhand/values.yaml @@ -215,6 +215,7 @@ conf: debug: true use_stderr: true use_syslog: true + profiler: false database: connection: keystone_authtoken: diff --git a/deckhand/conf/config.py b/deckhand/conf/config.py index f5128393..ae64e3a2 100644 --- a/deckhand/conf/config.py +++ b/deckhand/conf/config.py @@ -48,6 +48,9 @@ Possible values: * True * False """), + cfg.BoolOpt('profiler', default=False, + help="Enabling profiling of API requests. Do NOT " + "use in production."), ] diff --git a/deckhand/service.py b/deckhand/service.py index 1de32bce..1dc00b5b 100644 --- a/deckhand/service.py +++ b/deckhand/service.py @@ -17,6 +17,7 @@ import os import falcon from oslo_config import cfg from oslo_log import log +from werkzeug.contrib.profiler import ProfilerMiddleware from deckhand.control import base from deckhand.control import buckets @@ -82,5 +83,11 @@ def deckhand_app_factory(global_config, **local_config): app = falcon.API(request_type=base.DeckhandRequest, middleware=middleware_list) - - return configure_app(app, version='v1.0') + if CONF.profiler: + LOG.warning("Profiler ENABLED. Expect significant " + "performance overhead.") + return ProfilerMiddleware( + configure_app(app, version='v1.0'), + profile_dir="/tmp/profiles") # nosec w/o profile data + else: + return configure_app(app, version='v1.0') diff --git a/deckhand/utils.py b/deckhand/utils.py index e689c264..e5e30b5a 100644 --- a/deckhand/utils.py +++ b/deckhand/utils.py @@ -25,6 +25,8 @@ from deckhand import errors LOG = logging.getLogger(__name__) +path_cache = dict() + def to_camel_case(s): """Convert string to camel case.""" @@ -71,7 +73,12 @@ def jsonpath_parse(data, jsonpath, match_all=False): elif jsonpath.startswith('.'): jsonpath = '$' + jsonpath - p = jsonpath_ng.parse(jsonpath) + if jsonpath not in path_cache: + p = jsonpath_ng.parse(jsonpath) + path_cache[jsonpath] = p + else: + p = path_cache[jsonpath] + matches = p.find(data) if matches: result = [m.value for m in matches] diff --git a/requirements.txt b/requirements.txt index e4d29906..f0ddf45f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -41,3 +41,6 @@ oslo.utils>=3.35.0 # Apache-2.0 # likely this should be imported from a # container sidecar long-term python-barbicanclient>=4.6.0 # Apache-2.0 + +# To support profiling in non-prod +Werkzeug==0.14.1