swift 2.23.3__py3-none-any.whl → 2.35.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- swift/__init__.py +29 -50
- swift/account/auditor.py +21 -118
- swift/account/backend.py +33 -28
- swift/account/reaper.py +37 -28
- swift/account/replicator.py +22 -0
- swift/account/server.py +60 -26
- swift/account/utils.py +28 -11
- swift-2.23.3.data/scripts/swift-account-audit → swift/cli/account_audit.py +23 -13
- swift-2.23.3.data/scripts/swift-config → swift/cli/config.py +2 -2
- swift/cli/container_deleter.py +5 -11
- swift-2.23.3.data/scripts/swift-dispersion-populate → swift/cli/dispersion_populate.py +8 -7
- swift/cli/dispersion_report.py +10 -9
- swift-2.23.3.data/scripts/swift-drive-audit → swift/cli/drive_audit.py +63 -21
- swift/cli/form_signature.py +3 -7
- swift-2.23.3.data/scripts/swift-get-nodes → swift/cli/get_nodes.py +8 -2
- swift/cli/info.py +154 -14
- swift/cli/manage_shard_ranges.py +705 -37
- swift-2.23.3.data/scripts/swift-oldies → swift/cli/oldies.py +25 -14
- swift-2.23.3.data/scripts/swift-orphans → swift/cli/orphans.py +7 -3
- swift/cli/recon.py +196 -67
- swift-2.23.3.data/scripts/swift-recon-cron → swift/cli/recon_cron.py +17 -20
- swift-2.23.3.data/scripts/swift-reconciler-enqueue → swift/cli/reconciler_enqueue.py +2 -3
- swift/cli/relinker.py +807 -126
- swift/cli/reload.py +135 -0
- swift/cli/ringbuilder.py +217 -20
- swift/cli/ringcomposer.py +0 -1
- swift/cli/shard-info.py +4 -3
- swift/common/base_storage_server.py +9 -20
- swift/common/bufferedhttp.py +48 -74
- swift/common/constraints.py +20 -15
- swift/common/container_sync_realms.py +9 -11
- swift/common/daemon.py +25 -8
- swift/common/db.py +195 -128
- swift/common/db_auditor.py +168 -0
- swift/common/db_replicator.py +95 -55
- swift/common/digest.py +141 -0
- swift/common/direct_client.py +144 -33
- swift/common/error_limiter.py +93 -0
- swift/common/exceptions.py +25 -1
- swift/common/header_key_dict.py +2 -9
- swift/common/http_protocol.py +373 -0
- swift/common/internal_client.py +129 -59
- swift/common/linkat.py +3 -4
- swift/common/manager.py +284 -67
- swift/common/memcached.py +390 -145
- swift/common/middleware/__init__.py +4 -0
- swift/common/middleware/account_quotas.py +211 -46
- swift/common/middleware/acl.py +3 -8
- swift/common/middleware/backend_ratelimit.py +230 -0
- swift/common/middleware/bulk.py +22 -34
- swift/common/middleware/catch_errors.py +1 -3
- swift/common/middleware/cname_lookup.py +6 -11
- swift/common/middleware/container_quotas.py +1 -1
- swift/common/middleware/container_sync.py +39 -17
- swift/common/middleware/copy.py +12 -0
- swift/common/middleware/crossdomain.py +22 -9
- swift/common/middleware/crypto/__init__.py +2 -1
- swift/common/middleware/crypto/crypto_utils.py +11 -15
- swift/common/middleware/crypto/decrypter.py +28 -11
- swift/common/middleware/crypto/encrypter.py +12 -17
- swift/common/middleware/crypto/keymaster.py +8 -15
- swift/common/middleware/crypto/kms_keymaster.py +2 -1
- swift/common/middleware/dlo.py +15 -11
- swift/common/middleware/domain_remap.py +5 -4
- swift/common/middleware/etag_quoter.py +128 -0
- swift/common/middleware/formpost.py +73 -70
- swift/common/middleware/gatekeeper.py +8 -1
- swift/common/middleware/keystoneauth.py +33 -3
- swift/common/middleware/list_endpoints.py +4 -4
- swift/common/middleware/listing_formats.py +85 -49
- swift/common/middleware/memcache.py +4 -95
- swift/common/middleware/name_check.py +3 -2
- swift/common/middleware/proxy_logging.py +160 -92
- swift/common/middleware/ratelimit.py +17 -10
- swift/common/middleware/read_only.py +6 -4
- swift/common/middleware/recon.py +59 -22
- swift/common/middleware/s3api/acl_handlers.py +25 -3
- swift/common/middleware/s3api/acl_utils.py +6 -1
- swift/common/middleware/s3api/controllers/__init__.py +6 -0
- swift/common/middleware/s3api/controllers/acl.py +3 -2
- swift/common/middleware/s3api/controllers/bucket.py +242 -137
- swift/common/middleware/s3api/controllers/logging.py +2 -2
- swift/common/middleware/s3api/controllers/multi_delete.py +43 -20
- swift/common/middleware/s3api/controllers/multi_upload.py +219 -133
- swift/common/middleware/s3api/controllers/obj.py +112 -8
- swift/common/middleware/s3api/controllers/object_lock.py +44 -0
- swift/common/middleware/s3api/controllers/s3_acl.py +2 -2
- swift/common/middleware/s3api/controllers/tagging.py +57 -0
- swift/common/middleware/s3api/controllers/versioning.py +36 -7
- swift/common/middleware/s3api/etree.py +22 -9
- swift/common/middleware/s3api/exception.py +0 -4
- swift/common/middleware/s3api/s3api.py +113 -41
- swift/common/middleware/s3api/s3request.py +384 -218
- swift/common/middleware/s3api/s3response.py +126 -23
- swift/common/middleware/s3api/s3token.py +16 -17
- swift/common/middleware/s3api/schema/delete.rng +1 -1
- swift/common/middleware/s3api/subresource.py +7 -10
- swift/common/middleware/s3api/utils.py +27 -10
- swift/common/middleware/slo.py +665 -358
- swift/common/middleware/staticweb.py +64 -37
- swift/common/middleware/symlink.py +51 -18
- swift/common/middleware/tempauth.py +76 -58
- swift/common/middleware/tempurl.py +191 -173
- swift/common/middleware/versioned_writes/__init__.py +51 -0
- swift/common/middleware/{versioned_writes.py → versioned_writes/legacy.py} +27 -26
- swift/common/middleware/versioned_writes/object_versioning.py +1482 -0
- swift/common/middleware/x_profile/exceptions.py +1 -4
- swift/common/middleware/x_profile/html_viewer.py +18 -19
- swift/common/middleware/x_profile/profile_model.py +1 -2
- swift/common/middleware/xprofile.py +10 -10
- swift-2.23.3.data/scripts/swift-container-server → swift/common/recon.py +13 -8
- swift/common/registry.py +147 -0
- swift/common/request_helpers.py +324 -57
- swift/common/ring/builder.py +67 -25
- swift/common/ring/composite_builder.py +1 -1
- swift/common/ring/ring.py +177 -51
- swift/common/ring/utils.py +1 -1
- swift/common/splice.py +10 -6
- swift/common/statsd_client.py +205 -0
- swift/common/storage_policy.py +49 -44
- swift/common/swob.py +86 -102
- swift/common/{utils.py → utils/__init__.py} +2163 -2772
- swift/common/utils/base.py +131 -0
- swift/common/utils/config.py +433 -0
- swift/common/utils/ipaddrs.py +256 -0
- swift/common/utils/libc.py +345 -0
- swift/common/utils/logs.py +859 -0
- swift/common/utils/timestamp.py +412 -0
- swift/common/wsgi.py +553 -535
- swift/container/auditor.py +14 -100
- swift/container/backend.py +490 -231
- swift/container/reconciler.py +126 -37
- swift/container/replicator.py +96 -22
- swift/container/server.py +358 -165
- swift/container/sharder.py +1540 -684
- swift/container/sync.py +94 -88
- swift/container/updater.py +53 -32
- swift/obj/auditor.py +153 -35
- swift/obj/diskfile.py +466 -217
- swift/obj/expirer.py +406 -124
- swift/obj/mem_diskfile.py +7 -4
- swift/obj/mem_server.py +1 -0
- swift/obj/reconstructor.py +523 -262
- swift/obj/replicator.py +249 -188
- swift/obj/server.py +207 -122
- swift/obj/ssync_receiver.py +145 -85
- swift/obj/ssync_sender.py +113 -54
- swift/obj/updater.py +652 -139
- swift/obj/watchers/__init__.py +0 -0
- swift/obj/watchers/dark_data.py +213 -0
- swift/proxy/controllers/account.py +11 -11
- swift/proxy/controllers/base.py +848 -604
- swift/proxy/controllers/container.py +433 -92
- swift/proxy/controllers/info.py +3 -2
- swift/proxy/controllers/obj.py +1000 -489
- swift/proxy/server.py +185 -112
- {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/AUTHORS +58 -11
- {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/METADATA +51 -56
- swift-2.35.0.dist-info/RECORD +201 -0
- {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/WHEEL +1 -1
- {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/entry_points.txt +43 -0
- swift-2.35.0.dist-info/pbr.json +1 -0
- swift/locale/de/LC_MESSAGES/swift.po +0 -1216
- swift/locale/en_GB/LC_MESSAGES/swift.po +0 -1207
- swift/locale/es/LC_MESSAGES/swift.po +0 -1085
- swift/locale/fr/LC_MESSAGES/swift.po +0 -909
- swift/locale/it/LC_MESSAGES/swift.po +0 -894
- swift/locale/ja/LC_MESSAGES/swift.po +0 -965
- swift/locale/ko_KR/LC_MESSAGES/swift.po +0 -964
- swift/locale/pt_BR/LC_MESSAGES/swift.po +0 -881
- swift/locale/ru/LC_MESSAGES/swift.po +0 -891
- swift/locale/tr_TR/LC_MESSAGES/swift.po +0 -832
- swift/locale/zh_CN/LC_MESSAGES/swift.po +0 -833
- swift/locale/zh_TW/LC_MESSAGES/swift.po +0 -838
- swift-2.23.3.data/scripts/swift-account-auditor +0 -23
- swift-2.23.3.data/scripts/swift-account-info +0 -51
- swift-2.23.3.data/scripts/swift-account-reaper +0 -23
- swift-2.23.3.data/scripts/swift-account-replicator +0 -34
- swift-2.23.3.data/scripts/swift-account-server +0 -23
- swift-2.23.3.data/scripts/swift-container-auditor +0 -23
- swift-2.23.3.data/scripts/swift-container-info +0 -55
- swift-2.23.3.data/scripts/swift-container-reconciler +0 -21
- swift-2.23.3.data/scripts/swift-container-replicator +0 -34
- swift-2.23.3.data/scripts/swift-container-sharder +0 -37
- swift-2.23.3.data/scripts/swift-container-sync +0 -23
- swift-2.23.3.data/scripts/swift-container-updater +0 -23
- swift-2.23.3.data/scripts/swift-dispersion-report +0 -24
- swift-2.23.3.data/scripts/swift-form-signature +0 -20
- swift-2.23.3.data/scripts/swift-init +0 -119
- swift-2.23.3.data/scripts/swift-object-auditor +0 -29
- swift-2.23.3.data/scripts/swift-object-expirer +0 -33
- swift-2.23.3.data/scripts/swift-object-info +0 -60
- swift-2.23.3.data/scripts/swift-object-reconstructor +0 -33
- swift-2.23.3.data/scripts/swift-object-relinker +0 -41
- swift-2.23.3.data/scripts/swift-object-replicator +0 -37
- swift-2.23.3.data/scripts/swift-object-server +0 -27
- swift-2.23.3.data/scripts/swift-object-updater +0 -23
- swift-2.23.3.data/scripts/swift-proxy-server +0 -23
- swift-2.23.3.data/scripts/swift-recon +0 -24
- swift-2.23.3.data/scripts/swift-ring-builder +0 -24
- swift-2.23.3.data/scripts/swift-ring-builder-analyzer +0 -22
- swift-2.23.3.data/scripts/swift-ring-composer +0 -22
- swift-2.23.3.dist-info/RECORD +0 -220
- swift-2.23.3.dist-info/pbr.json +0 -1
- {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/LICENSE +0 -0
- {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/top_level.txt +0 -0
@@ -19,27 +19,36 @@ Logging middleware for the Swift proxy.
|
|
19
19
|
This serves as both the default logging implementation and an example of how
|
20
20
|
to plug in your own logging format/method.
|
21
21
|
|
22
|
-
The logging format implemented below is as follows
|
22
|
+
The logging format implemented below is as follows::
|
23
23
|
|
24
|
-
client_ip remote_addr end_time.datetime method path protocol
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
client_ip remote_addr end_time.datetime method path protocol
|
25
|
+
status_int referer user_agent auth_token bytes_recvd bytes_sent
|
26
|
+
client_etag transaction_id headers request_time source log_info
|
27
|
+
start_time end_time policy_index
|
28
28
|
|
29
29
|
These values are space-separated, and each is url-encoded, so that they can
|
30
|
-
be separated with a simple
|
31
|
-
|
32
|
-
* remote_addr is the contents of the REMOTE_ADDR environment variable,
|
33
|
-
client_ip is swift's best guess at the end-user IP, extracted
|
34
|
-
from the X-Forwarded-For header, X-Cluster-Ip header, or the
|
35
|
-
environment variable.
|
36
|
-
|
37
|
-
*
|
30
|
+
be separated with a simple ``.split()``.
|
31
|
+
|
32
|
+
* ``remote_addr`` is the contents of the REMOTE_ADDR environment variable,
|
33
|
+
while ``client_ip`` is swift's best guess at the end-user IP, extracted
|
34
|
+
variously from the X-Forwarded-For header, X-Cluster-Ip header, or the
|
35
|
+
REMOTE_ADDR environment variable.
|
36
|
+
|
37
|
+
* ``status_int`` is the integer part of the ``status`` string passed to this
|
38
|
+
middleware's start_response function, unless the WSGI environment has an item
|
39
|
+
with key ``swift.proxy_logging_status``, in which case the value of that item
|
40
|
+
is used. Other middleware's may set ``swift.proxy_logging_status`` to
|
41
|
+
override the logging of ``status_int``. In either case, the logged
|
42
|
+
``status_int`` value is forced to 499 if a client disconnect is detected
|
43
|
+
while this middleware is handling a request, or 500 if an exception is caught
|
44
|
+
while handling a request.
|
45
|
+
|
46
|
+
* ``source`` (``swift.source`` in the WSGI environment) indicates the code
|
38
47
|
that generated the request, such as most middleware. (See below for
|
39
48
|
more detail.)
|
40
49
|
|
41
|
-
* log_info (swift.log_info in the WSGI environment) is for additional
|
42
|
-
information that could prove quite useful, such as any x-delete-at
|
50
|
+
* ``log_info`` (``swift.log_info`` in the WSGI environment) is for additional
|
51
|
+
information that could prove quite useful, such as any ``x-delete-at``
|
43
52
|
value or other "behind the scenes" activity that might not
|
44
53
|
otherwise be detectable from the plain log information. Code that
|
45
54
|
wishes to add additional log information should use code like
|
@@ -49,6 +58,11 @@ be separated with a simple .split()
|
|
49
58
|
* Values that are missing (e.g. due to a header not being present) or zero
|
50
59
|
are generally represented by a single hyphen ('-').
|
51
60
|
|
61
|
+
.. note::
|
62
|
+
The message format may be configured using the ``log_msg_template`` option,
|
63
|
+
allowing fields to be added, removed, re-ordered, and even anonymized. For
|
64
|
+
more information, see https://docs.openstack.org/swift/latest/logs.html
|
65
|
+
|
52
66
|
The proxy-logging can be used twice in the proxy server's pipeline when there
|
53
67
|
is middleware installed that can return custom responses that don't follow the
|
54
68
|
standard pipeline to the proxy server.
|
@@ -57,30 +71,37 @@ For example, with staticweb, the middleware might intercept a request to
|
|
57
71
|
/v1/AUTH_acc/cont/, make a subrequest to the proxy to retrieve
|
58
72
|
/v1/AUTH_acc/cont/index.html and, in effect, respond to the client's original
|
59
73
|
request using the 2nd request's body. In this instance the subrequest will be
|
60
|
-
logged by the rightmost middleware (with a swift.source set) and the
|
61
|
-
request (with body overridden) will be logged by leftmost middleware.
|
74
|
+
logged by the rightmost middleware (with a ``swift.source`` set) and the
|
75
|
+
outgoing request (with body overridden) will be logged by leftmost middleware.
|
62
76
|
|
63
77
|
Requests that follow the normal pipeline (use the same wsgi environment
|
64
78
|
throughout) will not be double logged because an environment variable
|
65
|
-
(swift.proxy_access_log_made) is checked/set when a log is made.
|
79
|
+
(``swift.proxy_access_log_made``) is checked/set when a log is made.
|
66
80
|
|
67
|
-
All middleware making subrequests should take care to set swift.source when
|
81
|
+
All middleware making subrequests should take care to set ``swift.source`` when
|
68
82
|
needed. With the doubled proxy logs, any consumer/processor of swift's proxy
|
69
|
-
logs should look at the swift.source field, the rightmost log value, to
|
70
|
-
if this is a middleware subrequest or not. A log processor calculating
|
71
|
-
bandwidth usage will want to only sum up logs with no swift.source
|
83
|
+
logs should look at the ``swift.source`` field, the rightmost log value, to
|
84
|
+
decide if this is a middleware subrequest or not. A log processor calculating
|
85
|
+
bandwidth usage will want to only sum up logs with no ``swift.source``.
|
72
86
|
"""
|
73
87
|
|
88
|
+
import os
|
74
89
|
import time
|
75
90
|
|
91
|
+
from swift.common.constraints import valid_api_version
|
92
|
+
from swift.common.middleware.catch_errors import enforce_byte_count
|
93
|
+
from swift.common.request_helpers import get_log_info
|
76
94
|
from swift.common.swob import Request
|
77
95
|
from swift.common.utils import (get_logger, get_remote_client,
|
78
|
-
config_true_value,
|
96
|
+
config_true_value, reiterate,
|
97
|
+
close_if_possible, cap_length,
|
79
98
|
InputProxy, list_from_csv, get_policy_index,
|
80
99
|
split_path, StrAnonymizer, StrFormatTime,
|
81
100
|
LogStringFormatter)
|
82
101
|
|
83
102
|
from swift.common.storage_policy import POLICIES
|
103
|
+
from swift.common.registry import get_sensitive_headers, \
|
104
|
+
get_sensitive_params, register_sensitive_header
|
84
105
|
|
85
106
|
|
86
107
|
class ProxyLoggingMiddleware(object):
|
@@ -90,6 +111,7 @@ class ProxyLoggingMiddleware(object):
|
|
90
111
|
|
91
112
|
def __init__(self, app, conf, logger=None):
|
92
113
|
self.app = app
|
114
|
+
self.pid = os.getpid()
|
93
115
|
self.log_formatter = LogStringFormatter(default='-', quote=True)
|
94
116
|
self.log_msg_template = conf.get(
|
95
117
|
'log_msg_template', (
|
@@ -115,7 +137,7 @@ class ProxyLoggingMiddleware(object):
|
|
115
137
|
self.valid_methods = conf.get(
|
116
138
|
'access_log_statsd_valid_http_methods',
|
117
139
|
conf.get('log_statsd_valid_http_methods',
|
118
|
-
'GET,HEAD,POST,PUT,DELETE,COPY,OPTIONS'))
|
140
|
+
'GET,HEAD,POST,PUT,DELETE,COPY,OPTIONS,UPDATE'))
|
119
141
|
self.valid_methods = [m.strip().upper() for m in
|
120
142
|
self.valid_methods.split(',') if m.strip()]
|
121
143
|
access_log_conf = {}
|
@@ -127,9 +149,10 @@ class ProxyLoggingMiddleware(object):
|
|
127
149
|
value = conf.get('access_' + key, conf.get(key, None))
|
128
150
|
if value:
|
129
151
|
access_log_conf[key] = value
|
130
|
-
self.access_logger = logger or get_logger(
|
131
|
-
|
132
|
-
|
152
|
+
self.access_logger = logger or get_logger(
|
153
|
+
access_log_conf,
|
154
|
+
log_route=conf.get('access_log_route', 'proxy-access'),
|
155
|
+
statsd_tail_prefix='proxy-server')
|
133
156
|
self.reveal_sensitive_prefix = int(
|
134
157
|
conf.get('reveal_sensitive_prefix', 16))
|
135
158
|
self.check_log_msg_template_validity()
|
@@ -144,6 +167,8 @@ class ProxyLoggingMiddleware(object):
|
|
144
167
|
self.anonymization_salt),
|
145
168
|
'remote_addr': StrAnonymizer('4.3.2.1', self.anonymization_method,
|
146
169
|
self.anonymization_salt),
|
170
|
+
'domain': StrAnonymizer('', self.anonymization_method,
|
171
|
+
self.anonymization_salt),
|
147
172
|
'path': StrAnonymizer('/', self.anonymization_method,
|
148
173
|
self.anonymization_salt),
|
149
174
|
'referer': StrAnonymizer('ref', self.anonymization_method,
|
@@ -171,7 +196,10 @@ class ProxyLoggingMiddleware(object):
|
|
171
196
|
'request_time': '0.05',
|
172
197
|
'source': '',
|
173
198
|
'log_info': '',
|
174
|
-
'policy_index': ''
|
199
|
+
'policy_index': '',
|
200
|
+
'ttfb': '0.05',
|
201
|
+
'pid': '42',
|
202
|
+
'wire_status_int': '200',
|
175
203
|
}
|
176
204
|
try:
|
177
205
|
self.log_formatter.format(self.log_msg_template, **replacements)
|
@@ -188,12 +216,29 @@ class ProxyLoggingMiddleware(object):
|
|
188
216
|
env['swift.proxy_access_log_made'] = True
|
189
217
|
|
190
218
|
def obscure_sensitive(self, value):
|
191
|
-
|
192
|
-
|
193
|
-
|
219
|
+
return cap_length(value, self.reveal_sensitive_prefix)
|
220
|
+
|
221
|
+
def obscure_req(self, req):
|
222
|
+
for header in get_sensitive_headers():
|
223
|
+
if header in req.headers:
|
224
|
+
req.headers[header] = \
|
225
|
+
self.obscure_sensitive(req.headers[header])
|
226
|
+
|
227
|
+
obscure_params = get_sensitive_params()
|
228
|
+
new_params = []
|
229
|
+
any_obscured = False
|
230
|
+
for k, v in req.params.items():
|
231
|
+
if k in obscure_params:
|
232
|
+
new_params.append((k, self.obscure_sensitive(v)))
|
233
|
+
any_obscured = True
|
234
|
+
else:
|
235
|
+
new_params.append((k, v))
|
236
|
+
if any_obscured:
|
237
|
+
req.params = new_params
|
194
238
|
|
195
239
|
def log_request(self, req, status_int, bytes_received, bytes_sent,
|
196
|
-
start_time, end_time, resp_headers=None
|
240
|
+
start_time, end_time, resp_headers=None, ttfb=0,
|
241
|
+
wire_status_int=None):
|
197
242
|
"""
|
198
243
|
Log a request.
|
199
244
|
|
@@ -204,7 +249,14 @@ class ProxyLoggingMiddleware(object):
|
|
204
249
|
:param start_time: timestamp request started
|
205
250
|
:param end_time: timestamp request completed
|
206
251
|
:param resp_headers: dict of the response headers
|
252
|
+
:param ttfb: time to first byte
|
253
|
+
:param wire_status_int: the on the wire status int
|
207
254
|
"""
|
255
|
+
self.obscure_req(req)
|
256
|
+
domain = req.environ.get('HTTP_HOST',
|
257
|
+
req.environ.get('SERVER_NAME', None))
|
258
|
+
if ':' in domain:
|
259
|
+
domain, port = domain.rsplit(':', 1)
|
208
260
|
resp_headers = resp_headers or {}
|
209
261
|
logged_headers = None
|
210
262
|
if self.log_hdrs:
|
@@ -220,9 +272,8 @@ class ProxyLoggingMiddleware(object):
|
|
220
272
|
duration_time_str = "%.4f" % (end_time - start_time)
|
221
273
|
policy_index = get_policy_index(req.headers, resp_headers)
|
222
274
|
|
223
|
-
|
224
|
-
|
225
|
-
_, acc, cont, obj = split_path(req.path, 1, 4, True)
|
275
|
+
swift_path = req.environ.get('swift.backend_path', req.path)
|
276
|
+
acc, cont, obj = self.get_aco_from_path(swift_path)
|
226
277
|
|
227
278
|
replacements = {
|
228
279
|
# Time information
|
@@ -235,6 +286,8 @@ class ProxyLoggingMiddleware(object):
|
|
235
286
|
'remote_addr': StrAnonymizer(req.remote_addr,
|
236
287
|
self.anonymization_method,
|
237
288
|
self.anonymization_salt),
|
289
|
+
'domain': StrAnonymizer(domain, self.anonymization_method,
|
290
|
+
self.anonymization_salt),
|
238
291
|
'path': StrAnonymizer(req.path_qs, self.anonymization_method,
|
239
292
|
self.anonymization_salt),
|
240
293
|
'referer': StrAnonymizer(req.referer, self.anonymization_method,
|
@@ -259,16 +312,17 @@ class ProxyLoggingMiddleware(object):
|
|
259
312
|
req.environ.get('SERVER_PROTOCOL'),
|
260
313
|
'status_int': status_int,
|
261
314
|
'auth_token':
|
262
|
-
|
263
|
-
req.headers.get('x-auth-token')),
|
315
|
+
req.headers.get('x-auth-token'),
|
264
316
|
'bytes_recvd': bytes_received,
|
265
317
|
'bytes_sent': bytes_sent,
|
266
318
|
'transaction_id': req.environ.get('swift.trans_id'),
|
267
319
|
'request_time': duration_time_str,
|
268
320
|
'source': req.environ.get('swift.source'),
|
269
|
-
'log_info':
|
270
|
-
','.join(req.environ.get('swift.log_info', '')),
|
321
|
+
'log_info': get_log_info(req.environ),
|
271
322
|
'policy_index': policy_index,
|
323
|
+
'ttfb': ttfb,
|
324
|
+
'pid': self.pid,
|
325
|
+
'wire_status_int': wire_status_int or status_int,
|
272
326
|
}
|
273
327
|
self.access_logger.info(
|
274
328
|
self.log_formatter.format(self.log_msg_template,
|
@@ -293,21 +347,28 @@ class ProxyLoggingMiddleware(object):
|
|
293
347
|
self.access_logger.update_stats(metric_name_policy + '.xfer',
|
294
348
|
bytes_received + bytes_sent)
|
295
349
|
|
350
|
+
def get_aco_from_path(self, swift_path):
|
351
|
+
try:
|
352
|
+
version, acc, cont, obj = split_path(swift_path, 1, 4, True)
|
353
|
+
if not valid_api_version(version):
|
354
|
+
raise ValueError
|
355
|
+
except ValueError:
|
356
|
+
acc, cont, obj = None, None, None
|
357
|
+
return acc, cont, obj
|
358
|
+
|
296
359
|
def get_metric_name_type(self, req):
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
return
|
360
|
+
swift_path = req.environ.get('swift.backend_path', req.path)
|
361
|
+
acc, cont, obj = self.get_aco_from_path(swift_path)
|
362
|
+
if obj:
|
363
|
+
return 'object'
|
364
|
+
if cont:
|
365
|
+
return 'container'
|
366
|
+
if acc:
|
367
|
+
return 'account'
|
368
|
+
return req.environ.get('swift.source') or 'UNKNOWN'
|
306
369
|
|
307
370
|
def statsd_metric_name(self, req, status_int, method):
|
308
371
|
stat_type = self.get_metric_name_type(req)
|
309
|
-
if stat_type is None:
|
310
|
-
return None
|
311
372
|
stat_method = method if method in self.valid_methods \
|
312
373
|
else 'BAD_METHOD'
|
313
374
|
return '.'.join((stat_type, stat_method, str(status_int)))
|
@@ -343,79 +404,80 @@ class ProxyLoggingMiddleware(object):
|
|
343
404
|
def my_start_response(status, headers, exc_info=None):
|
344
405
|
start_response_args[0] = (status, list(headers), exc_info)
|
345
406
|
|
346
|
-
def status_int_for_logging(
|
407
|
+
def status_int_for_logging():
|
347
408
|
# log disconnected clients as '499' status code
|
348
|
-
if
|
349
|
-
|
350
|
-
|
351
|
-
ret_status_int = int(
|
352
|
-
start_response_args[0][0].split(' ', 1)[0])
|
353
|
-
else:
|
354
|
-
ret_status_int = start_status
|
355
|
-
return ret_status_int
|
409
|
+
if input_proxy.client_disconnect:
|
410
|
+
return 499
|
411
|
+
return env.get('swift.proxy_logging_status')
|
356
412
|
|
357
413
|
def iter_response(iterable):
|
358
|
-
iterator =
|
359
|
-
|
360
|
-
chunk = next(iterator)
|
361
|
-
while not chunk:
|
362
|
-
chunk = next(iterator)
|
363
|
-
except StopIteration:
|
364
|
-
chunk = ''
|
414
|
+
iterator = reiterate(iterable)
|
415
|
+
content_length = None
|
365
416
|
for h, v in start_response_args[0][1]:
|
366
|
-
if h.lower()
|
417
|
+
if h.lower() == 'content-length':
|
418
|
+
content_length = int(v)
|
419
|
+
break
|
420
|
+
elif h.lower() == 'transfer-encoding':
|
367
421
|
break
|
368
422
|
else:
|
369
|
-
if
|
370
|
-
|
371
|
-
elif isinstance(iterable, list):
|
423
|
+
if isinstance(iterator, list):
|
424
|
+
content_length = sum(len(i) for i in iterator)
|
372
425
|
start_response_args[0][1].append(
|
373
|
-
('Content-Length', str(
|
426
|
+
('Content-Length', str(content_length)))
|
427
|
+
|
428
|
+
req = Request(env)
|
429
|
+
method = self.method_from_req(req)
|
430
|
+
if method == 'HEAD':
|
431
|
+
content_length = 0
|
432
|
+
if content_length is not None:
|
433
|
+
iterator = enforce_byte_count(iterator, content_length)
|
434
|
+
|
435
|
+
wire_status_int = int(start_response_args[0][0].split(' ', 1)[0])
|
374
436
|
resp_headers = dict(start_response_args[0][1])
|
375
437
|
start_response(*start_response_args[0])
|
376
|
-
req = Request(env)
|
377
438
|
|
378
439
|
# Log timing information for time-to-first-byte (GET requests only)
|
379
|
-
|
440
|
+
ttfb = 0.0
|
380
441
|
if method == 'GET':
|
381
|
-
status_int = status_int_for_logging()
|
382
442
|
policy_index = get_policy_index(req.headers, resp_headers)
|
383
|
-
metric_name = self.statsd_metric_name(
|
443
|
+
metric_name = self.statsd_metric_name(
|
444
|
+
req, wire_status_int, method)
|
384
445
|
metric_name_policy = self.statsd_metric_name_policy(
|
385
|
-
req,
|
446
|
+
req, wire_status_int, method, policy_index)
|
447
|
+
ttfb = time.time() - start_time
|
386
448
|
if metric_name:
|
387
|
-
self.access_logger.
|
388
|
-
metric_name + '.first-byte.timing',
|
449
|
+
self.access_logger.timing(
|
450
|
+
metric_name + '.first-byte.timing', ttfb * 1000)
|
389
451
|
if metric_name_policy:
|
390
|
-
self.access_logger.
|
391
|
-
metric_name_policy + '.first-byte.timing',
|
452
|
+
self.access_logger.timing(
|
453
|
+
metric_name_policy + '.first-byte.timing', ttfb * 1000)
|
392
454
|
|
393
455
|
bytes_sent = 0
|
394
|
-
client_disconnect = False
|
395
456
|
try:
|
396
|
-
|
457
|
+
for chunk in iterator:
|
397
458
|
bytes_sent += len(chunk)
|
398
459
|
yield chunk
|
399
|
-
chunk = next(iterator)
|
400
|
-
except StopIteration: # iterator was depleted
|
401
|
-
return
|
402
460
|
except GeneratorExit: # generator was closed before we finished
|
403
|
-
|
461
|
+
env['swift.proxy_logging_status'] = 499
|
462
|
+
raise
|
463
|
+
except Exception:
|
464
|
+
env['swift.proxy_logging_status'] = 500
|
404
465
|
raise
|
405
466
|
finally:
|
406
|
-
|
467
|
+
env.setdefault('swift.proxy_logging_status', wire_status_int)
|
468
|
+
status_int = status_int_for_logging()
|
407
469
|
self.log_request(
|
408
470
|
req, status_int, input_proxy.bytes_received, bytes_sent,
|
409
|
-
start_time, time.time(), resp_headers=resp_headers
|
410
|
-
|
411
|
-
|
412
|
-
close_method()
|
471
|
+
start_time, time.time(), resp_headers=resp_headers,
|
472
|
+
ttfb=ttfb, wire_status_int=wire_status_int)
|
473
|
+
close_if_possible(iterator)
|
413
474
|
|
414
475
|
try:
|
415
476
|
iterable = self.app(env, my_start_response)
|
416
477
|
except Exception:
|
417
478
|
req = Request(env)
|
418
|
-
|
479
|
+
env['swift.proxy_logging_status'] = 500
|
480
|
+
status_int = status_int_for_logging()
|
419
481
|
self.log_request(
|
420
482
|
req, status_int, input_proxy.bytes_received, 0, start_time,
|
421
483
|
time.time())
|
@@ -428,6 +490,12 @@ def filter_factory(global_conf, **local_conf):
|
|
428
490
|
conf = global_conf.copy()
|
429
491
|
conf.update(local_conf)
|
430
492
|
|
493
|
+
# Normally it would be the middleware that uses the header that
|
494
|
+
# would register it, but because there could be 3rd party auth middlewares
|
495
|
+
# that use 'x-auth-token' or 'x-storage-token' we special case it here.
|
496
|
+
register_sensitive_header('x-auth-token')
|
497
|
+
register_sensitive_header('x-storage-token')
|
498
|
+
|
431
499
|
def proxy_logger(app):
|
432
500
|
return ProxyLoggingMiddleware(app, conf)
|
433
501
|
return proxy_logger
|
@@ -13,11 +13,11 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
import time
|
16
|
-
from swift import gettext_ as _
|
17
16
|
|
18
17
|
import eventlet
|
19
18
|
|
20
|
-
from swift.common.utils import cache_from_env, get_logger
|
19
|
+
from swift.common.utils import cache_from_env, get_logger
|
20
|
+
from swift.common.registry import register_swift_info
|
21
21
|
from swift.proxy.controllers.base import get_account_info, get_container_info
|
22
22
|
from swift.common.constraints import valid_api_version
|
23
23
|
from swift.common.memcached import MemcacheConnectionError
|
@@ -242,6 +242,10 @@ class RateLimitMiddleware(object):
|
|
242
242
|
if not self.memcache_client:
|
243
243
|
return None
|
244
244
|
|
245
|
+
if req.environ.get('swift.ratelimit.handled'):
|
246
|
+
return None
|
247
|
+
req.environ['swift.ratelimit.handled'] = True
|
248
|
+
|
245
249
|
try:
|
246
250
|
account_info = get_account_info(req.environ, self.app,
|
247
251
|
swift_source='RL')
|
@@ -256,7 +260,7 @@ class RateLimitMiddleware(object):
|
|
256
260
|
|
257
261
|
if account_name in self.ratelimit_blacklist or \
|
258
262
|
account_global_ratelimit == 'BLACKLIST':
|
259
|
-
self.logger.error(
|
263
|
+
self.logger.error('Returning 497 because of blacklisting: %s',
|
260
264
|
account_name)
|
261
265
|
eventlet.sleep(self.BLACK_LIST_SLEEP)
|
262
266
|
return Response(status='497 Blacklisted',
|
@@ -271,18 +275,21 @@ class RateLimitMiddleware(object):
|
|
271
275
|
if self.log_sleep_time_seconds and \
|
272
276
|
need_to_sleep > self.log_sleep_time_seconds:
|
273
277
|
self.logger.warning(
|
274
|
-
|
275
|
-
|
278
|
+
"Ratelimit sleep log: %(sleep)s for "
|
279
|
+
"%(account)s/%(container)s/%(object)s",
|
276
280
|
{'sleep': need_to_sleep, 'account': account_name,
|
277
281
|
'container': container_name, 'object': obj_name})
|
278
282
|
if need_to_sleep > 0:
|
279
283
|
eventlet.sleep(need_to_sleep)
|
280
284
|
except MaxSleepTimeHitError as e:
|
285
|
+
if obj_name:
|
286
|
+
path = '/'.join((account_name, container_name, obj_name))
|
287
|
+
else:
|
288
|
+
path = '/'.join((account_name, container_name))
|
281
289
|
self.logger.error(
|
282
|
-
|
283
|
-
|
284
|
-
{'meth': req.method, '
|
285
|
-
'cont': container_name, 'obj': obj_name, 'e': str(e)})
|
290
|
+
'Returning 498 for %(meth)s to %(path)s. '
|
291
|
+
'Ratelimit (Max Sleep) %(e)s',
|
292
|
+
{'meth': req.method, 'path': path, 'e': str(e)})
|
286
293
|
error_resp = Response(status='498 Rate Limited',
|
287
294
|
body='Slow down', request=req)
|
288
295
|
return error_resp
|
@@ -301,7 +308,7 @@ class RateLimitMiddleware(object):
|
|
301
308
|
self.memcache_client = cache_from_env(env)
|
302
309
|
if not self.memcache_client:
|
303
310
|
self.logger.warning(
|
304
|
-
|
311
|
+
'Warning: Cannot ratelimit without a memcached client')
|
305
312
|
return self.app(env, start_response)
|
306
313
|
try:
|
307
314
|
version, account, container, obj = req.split_path(1, 4, True)
|
@@ -12,10 +12,10 @@
|
|
12
12
|
# implied.
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
|
-
from swift.common.constraints import check_account_format
|
15
|
+
from swift.common.constraints import check_account_format, valid_api_version
|
16
16
|
from swift.common.swob import HTTPMethodNotAllowed, Request
|
17
|
-
from swift.common.utils import get_logger, config_true_value
|
18
|
-
|
17
|
+
from swift.common.utils import get_logger, config_true_value
|
18
|
+
from swift.common.registry import register_swift_info
|
19
19
|
from swift.proxy.controllers.base import get_info
|
20
20
|
|
21
21
|
"""
|
@@ -79,7 +79,9 @@ class ReadOnlyMiddleware(object):
|
|
79
79
|
return self.app(env, start_response)
|
80
80
|
|
81
81
|
try:
|
82
|
-
version, account, container, obj = req.split_path(
|
82
|
+
version, account, container, obj = req.split_path(2, 4, True)
|
83
|
+
if not valid_api_version(version):
|
84
|
+
raise ValueError
|
83
85
|
except ValueError:
|
84
86
|
return self.app(env, start_response)
|
85
87
|
|