From 4e188f9e146017fd04af3d80abbed94c01f9616f Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Tue, 11 Sep 2018 17:15:20 +0200 Subject: [PATCH 01/13] Also make sure to always include parameters - that's needed for correct secrets masking. --- st2api/st2api/controllers/v1/actionexecutions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/st2api/st2api/controllers/v1/actionexecutions.py b/st2api/st2api/controllers/v1/actionexecutions.py index 8ba7575a44..7107735871 100644 --- a/st2api/st2api/controllers/v1/actionexecutions.py +++ b/st2api/st2api/controllers/v1/actionexecutions.py @@ -86,7 +86,8 @@ class ActionExecutionsControllerMixin(BaseRestControllerMixin): # parameters mandatory_include_fields_retrieve = [ 'action.parameters', - 'runner.runner_parameters' + 'runner.runner_parameters', + 'parameters' ] # A list of attributes which can be specified using ?exclude_attributes filter From 6804540408248992520a765a0fc1c93197f79187 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Tue, 11 Sep 2018 17:16:10 +0200 Subject: [PATCH 02/13] result.parameters can be empty, make sure we account for that scenario. --- st2common/st2common/models/db/execution.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st2common/st2common/models/db/execution.py b/st2common/st2common/models/db/execution.py index 9488a10611..9bd5587648 100644 --- a/st2common/st2common/models/db/execution.py +++ b/st2common/st2common/models/db/execution.py @@ -110,7 +110,7 @@ def mask_secrets(self, value): parameters.update(value.get('runner', {}).get('runner_parameters', {})) secret_parameters = get_secret_parameters(parameters=parameters) - result['parameters'] = mask_secret_parameters(parameters=result['parameters'], + result['parameters'] = mask_secret_parameters(parameters=result.get('parameters', {}), secret_parameters=secret_parameters) if 'parameters' in liveaction: From b4e66030838b0bbf804e3d6add4a3b152d0bd0ec Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Tue, 11 Sep 2018 17:26:46 +0200 Subject: [PATCH 03/13] Remove log statement which is not needed and causes massive performance overhead if there are many actions in the db. --- st2api/st2api/controllers/v1/action_views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/st2api/st2api/controllers/v1/action_views.py b/st2api/st2api/controllers/v1/action_views.py index 36b2025c11..700067b686 100644 --- a/st2api/st2api/controllers/v1/action_views.py +++ b/st2api/st2api/controllers/v1/action_views.py @@ -88,7 +88,6 @@ def _get_one(action_id, requester_user): GET /actions/views/parameters/1 """ action_db = LookupUtils._get_action_by_id(action_id) - LOG.info('Found action: %s, runner: %s', action_db, action_db.runner_type['name']) permission_type = PermissionType.ACTION_VIEW rbac_utils.assert_user_has_resource_db_permission(user_db=requester_user, From 746adf70c0d0d70fea44b0855d0784e4179db244 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Tue, 11 Sep 2018 17:34:06 +0200 Subject: [PATCH 04/13] Add todo annotation. --- st2api/st2api/controllers/v1/action_views.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/st2api/st2api/controllers/v1/action_views.py b/st2api/st2api/controllers/v1/action_views.py index 700067b686..7550d9ca36 100644 --- a/st2api/st2api/controllers/v1/action_views.py +++ b/st2api/st2api/controllers/v1/action_views.py @@ -143,6 +143,9 @@ def get_all(self, exclude_attributes=None, include_attributes=None, sort=None, o result = [] for item in resp.json: action_api = ActionAPI(**item) + # TODO: This is extreme inefficient and results in N * 2 queries where N is number of + # actions + # Refactor it to perform 2 queries instead result.append(self._transform_action_api(action_api=action_api, requester_user=requester_user)) resp.json = result From bcb63f58cb9530c5ce4b73203992d19e4f8cb222 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Tue, 11 Sep 2018 18:06:21 +0200 Subject: [PATCH 05/13] Fix / improve performance of /v1/actions/overview API endpoint. We now make 2 instead of N * 2 queries which results in a massive speed up. --- st2api/st2api/controllers/v1/action_views.py | 41 ++++++++++++++++--- .../models/utils/action_param_utils.py | 13 ++++-- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/st2api/st2api/controllers/v1/action_views.py b/st2api/st2api/controllers/v1/action_views.py index 7550d9ca36..6eeb81411f 100644 --- a/st2api/st2api/controllers/v1/action_views.py +++ b/st2api/st2api/controllers/v1/action_views.py @@ -110,6 +110,13 @@ class OverviewController(resource.ContentPackResourceController): 'sort': ['pack', 'name'] } + mandatory_include_fields_retrieve = [ + 'pack', + 'name', + 'parameters', + 'runner_type' + ] + def get_one(self, ref_or_id, requester_user): """ List action by id. @@ -140,14 +147,38 @@ def get_all(self, exclude_attributes=None, include_attributes=None, sort=None, o limit=limit, raw_filters=raw_filters, requester_user=requester_user) + runner_type_names = set([]) + action_ids = [] + result = [] for item in resp.json: action_api = ActionAPI(**item) - # TODO: This is extreme inefficient and results in N * 2 queries where N is number of - # actions - # Refactor it to perform 2 queries instead - result.append(self._transform_action_api(action_api=action_api, - requester_user=requester_user)) + result.append(action_api) + + runner_type_names.add(action_api.runner_type) + action_ids.append(action_api.id) + + # Add combined runner and action parameters to the compound result object + # NOTE: This approach results in 2 additional queries while previous one resulted in + # N * 2 additional queries + + # 1. Retrieve all the respective runner objects - we only need parameters + runner_type_dbs = RunnerType.query(name__in=runner_type_names, + only_fields=['name', 'runner_parameters']) + runner_type_dbs = dict([(runner_db.name, runner_db) for runner_db in runner_type_dbs]) + + # 2. Retrieve all the respective action objects - we only need parameters + action_dbs = Action.query(id__in=action_ids, only_fields=['ref', 'parameters']) + action_dbs = dict([(action_db.id, action_db) for action_db in action_dbs]) + + for action_api in result: + action_db = action_dbs.get(action_api.id, None) + runner_db = runner_type_dbs.get(action_api.runner_type, None) + all_params = action_param_utils.get_params_view(action_db=action_db, + runner_db=runner_db, + merged_only=True) + action_api.parameters = all_params + resp.json = result return resp diff --git a/st2common/st2common/models/utils/action_param_utils.py b/st2common/st2common/models/utils/action_param_utils.py index c93a30e5ae..ac0cd8a985 100644 --- a/st2common/st2common/models/utils/action_param_utils.py +++ b/st2common/st2common/models/utils/action_param_utils.py @@ -49,10 +49,17 @@ def _merge_param_meta_values(action_meta=None, runner_meta=None): def get_params_view(action_db=None, runner_db=None, merged_only=False): - runner_params = copy.deepcopy(runner_db.runner_parameters) if runner_db else {} - action_params = copy.deepcopy(action_db.parameters) if action_db else {} + if runner_db: + runner_params = copy.deepcopy(getattr(runner_db, 'runner_parameters', {})) + else: + runner_params = {} - parameters = set(runner_params.keys()).union(set(action_params.keys())) + if action_db: + action_params = copy.deepcopy(getattr(action_db, 'parameters', {})) + else: + action_params = {} + + parameters = set(runner_params or {}.keys()).union(set(action_params or {}.keys())) merged_params = {} for param in parameters: From fcb60efae0f7605a58c1f5ff31d33287e222155d Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Tue, 11 Sep 2018 18:09:30 +0200 Subject: [PATCH 06/13] Don't log responses for API endpoint which could contain a lot of data. --- st2common/st2common/openapi.yaml | 2 ++ st2common/st2common/openapi.yaml.j2 | 2 ++ 2 files changed, 4 insertions(+) diff --git a/st2common/st2common/openapi.yaml b/st2common/st2common/openapi.yaml index e59616f727..cc890a4566 100644 --- a/st2common/st2common/openapi.yaml +++ b/st2common/st2common/openapi.yaml @@ -250,6 +250,7 @@ paths: operationId: st2api.controllers.v1.actions:actions_controller.get_all x-permissions: action_list description: Returns a list of all actions. + x-log-result: false parameters: - name: exclude_attributes in: query @@ -460,6 +461,7 @@ paths: operationId: st2api.controllers.v1.action_views:overview_controller.get_all x-permissions: action_list description: Returns a list of all the actions with runner parameters included. + x-log-result: false parameters: - name: exclude_attributes in: query diff --git a/st2common/st2common/openapi.yaml.j2 b/st2common/st2common/openapi.yaml.j2 index b092f64684..8542657315 100644 --- a/st2common/st2common/openapi.yaml.j2 +++ b/st2common/st2common/openapi.yaml.j2 @@ -246,6 +246,7 @@ paths: operationId: st2api.controllers.v1.actions:actions_controller.get_all x-permissions: {{ PERMISSION_TYPE.ACTION_LIST }} description: Returns a list of all actions. + x-log-result: false parameters: - name: exclude_attributes in: query @@ -456,6 +457,7 @@ paths: operationId: st2api.controllers.v1.action_views:overview_controller.get_all x-permissions: {{ PERMISSION_TYPE.ACTION_LIST }} description: Returns a list of all the actions with runner parameters included. + x-log-result: false parameters: - name: exclude_attributes in: query From 7d070d81c6f29d7b6952ba1c6f7c4cb06b9ab6a1 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Tue, 11 Sep 2018 18:28:01 +0200 Subject: [PATCH 07/13] We already have access to action_dbs, no need to retrieve it twice. --- st2api/st2api/controllers/v1/action_views.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/st2api/st2api/controllers/v1/action_views.py b/st2api/st2api/controllers/v1/action_views.py index 6eeb81411f..8918421646 100644 --- a/st2api/st2api/controllers/v1/action_views.py +++ b/st2api/st2api/controllers/v1/action_views.py @@ -156,7 +156,7 @@ def get_all(self, exclude_attributes=None, include_attributes=None, sort=None, o result.append(action_api) runner_type_names.add(action_api.runner_type) - action_ids.append(action_api.id) + action_ids.append(str(action_api.id)) # Add combined runner and action parameters to the compound result object # NOTE: This approach results in 2 additional queries while previous one resulted in @@ -168,8 +168,7 @@ def get_all(self, exclude_attributes=None, include_attributes=None, sort=None, o runner_type_dbs = dict([(runner_db.name, runner_db) for runner_db in runner_type_dbs]) # 2. Retrieve all the respective action objects - we only need parameters - action_dbs = Action.query(id__in=action_ids, only_fields=['ref', 'parameters']) - action_dbs = dict([(action_db.id, action_db) for action_db in action_dbs]) + action_dbs = dict([(action_db.id, action_db) for action_db in result]) for action_api in result: action_db = action_dbs.get(action_api.id, None) From 9175ca9e3341ac2558e8a12bed6058a4ba37d46c Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Tue, 11 Sep 2018 18:32:36 +0200 Subject: [PATCH 08/13] Use fast_deepcopy. --- st2common/st2common/models/utils/action_param_utils.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/st2common/st2common/models/utils/action_param_utils.py b/st2common/st2common/models/utils/action_param_utils.py index ac0cd8a985..c12859b49e 100644 --- a/st2common/st2common/models/utils/action_param_utils.py +++ b/st2common/st2common/models/utils/action_param_utils.py @@ -14,12 +14,14 @@ # limitations under the License. from __future__ import absolute_import + import copy import six from st2common import log as logging from st2common.util import action_db as action_db_util from st2common.util.casts import get_cast +from st2common.util.ujson import fast_deepcopy LOG = logging.getLogger(__name__) @@ -50,16 +52,16 @@ def _merge_param_meta_values(action_meta=None, runner_meta=None): def get_params_view(action_db=None, runner_db=None, merged_only=False): if runner_db: - runner_params = copy.deepcopy(getattr(runner_db, 'runner_parameters', {})) + runner_params = fast_deepcopy(getattr(runner_db, 'runner_parameters', {})) or {} else: runner_params = {} if action_db: - action_params = copy.deepcopy(getattr(action_db, 'parameters', {})) + action_params = fast_deepcopy(getattr(action_db, 'parameters', {})) or {} else: action_params = {} - parameters = set(runner_params or {}.keys()).union(set(action_params or {}.keys())) + parameters = set(runner_params.keys()).union(set(action_params.keys())) merged_params = {} for param in parameters: From b9c65259e1086bea334960fb3fbc6ec9a12a691d Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Tue, 11 Sep 2018 19:23:07 +0200 Subject: [PATCH 09/13] Add changelog entry. --- CHANGELOG.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c77b920a75..ef38ae72fc 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -112,6 +112,7 @@ Changed * Improve ``st2 execution tail`` CLI command so it also supports Orquesta workflows and arbitrarily nested workflows. Also fix the command so it doesn't include data from other unrelated running executions. (improvement) #4328 +* Improve performance of the ``GET /v1/actions/views/overview`` API endpoint. (improvement) #4337 Fixed ~~~~~ From aa4e4adab5300a8d23536d40758abe820eaa3cce Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Thu, 13 Sep 2018 10:59:00 +0200 Subject: [PATCH 10/13] Fix lint. --- st2common/st2common/models/utils/action_param_utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/st2common/st2common/models/utils/action_param_utils.py b/st2common/st2common/models/utils/action_param_utils.py index c12859b49e..c0a8ab3a98 100644 --- a/st2common/st2common/models/utils/action_param_utils.py +++ b/st2common/st2common/models/utils/action_param_utils.py @@ -15,7 +15,6 @@ from __future__ import absolute_import -import copy import six from st2common import log as logging From f544d566a1f83998df19d85e9907fb105413a710 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Thu, 13 Sep 2018 11:11:37 +0200 Subject: [PATCH 11/13] Use fast_deepcopy in more places instead of copy.deepcopy(). --- .../action_chain_runner/action_chain_runner.py | 4 ++-- .../orquesta_runner/orquesta_runner/orquesta_runner.py | 5 ++--- st2common/st2common/util/secrets.py | 6 +++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/contrib/runners/action_chain_runner/action_chain_runner/action_chain_runner.py b/contrib/runners/action_chain_runner/action_chain_runner/action_chain_runner.py index 2d68224401..28151a18c3 100644 --- a/contrib/runners/action_chain_runner/action_chain_runner/action_chain_runner.py +++ b/contrib/runners/action_chain_runner/action_chain_runner/action_chain_runner.py @@ -14,7 +14,6 @@ # limitations under the License. from __future__ import absolute_import -import copy import eventlet import traceback import uuid @@ -46,6 +45,7 @@ from st2common.util import jinja as jinja_utils from st2common.util import param as param_utils from st2common.util.config_loader import get_config +from st2common.util.ujson import fast_deepcopy __all__ = [ 'ActionChainRunner', @@ -87,7 +87,7 @@ def init_vars(self, action_parameters): action_parameters=action_parameters) def restore_vars(self, ctx_vars): - self.vars.update(copy.deepcopy(ctx_vars)) + self.vars.update(fast_deepcopy(ctx_vars)) def validate(self): """ diff --git a/contrib/runners/orquesta_runner/orquesta_runner/orquesta_runner.py b/contrib/runners/orquesta_runner/orquesta_runner/orquesta_runner.py index e03729ced0..e0de955dd1 100644 --- a/contrib/runners/orquesta_runner/orquesta_runner/orquesta_runner.py +++ b/contrib/runners/orquesta_runner/orquesta_runner/orquesta_runner.py @@ -15,7 +15,6 @@ from __future__ import absolute_import -import copy import uuid from oslo_config import cfg @@ -31,7 +30,7 @@ from st2common.services import action as ac_svc from st2common.services import workflows as wf_svc from st2common.util import api as api_util - +from st2common.util import ujson __all__ = [ 'OrquestaRunner', @@ -51,7 +50,7 @@ def get_workflow_definition(entry_point): return def_file.read() def _construct_context(self, wf_ex): - ctx = copy.deepcopy(self.context) + ctx = ujson.fast_deepcopy(self.context) ctx['workflow_execution'] = str(wf_ex.id) return ctx diff --git a/st2common/st2common/util/secrets.py b/st2common/st2common/util/secrets.py index 57d8a0b08f..a0db523e80 100644 --- a/st2common/st2common/util/secrets.py +++ b/st2common/st2common/util/secrets.py @@ -18,10 +18,10 @@ """ from __future__ import absolute_import -import copy import six +from st2common.util.ujson import fast_deepcopy from st2common.constants.secrets import MASKED_ATTRIBUTE_VALUE @@ -170,7 +170,7 @@ def mask_secret_parameters(parameters, secret_parameters, result=None): # all other recursive calls pass back referneces to this result object # so we can reuse it, saving memory and CPU cycles if result is None: - result = copy.deepcopy(parameters) + result = fast_deepcopy(parameters) # iterate over the secret parameters for secret_param, secret_sub_params in iterator: @@ -202,7 +202,7 @@ def mask_inquiry_response(response, schema): :param schema: Inquiry response schema :type schema: ``dict`` """ - result = copy.deepcopy(response) + result = fast_deepcopy(response) for prop_name, prop_attrs in schema['properties'].items(): if prop_attrs.get('secret') is True: From f32d7277a91e13c7c4800663e7c67b24a077d3f8 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Thu, 13 Sep 2018 14:48:04 +0200 Subject: [PATCH 12/13] Don't submit request and response metrics for paths / endpoints such as /v1/executions/{id}, etc. Submitting metrics for those unique endpoints would result in a lot of unique metrics which is an anti-pattern and results on unnecessary high metrics server load. --- st2api/st2api/app.py | 4 +- st2auth/st2auth/app.py | 4 +- .../st2common/middleware/instrumentation.py | 48 ++++++++++++++++--- st2common/st2common/openapi.yaml | 7 +++ st2common/st2common/openapi.yaml.j2 | 7 +++ st2stream/st2stream/app.py | 4 +- 6 files changed, 61 insertions(+), 13 deletions(-) diff --git a/st2api/st2api/app.py b/st2api/st2api/app.py index 4526e0212d..27c9a815ff 100644 --- a/st2api/st2api/app.py +++ b/st2api/st2api/app.py @@ -77,8 +77,8 @@ def setup_app(config={}): app = ErrorHandlingMiddleware(app) app = CorsMiddleware(app) app = LoggingMiddleware(app, router) - app = ResponseInstrumentationMiddleware(app, service_name='api') + app = ResponseInstrumentationMiddleware(app, router, service_name='api') app = RequestIDMiddleware(app) - app = RequestInstrumentationMiddleware(app, service_name='api') + app = RequestInstrumentationMiddleware(app, router, service_name='api') return app diff --git a/st2auth/st2auth/app.py b/st2auth/st2auth/app.py index 2bbf725ab5..0dd154bb11 100644 --- a/st2auth/st2auth/app.py +++ b/st2auth/st2auth/app.py @@ -71,8 +71,8 @@ def setup_app(config={}): app = ErrorHandlingMiddleware(app) app = CorsMiddleware(app) app = LoggingMiddleware(app, router) - app = ResponseInstrumentationMiddleware(app, service_name='auth') + app = ResponseInstrumentationMiddleware(app, router, service_name='auth') app = RequestIDMiddleware(app) - app = RequestInstrumentationMiddleware(app, service_name='auth') + app = RequestInstrumentationMiddleware(app, router, service_name='auth') return app diff --git a/st2common/st2common/middleware/instrumentation.py b/st2common/st2common/middleware/instrumentation.py index bfbe6b3075..bcf6f6fc39 100644 --- a/st2common/st2common/middleware/instrumentation.py +++ b/st2common/st2common/middleware/instrumentation.py @@ -13,16 +13,20 @@ # See the License for the specific language governing permissions and # limitations under the License. -__all__ = [ - 'RequestInstrumentationMiddleware', - 'ResponseInstrumentationMiddleware' -] - from webob import Request +from st2common import log as logging from st2common.metrics.base import CounterWithTimer from st2common.metrics.base import get_driver from st2common.util.date import get_datetime_utc_now +from st2common.router import NotFoundException + +__all__ = [ + 'RequestInstrumentationMiddleware', + 'ResponseInstrumentationMiddleware' +] + +LOG = logging.getLogger(__name__) class RequestInstrumentationMiddleware(object): @@ -30,17 +34,31 @@ class RequestInstrumentationMiddleware(object): Instrumentation middleware which records various request related metrics. """ - def __init__(self, app, service_name): + def __init__(self, app, router, service_name): """ :param service_name: Service name (e.g. api, stream, auth). :type service_name: ``str`` """ self.app = app + self.router = router self._service_name = service_name def __call__(self, environ, start_response): request = Request(environ) + try: + endpoint, _ = self.router.match(request) + except NotFoundException: + endpoint = {} + + # NOTE: We don't track per request and response metrics for /v1/executions/ and some + # other endpoints because this would result in a lot of unique metrics which is an + # anti-pattern and causes unnecessary load on the metrics server. + submit_metrics = endpoint.get('x-submit-metrics', True) + if not submit_metrics: + LOG.debug('Not submitting request metrics for path: %s' % (request.path)) + return self.app(environ, start_response) + metrics_driver = get_driver() key = '%s.request.total' % (self._service_name) @@ -99,12 +117,13 @@ class ResponseInstrumentationMiddleware(object): Instrumentation middleware which records various response related metrics. """ - def __init__(self, app, service_name): + def __init__(self, app, router, service_name): """ :param service_name: Service name (e.g. api, stream, auth). :type service_name: ``str`` """ self.app = app + self.router = router self._service_name = service_name def __call__(self, environ, start_response): @@ -118,4 +137,19 @@ def custom_start_response(status, headers, exc_info=None): return start_response(status, headers, exc_info) + request = Request(environ) + + try: + endpoint, _ = self.router.match(request) + except NotFoundException: + endpoint = {} + + # NOTE: We don't track per request and response metrics for /v1/executions/ and some + # other endpoints because this would result in a lot of unique metrics which is an + # anti-pattern and causes unnecessary load on the metrics server. + submit_metrics = endpoint.get('x-submit-metrics', True) + if not submit_metrics: + LOG.debug('Not submitting response metrics for path: %s' % (request.path)) + return self.app(environ, start_response) + return self.app(environ, custom_start_response) diff --git a/st2common/st2common/openapi.yaml b/st2common/st2common/openapi.yaml index cc890a4566..829b0286ca 100644 --- a/st2common/st2common/openapi.yaml +++ b/st2common/st2common/openapi.yaml @@ -1068,6 +1068,7 @@ paths: get: operationId: st2api.controllers.v1.actionexecutions:action_executions_controller.get_one x-log-result: false + x-submit-metrics: false description: | Get one execution. parameters: @@ -1164,6 +1165,7 @@ paths: get: operationId: st2api.controllers.v1.actionexecutions:action_execution_output_controller.get_one x-log-result: false + x-submit-metrics: false description: | Retrieve execution output. parameters: @@ -1197,6 +1199,7 @@ paths: post: operationId: st2api.controllers.v1.actionexecutions:action_execution_rerun_controller.post x-log-result: false + x-submit-metrics: false description: | Create a new execution. parameters: @@ -1252,6 +1255,7 @@ paths: get: operationId: st2api.controllers.v1.actionexecutions:action_execution_attribute_controller.get x-log-result: false + x-submit-metrics: false description: | Get one execution. parameters: @@ -1286,6 +1290,7 @@ paths: get: operationId: st2api.controllers.v1.actionexecutions:action_execution_children_controller.get_one x-log-result: false + x-submit-metrics: false description: | Get one execution. parameters: @@ -1308,6 +1313,7 @@ paths: in: context x-as: requester_user description: User performing the operation. + x-submit-metrics: false responses: '200': description: Execution attribute requested @@ -1902,6 +1908,7 @@ paths: x-requirements: file_path: .* x-log-result: false + x-submit-metrics: false description: Get information about an installed pack. parameters: - name: ref_or_id diff --git a/st2common/st2common/openapi.yaml.j2 b/st2common/st2common/openapi.yaml.j2 index 8542657315..7ee95e7895 100644 --- a/st2common/st2common/openapi.yaml.j2 +++ b/st2common/st2common/openapi.yaml.j2 @@ -1064,6 +1064,7 @@ paths: get: operationId: st2api.controllers.v1.actionexecutions:action_executions_controller.get_one x-log-result: false + x-submit-metrics: false description: | Get one execution. parameters: @@ -1160,6 +1161,7 @@ paths: get: operationId: st2api.controllers.v1.actionexecutions:action_execution_output_controller.get_one x-log-result: false + x-submit-metrics: false description: | Retrieve execution output. parameters: @@ -1193,6 +1195,7 @@ paths: post: operationId: st2api.controllers.v1.actionexecutions:action_execution_rerun_controller.post x-log-result: false + x-submit-metrics: false description: | Create a new execution. parameters: @@ -1248,6 +1251,7 @@ paths: get: operationId: st2api.controllers.v1.actionexecutions:action_execution_attribute_controller.get x-log-result: false + x-submit-metrics: false description: | Get one execution. parameters: @@ -1282,6 +1286,7 @@ paths: get: operationId: st2api.controllers.v1.actionexecutions:action_execution_children_controller.get_one x-log-result: false + x-submit-metrics: false description: | Get one execution. parameters: @@ -1304,6 +1309,7 @@ paths: in: context x-as: requester_user description: User performing the operation. + x-submit-metrics: false responses: '200': description: Execution attribute requested @@ -1898,6 +1904,7 @@ paths: x-requirements: file_path: .* x-log-result: false + x-submit-metrics: false description: Get information about an installed pack. parameters: - name: ref_or_id diff --git a/st2stream/st2stream/app.py b/st2stream/st2stream/app.py index 5b106ca90d..588aaf026a 100644 --- a/st2stream/st2stream/app.py +++ b/st2stream/st2stream/app.py @@ -79,8 +79,8 @@ def setup_app(config={}): app = ErrorHandlingMiddleware(app) app = CorsMiddleware(app) app = LoggingMiddleware(app, router) - app = ResponseInstrumentationMiddleware(app, service_name='stream') + app = ResponseInstrumentationMiddleware(app, router, service_name='stream') app = RequestIDMiddleware(app) - app = RequestInstrumentationMiddleware(app, service_name='stream') + app = RequestInstrumentationMiddleware(app, router, service_name='stream') return app From 20077401ce818cf8be5cfac6b98bee25a5a19d31 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Thu, 13 Sep 2018 14:57:11 +0200 Subject: [PATCH 13/13] We can still submit response metrics for unique endpoints since those don't result in unique metric names and don't cause any load issues. --- st2common/st2common/middleware/instrumentation.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/st2common/st2common/middleware/instrumentation.py b/st2common/st2common/middleware/instrumentation.py index bcf6f6fc39..ea03b72df1 100644 --- a/st2common/st2common/middleware/instrumentation.py +++ b/st2common/st2common/middleware/instrumentation.py @@ -137,19 +137,4 @@ def custom_start_response(status, headers, exc_info=None): return start_response(status, headers, exc_info) - request = Request(environ) - - try: - endpoint, _ = self.router.match(request) - except NotFoundException: - endpoint = {} - - # NOTE: We don't track per request and response metrics for /v1/executions/ and some - # other endpoints because this would result in a lot of unique metrics which is an - # anti-pattern and causes unnecessary load on the metrics server. - submit_metrics = endpoint.get('x-submit-metrics', True) - if not submit_metrics: - LOG.debug('Not submitting response metrics for path: %s' % (request.path)) - return self.app(environ, start_response) - return self.app(environ, custom_start_response)