We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
The api key in the st2api log is not obfuscated
##### SUMMARY
The user found in clean API key in query request (for the load balancer health check)
```GET /api/v1/?st2-api-key=foo HTTP/1.1```

##### ISSUE TYPE
 - Bug Report
 
##### STACKSTORM VERSION
st2 2.10.3, on Python 2.7.12

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `st2common/st2common/middleware/logging.py`
Content:
```
1 # Licensed to the StackStorm, Inc ('StackStorm') under one or more
2 # contributor license agreements.  See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License.  You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 from __future__ import absolute_import
17 import time
18 import types
19 import itertools
20 
21 from st2common.constants.api import REQUEST_ID_HEADER
22 from st2common import log as logging
23 from st2common.router import Request, NotFoundException
24 
25 LOG = logging.getLogger(__name__)
26 
27 try:
28     clock = time.perf_counter
29 except AttributeError:
30     clock = time.time
31 
32 
33 class LoggingMiddleware(object):
34     """
35     Logs all incoming requests and outgoing responses
36     """
37 
38     def __init__(self, app, router):
39         self.app = app
40         self.router = router
41 
42     def __call__(self, environ, start_response):
43         start_time = clock()
44         status_code = []
45         content_length = []
46 
47         request = Request(environ)
48 
49         # Log the incoming request
50         values = {
51             'method': request.method,
52             'path': request.path,
53             'remote_addr': request.remote_addr,
54             'query': request.GET.dict_of_lists(),
55             'request_id': request.headers.get(REQUEST_ID_HEADER, None)
56         }
57 
58         LOG.info('%(request_id)s - %(method)s %(path)s with query=%(query)s' %
59                  values, extra=values)
60 
61         def custom_start_response(status, headers, exc_info=None):
62             status_code.append(int(status.split(' ')[0]))
63 
64             for name, value in headers:
65                 if name.lower() == 'content-length':
66                     content_length.append(int(value))
67                     break
68 
69             return start_response(status, headers, exc_info)
70 
71         retval = self.app(environ, custom_start_response)
72 
73         try:
74             endpoint, path_vars = self.router.match(request)
75         except NotFoundException:
76             endpoint = {}
77 
78         log_result = endpoint.get('x-log-result', True)
79 
80         if isinstance(retval, (types.GeneratorType, itertools.chain)):
81             # Note: We don't log the result when return value is a generator, because this would
82             # result in calling str() on the generator and as such, exhausting it
83             content_length = [float('inf')]
84             log_result = False
85 
86         # Log the response
87         values = {
88             'method': request.method,
89             'path': request.path,
90             'remote_addr': request.remote_addr,
91             'status': status_code[0],
92             'runtime': float("{0:.3f}".format((clock() - start_time) * 10**3)),
93             'content_length': content_length[0] if content_length else len(b''.join(retval)),
94             'request_id': request.headers.get(REQUEST_ID_HEADER, None)
95         }
96 
97         log_msg = '%(request_id)s - %(status)s %(content_length)s %(runtime)sms' % (values)
98         LOG.info(log_msg, extra=values)
99 
100         if log_result:
101             values['result'] = retval[0]
102             log_msg = ('%(request_id)s - %(status)s %(content_length)s %(runtime)sms\n%(result)s' %
103                       (values))
104             LOG.debug(log_msg, extra=values)
105 
106         return retval
107
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/st2common/st2common/middleware/logging.py b/st2common/st2common/middleware/logging.py
--- a/st2common/st2common/middleware/logging.py
+++ b/st2common/st2common/middleware/logging.py
@@ -14,16 +14,28 @@
 # limitations under the License.
 
 from __future__ import absolute_import
+
 import time
 import types
 import itertools
 
+from oslo_config import cfg
+
 from st2common.constants.api import REQUEST_ID_HEADER
+from st2common.constants.auth import QUERY_PARAM_ATTRIBUTE_NAME
+from st2common.constants.auth import QUERY_PARAM_API_KEY_ATTRIBUTE_NAME
+from st2common.constants.secrets import MASKED_ATTRIBUTE_VALUE
+from st2common.constants.secrets import MASKED_ATTRIBUTES_BLACKLIST
 from st2common import log as logging
 from st2common.router import Request, NotFoundException
 
 LOG = logging.getLogger(__name__)
 
+SECRET_QUERY_PARAMS = [
+    QUERY_PARAM_ATTRIBUTE_NAME,
+    QUERY_PARAM_API_KEY_ATTRIBUTE_NAME
+] + MASKED_ATTRIBUTES_BLACKLIST
+
 try:
     clock = time.perf_counter
 except AttributeError:
@@ -46,12 +58,20 @@
 
         request = Request(environ)
 
+        query_params = request.GET.dict_of_lists()
+
+        # Mask secret / sensitive query params
+        secret_query_params = SECRET_QUERY_PARAMS + cfg.CONF.log.mask_secrets_blacklist
+        for param_name in secret_query_params:
+            if param_name in query_params:
+                query_params[param_name] = MASKED_ATTRIBUTE_VALUE
+
         # Log the incoming request
         values = {
             'method': request.method,
             'path': request.path,
             'remote_addr': request.remote_addr,
-            'query': request.GET.dict_of_lists(),
+            'query': query_params,
             'request_id': request.headers.get(REQUEST_ID_HEADER, None)
         }

{"golden_diff": "diff --git a/st2common/st2common/middleware/logging.py b/st2common/st2common/middleware/logging.py\n--- a/st2common/st2common/middleware/logging.py\n+++ b/st2common/st2common/middleware/logging.py\n@@ -14,16 +14,28 @@\n # limitations under the License.\n \n from __future__ import absolute_import\n+\n import time\n import types\n import itertools\n \n+from oslo_config import cfg\n+\n from st2common.constants.api import REQUEST_ID_HEADER\n+from st2common.constants.auth import QUERY_PARAM_ATTRIBUTE_NAME\n+from st2common.constants.auth import QUERY_PARAM_API_KEY_ATTRIBUTE_NAME\n+from st2common.constants.secrets import MASKED_ATTRIBUTE_VALUE\n+from st2common.constants.secrets import MASKED_ATTRIBUTES_BLACKLIST\n from st2common import log as logging\n from st2common.router import Request, NotFoundException\n \n LOG = logging.getLogger(__name__)\n \n+SECRET_QUERY_PARAMS = [\n+    QUERY_PARAM_ATTRIBUTE_NAME,\n+    QUERY_PARAM_API_KEY_ATTRIBUTE_NAME\n+] + MASKED_ATTRIBUTES_BLACKLIST\n+\n try:\n     clock = time.perf_counter\n except AttributeError:\n@@ -46,12 +58,20 @@\n \n         request = Request(environ)\n \n+        query_params = request.GET.dict_of_lists()\n+\n+        # Mask secret / sensitive query params\n+        secret_query_params = SECRET_QUERY_PARAMS + cfg.CONF.log.mask_secrets_blacklist\n+        for param_name in secret_query_params:\n+            if param_name in query_params:\n+                query_params[param_name] = MASKED_ATTRIBUTE_VALUE\n+\n         # Log the incoming request\n         values = {\n             'method': request.method,\n             'path': request.path,\n             'remote_addr': request.remote_addr,\n-            'query': request.GET.dict_of_lists(),\n+            'query': query_params,\n             'request_id': request.headers.get(REQUEST_ID_HEADER, None)\n         }\n", "issue": "The api key in the st2api log is not obfuscated\n##### SUMMARY\r\nThe user found in clean API key in query request (for the load balancer health check)\r\n```GET /api/v1/?st2-api-key=foo HTTP/1.1```\r\n\r\n##### ISSUE TYPE\r\n - Bug Report\r\n \r\n##### STACKSTORM VERSION\r\nst2 2.10.3, on Python 2.7.12\n", "before_files": [{"content": "# Licensed to the StackStorm, Inc ('StackStorm') under one or more\n# contributor license agreements.  See the NOTICE file distributed with\n# this work for additional information regarding copyright ownership.\n# The ASF licenses this file to You under the Apache License, Version 2.0\n# (the \"License\"); you may not use this file except in compliance with\n# the License.  You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom __future__ import absolute_import\nimport time\nimport types\nimport itertools\n\nfrom st2common.constants.api import REQUEST_ID_HEADER\nfrom st2common import log as logging\nfrom st2common.router import Request, NotFoundException\n\nLOG = logging.getLogger(__name__)\n\ntry:\n    clock = time.perf_counter\nexcept AttributeError:\n    clock = time.time\n\n\nclass LoggingMiddleware(object):\n    \"\"\"\n    Logs all incoming requests and outgoing responses\n    \"\"\"\n\n    def __init__(self, app, router):\n        self.app = app\n        self.router = router\n\n    def __call__(self, environ, start_response):\n        start_time = clock()\n        status_code = []\n        content_length = []\n\n        request = Request(environ)\n\n        # Log the incoming request\n        values = {\n            'method': request.method,\n            'path': request.path,\n            'remote_addr': request.remote_addr,\n            'query': request.GET.dict_of_lists(),\n            'request_id': request.headers.get(REQUEST_ID_HEADER, None)\n        }\n\n        LOG.info('%(request_id)s - %(method)s %(path)s with query=%(query)s' %\n                 values, extra=values)\n\n        def custom_start_response(status, headers, exc_info=None):\n            status_code.append(int(status.split(' ')[0]))\n\n            for name, value in headers:\n                if name.lower() == 'content-length':\n                    content_length.append(int(value))\n                    break\n\n            return start_response(status, headers, exc_info)\n\n        retval = self.app(environ, custom_start_response)\n\n        try:\n            endpoint, path_vars = self.router.match(request)\n        except NotFoundException:\n            endpoint = {}\n\n        log_result = endpoint.get('x-log-result', True)\n\n        if isinstance(retval, (types.GeneratorType, itertools.chain)):\n            # Note: We don't log the result when return value is a generator, because this would\n            # result in calling str() on the generator and as such, exhausting it\n            content_length = [float('inf')]\n            log_result = False\n\n        # Log the response\n        values = {\n            'method': request.method,\n            'path': request.path,\n            'remote_addr': request.remote_addr,\n            'status': status_code[0],\n            'runtime': float(\"{0:.3f}\".format((clock() - start_time) * 10**3)),\n            'content_length': content_length[0] if content_length else len(b''.join(retval)),\n            'request_id': request.headers.get(REQUEST_ID_HEADER, None)\n        }\n\n        log_msg = '%(request_id)s - %(status)s %(content_length)s %(runtime)sms' % (values)\n        LOG.info(log_msg, extra=values)\n\n        if log_result:\n            values['result'] = retval[0]\n            log_msg = ('%(request_id)s - %(status)s %(content_length)s %(runtime)sms\\n%(result)s' %\n                      (values))\n            LOG.debug(log_msg, extra=values)\n\n        return retval\n", "path": "st2common/st2common/middleware/logging.py"}], "after_files": [{"content": "# Licensed to the StackStorm, Inc ('StackStorm') under one or more\n# contributor license agreements.  See the NOTICE file distributed with\n# this work for additional information regarding copyright ownership.\n# The ASF licenses this file to You under the Apache License, Version 2.0\n# (the \"License\"); you may not use this file except in compliance with\n# the License.  You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom __future__ import absolute_import\n\nimport time\nimport types\nimport itertools\n\nfrom oslo_config import cfg\n\nfrom st2common.constants.api import REQUEST_ID_HEADER\nfrom st2common.constants.auth import QUERY_PARAM_ATTRIBUTE_NAME\nfrom st2common.constants.auth import QUERY_PARAM_API_KEY_ATTRIBUTE_NAME\nfrom st2common.constants.secrets import MASKED_ATTRIBUTE_VALUE\nfrom st2common.constants.secrets import MASKED_ATTRIBUTES_BLACKLIST\nfrom st2common import log as logging\nfrom st2common.router import Request, NotFoundException\n\nLOG = logging.getLogger(__name__)\n\nSECRET_QUERY_PARAMS = [\n    QUERY_PARAM_ATTRIBUTE_NAME,\n    QUERY_PARAM_API_KEY_ATTRIBUTE_NAME\n] + MASKED_ATTRIBUTES_BLACKLIST\n\ntry:\n    clock = time.perf_counter\nexcept AttributeError:\n    clock = time.time\n\n\nclass LoggingMiddleware(object):\n    \"\"\"\n    Logs all incoming requests and outgoing responses\n    \"\"\"\n\n    def __init__(self, app, router):\n        self.app = app\n        self.router = router\n\n    def __call__(self, environ, start_response):\n        start_time = clock()\n        status_code = []\n        content_length = []\n\n        request = Request(environ)\n\n        query_params = request.GET.dict_of_lists()\n\n        # Mask secret / sensitive query params\n        secret_query_params = SECRET_QUERY_PARAMS + cfg.CONF.log.mask_secrets_blacklist\n        for param_name in secret_query_params:\n            if param_name in query_params:\n                query_params[param_name] = MASKED_ATTRIBUTE_VALUE\n\n        # Log the incoming request\n        values = {\n            'method': request.method,\n            'path': request.path,\n            'remote_addr': request.remote_addr,\n            'query': query_params,\n            'request_id': request.headers.get(REQUEST_ID_HEADER, None)\n        }\n\n        LOG.info('%(request_id)s - %(method)s %(path)s with query=%(query)s' %\n                 values, extra=values)\n\n        def custom_start_response(status, headers, exc_info=None):\n            status_code.append(int(status.split(' ')[0]))\n\n            for name, value in headers:\n                if name.lower() == 'content-length':\n                    content_length.append(int(value))\n                    break\n\n            return start_response(status, headers, exc_info)\n\n        retval = self.app(environ, custom_start_response)\n\n        try:\n            endpoint, path_vars = self.router.match(request)\n        except NotFoundException:\n            endpoint = {}\n\n        log_result = endpoint.get('x-log-result', True)\n\n        if isinstance(retval, (types.GeneratorType, itertools.chain)):\n            # Note: We don't log the result when return value is a generator, because this would\n            # result in calling str() on the generator and as such, exhausting it\n            content_length = [float('inf')]\n            log_result = False\n\n        # Log the response\n        values = {\n            'method': request.method,\n            'path': request.path,\n            'remote_addr': request.remote_addr,\n            'status': status_code[0],\n            'runtime': float(\"{0:.3f}\".format((clock() - start_time) * 10**3)),\n            'content_length': content_length[0] if content_length else len(b''.join(retval)),\n            'request_id': request.headers.get(REQUEST_ID_HEADER, None)\n        }\n\n        log_msg = '%(request_id)s - %(status)s %(content_length)s %(runtime)sms' % (values)\n        LOG.info(log_msg, extra=values)\n\n        if log_result:\n            values['result'] = retval[0]\n            log_msg = ('%(request_id)s - %(status)s %(content_length)s %(runtime)sms\\n%(result)s' %\n                      (values))\n            LOG.debug(log_msg, extra=values)\n\n        return retval\n", "path": "st2common/st2common/middleware/logging.py"}]}