Fix missing X-OpenStack-Request-ID header

Request ID is essential in operating OpenStack services, especially
when troubleshooting some API problems. It allows us to find out
the log lines actually related to a specific request.

However watcher api hasn't returned it properly, so operators had no
way to determine the exact ID they should search.

Add RequestID middleware to return the id in X-OpenStack-Request-Id
header, which is globally used.

Closes-Bug: #2122350
Change-Id: Ie4a8307e8e7e981cedbeaf5fe731dbd47a50bade
Signed-off-by: Takashi Kajinami <kajinamit@oss.nttdata.com>
This commit is contained in:
Takashi Kajinami
2025-09-09 02:04:40 +09:00
parent b1aad46209
commit a562880b1c
4 changed files with 23 additions and 1 deletions

View File

@@ -0,0 +1,5 @@
---
fixes:
- |
Now request id is returned by Watcher API in the `X-OpenStack-Request-ID`
response header.

View File

@@ -19,6 +19,7 @@ oslo.db>=4.44.0 # Apache-2.0
oslo.i18n>=3.20.0 # Apache-2.0
oslo.log>=3.37.0 # Apache-2.0
oslo.messaging>=14.1.0 # Apache-2.0
oslo.middleware>=3.31.0 # Apache-2.0
oslo.policy>=4.5.0 # Apache-2.0
oslo.reports>=1.27.0 # Apache-2.0
oslo.serialization>=2.25.0 # Apache-2.0

View File

@@ -17,6 +17,7 @@
# under the License.
from oslo_middleware import request_id
import pecan
from watcher.api import acl
@@ -42,13 +43,22 @@ def setup_app(config=None):
app_conf.pop('root'),
logging=getattr(config, 'logging', {}),
debug=CONF.debug,
wrap_app=parsable_error.ParsableErrorMiddleware,
wrap_app=_wrap_app,
**app_conf
)
return acl.install(app, CONF, config.app.acl_public_routes)
def _wrap_app(app):
"""Wraps wsgi app with additional middlewares."""
app = parsable_error.ParsableErrorMiddleware(app)
app = request_id.RequestId(app)
return app
class VersionSelectorApplication(object):
def __init__(self):
pc = get_pecan_config()

View File

@@ -24,6 +24,12 @@ class TestRoot(base.FunctionalTest):
# Check fields are not empty
[self.assertNotIn(f, ['', []]) for f in data.keys()]
# NOTE(tkajinam): Request ID should be present in any request so we verify
# it only at the root path.
def test_request_id(self):
resp = self.get_json('/', path_prefix='', return_json=False)
self.assertIn('X-OpenStack-Request-Id', resp.headers)
class TestV1Root(base.FunctionalTest):