Skip to content

Commit a508216

Browse files
authored
Merge pull request ceph#60942 from AliMasarweh/wip-alimasa-bucket-logging-filter
RGW/logging: add filtering for bucket logging Reviewed-by: yuvalif<[email protected]>
2 parents 856b47f + e03f5ca commit a508216

File tree

11 files changed

+451
-295
lines changed

11 files changed

+451
-295
lines changed

doc/radosgw/bucket_logging.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ Journal
4040
If logging type is set to "Journal", the records are written to the log bucket before the bucket operation is completed.
4141
This means that if the logging action fails, the operation will not be executed, and an error will be returned to the client.
4242
An exception to the above are "multi/delete" log records: if writing these log records fail, the operation continues and may still be successful.
43-
Note that it may happen that the log records were successfully written, but the bucket operation failed, since the logs are written
44-
before such a failure, there will be no indication for that in the log records.
43+
Journal mode supports filtering out records based on matches of the prefixes and suffixes of the logged object keys. Regular-expression matching can also be used on these to create filters.
44+
Note that it may happen that the log records were successfully written, but the bucket operation failed, since the logs are written.
4545

4646

4747
Bucket Logging REST API

doc/radosgw/s3/bucketops.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,14 @@ Parameters are XML encoded in the body of the request, in the following format:
751751
<TargetPrefix>string</TargetPrefix>
752752
<LoggingType>Standard|Journal</LoggingType>
753753
<ObjectRollTime>integer</ObjectRollTime>
754+
<Filter>
755+
<S3Key>
756+
<FilterRule>
757+
<Name>suffix/prefix/regex</Name>
758+
<Value></Value>
759+
</FilterRule>
760+
</S3Key>
761+
</Filter>
754762
</LoggingEnabled>
755763
</BucketLoggingStatus>
756764

@@ -881,6 +889,14 @@ Response is XML encoded in the body of the request, in the following format:
881889
<TargetPrefix>string</TargetPrefix>
882890
<LoggingType>Standard|Journal</LoggingType>
883891
<ObjectRollTime>integer</ObjectRollTime>
892+
<Filter>
893+
<S3Key>
894+
<FilterRule>
895+
<Name>suffix/prefix/regex</Name>
896+
<Value></Value>
897+
</FilterRule>
898+
</S3Key>
899+
</Filter>
884900
</LoggingEnabled>
885901
</BucketLoggingStatus>
886902

examples/rgw/boto3/bucket_logging.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@
3939
},
4040
'ObjectRollTime': 60,
4141
'LoggingType': 'Journal',
42+
"Filter": {
43+
"Key": {
44+
"FilterRules":
45+
[
46+
{
47+
"Name": "prefix",
48+
"Value": "myfile"
49+
}
50+
]
51+
}
52+
}
4253
}
4354
}
4455

examples/rgw/boto3/service-2.sdk-extras.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,10 @@
310310
"RecordsBatchSize":{
311311
"shape":"RecordsBatchSize",
312312
"documentation":"indicates how many records to batch in memory before writing to the object. if set to zero, records are written syncronously to the object. if <code>ObjectRollTime</code>e is reached, the batch of records will be written to the object regardless of the number of records. </p>"
313+
},
314+
"Filter":{
315+
"shape":"LoggingConfigurationFilter",
316+
"documentation":"<p>A filter for all log object. Filter for the object by its key (prefix, suffix and regex).</p>"
313317
}
314318
},
315319
"documentation":"<p>Describes where logs are stored the prefix assigned to all log object keys for a bucket, and their format. also, the level the delivery guarantee of the records.</p>"
@@ -363,6 +367,18 @@
363367
"Standard",
364368
"Journal"
365369
]
370+
},
371+
"LoggingConfigurationFilter":{
372+
"type":"structure",
373+
"members":{
374+
"Key":{
375+
"shape":"S3KeyFilter",
376+
"documentation":"<p/>",
377+
"locationName":"S3Key"
378+
}
379+
},
380+
"documentation":"<p>A filter for all log object. Filter for the object by its key (prefix, suffix and regex).</p>",
381+
"locationName":"Filter"
366382
}
367383
},
368384
"documentation":"<p/>"

src/rgw/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ set(librgw_common_srcs
9090
rgw_notify_event_type.cc
9191
rgw_period_history.cc
9292
rgw_period_puller.cc
93+
rgw_s3_filter.cc
9394
rgw_pubsub.cc
9495
rgw_coroutine.cc
9596
rgw_cr_rest.cc

src/rgw/rgw_bucket_logging.cc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ bool configuration::decode_xml(XMLObj* obj) {
3131
logging_type = LoggingType::Standard;
3232
} else if (type == "Journal") {
3333
logging_type = LoggingType::Journal;
34+
if (iter = o->find("Filter"); XMLObj* const filter_o = iter.get_next()) {
35+
RGWXMLDecoder::decode_xml("S3Key", key_filter, filter_o);
36+
}
3437
} else {
3538
// we don't allow for type "Any" in the configuration
3639
throw RGWXMLDecoder::err("invalid bucket logging record type: '" + type + "'");
@@ -73,6 +76,11 @@ void configuration::dump_xml(Formatter *f) const {
7376
break;
7477
case LoggingType::Journal:
7578
::encode_xml("LoggingType", "Journal", f);
79+
if (key_filter.has_content()) {
80+
f->open_object_section("Filter");
81+
::encode_xml("S3Key", key_filter, f);
82+
f->close_section(); // Filter
83+
}
7684
break;
7785
case LoggingType::Any:
7886
::encode_xml("LoggingType", "", f);
@@ -118,6 +126,10 @@ void configuration::dump(Formatter *f) const {
118126
break;
119127
case LoggingType::Journal:
120128
encode_json("loggingType", "Journal", f);
129+
if (key_filter.has_content()) {
130+
Formatter::ObjectSection s(*f, "Filter");
131+
encode_json("S3Key", key_filter, f);
132+
}
121133
break;
122134
case LoggingType::Any:
123135
encode_json("loggingType", "", f);
@@ -526,6 +538,11 @@ int log_record(rgw::sal::Driver* driver,
526538
if (type != LoggingType::Any && configuration.logging_type != type) {
527539
return 0;
528540
}
541+
if (configuration.key_filter.has_content()) {
542+
if (!match(configuration.key_filter, obj->get_name())) {
543+
return 0;
544+
}
545+
}
529546
ldpp_dout(dpp, 20) << "INFO: found matching logging configuration of bucket '" << s->bucket->get_name() <<
530547
"' configuration: " << configuration.to_json_str() << dendl;
531548
if (auto ret = log_record(driver, obj, s, op_name, etag, size, configuration, dpp, y, async_completion, log_source_bucket); ret < 0) {

src/rgw/rgw_bucket_logging.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "include/buffer.h"
1111
#include "include/encoding.h"
1212
#include "common/async/yield_context.h"
13+
#include "rgw_s3_filter.h"
1314

1415
class XMLObj;
1516
namespace ceph { class Formatter; }
@@ -48,6 +49,14 @@ namespace rgw::bucketlogging {
4849
<LoggingType>Standard|Journal</LoggingType> <!-- Ceph extension -->
4950
<ObjectRollTime>integer</ObjectRollTime> <!-- Ceph extension -->
5051
<RecordsBatchSize>integer</RecordsBatchSize> <!-- Ceph extension -->
52+
<Filter>
53+
<S3Key>
54+
<FilterRule>
55+
<Name>suffix/prefix/regex</Name>
56+
<Value></Value>
57+
</FilterRule>
58+
</S3Key>
59+
</Filter>
5160
</LoggingEnabled>
5261
</BucketLoggingStatus>
5362
*/
@@ -78,6 +87,7 @@ struct configuration {
7887
PartitionDateSource date_source = PartitionDateSource::DeliveryTime;
7988
// EventTime: use only year, month, and day. The hour, minutes and seconds are set to 00 in the key
8089
// DeliveryTime: the time the log object was created
90+
rgw_s3_key_filter key_filter;
8191
bool decode_xml(XMLObj *obj);
8292
void dump_xml(Formatter *f) const;
8393
void dump(Formatter *f) const; // json
@@ -92,6 +102,9 @@ struct configuration {
92102
encode(static_cast<int>(logging_type), bl);
93103
encode(records_batch_size, bl);
94104
encode(static_cast<int>(date_source), bl);
105+
if (logging_type == LoggingType::Journal) {
106+
encode(key_filter, bl);
107+
}
95108
ENCODE_FINISH(bl);
96109
}
97110

@@ -108,6 +121,9 @@ struct configuration {
108121
decode(records_batch_size, bl);
109122
decode(type, bl);
110123
date_source = static_cast<PartitionDateSource>(type);
124+
if (logging_type == LoggingType::Journal) {
125+
decode(key_filter, bl);
126+
}
111127
DECODE_FINISH(bl);
112128
}
113129
};

0 commit comments

Comments
 (0)