};
WRITE_CLASS_ENCODER(rgw_bucket_dir)
-
-struct rgw_usage_log_entry {
- string owner;
- string bucket;
- uint64_t epoch;
+struct rgw_usage_data {
uint64_t bytes_sent;
uint64_t bytes_received;
uint64_t ops;
uint64_t successful_ops;
- rgw_usage_log_entry() : bytes_sent(0), bytes_received(0), ops(0), successful_ops(0) {}
- rgw_usage_log_entry(string& o, string& b, uint64_t s, uint64_t r) : owner(o), bucket(b), bytes_sent(s), bytes_received(r), ops(0), successful_ops(0) {}
+ rgw_usage_data() : bytes_sent(0), bytes_received(0), ops(0), successful_ops(0) {}
+ rgw_usage_data(uint64_t sent, uint64_t received) : bytes_sent(sent), bytes_received(received), ops(0), successful_ops(0) {}
void encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);
- ::encode(owner, bl);
- ::encode(bucket, bl);
- ::encode(epoch, bl);
::encode(bytes_sent, bl);
::encode(bytes_received, bl);
::encode(ops, bl);
ENCODE_FINISH(bl);
}
-
- void decode(bufferlist::iterator& bl) {
+ void decode(bufferlist::iterator& bl) {
DECODE_START(1, bl);
- ::decode(owner, bl);
- ::decode(bucket, bl);
- ::decode(epoch, bl);
::decode(bytes_sent, bl);
::decode(bytes_received, bl);
::decode(ops, bl);
DECODE_FINISH(bl);
}
+ void aggregate(const rgw_usage_data& usage) {
+ bytes_sent += usage.bytes_sent;
+ bytes_received += usage.bytes_received;
+ ops += usage.ops;
+ successful_ops += usage.successful_ops;
+ }
+};
+WRITE_CLASS_ENCODER(rgw_usage_data)
+
+
+struct rgw_usage_log_entry {
+ string owner;
+ string bucket;
+ uint64_t epoch;
+ map<string, rgw_usage_data> usage_map;
+
+ rgw_usage_log_entry() {}
+ rgw_usage_log_entry(string& o, string& b) : owner(o), bucket(b) {}
+
+ void encode(bufferlist& bl) const {
+ ENCODE_START(2, 2, bl);
+ ::encode(owner, bl);
+ ::encode(bucket, bl);
+ ::encode(epoch, bl);
+ ::encode(usage_map, bl);
+ ENCODE_FINISH(bl);
+ }
+
+
+ void decode(bufferlist::iterator& bl) {
+ DECODE_START(2, bl);
+ ::decode(owner, bl);
+ ::decode(bucket, bl);
+ ::decode(epoch, bl);
+ if (struct_v < 2) {
+ rgw_usage_data usage_data;
+ ::decode(usage_data.bytes_sent, bl);
+ ::decode(usage_data.bytes_received, bl);
+ ::decode(usage_data.ops, bl);
+ ::decode(usage_data.successful_ops, bl);
+ usage_map[""] = usage_data;
+ } else {
+ ::decode(usage_map, bl);
+ }
+ DECODE_FINISH(bl);
+ }
+
void aggregate(const rgw_usage_log_entry& e) {
if (owner.empty()) {
owner = e.owner;
bucket = e.bucket;
epoch = e.epoch;
}
- bytes_sent += e.bytes_sent;
- bytes_received += e.bytes_received;
- ops += e.ops;
- successful_ops += e.successful_ops;
+ map<string, rgw_usage_data>::const_iterator iter;
+ for (iter = e.usage_map.begin(); iter != e.usage_map.end(); ++iter) {
+ add(iter->first, iter->second);
+ }
+ }
+
+ void add(const string& category, const rgw_usage_data& data) {
+ usage_map[category].aggregate(data);
}
};
WRITE_CLASS_ENCODER(rgw_usage_log_entry)
return ret;
}
+void dump_usage_categories_info(Formatter *formatter, const rgw_usage_log_entry& entry)
+{
+ formatter->open_array_section("categories");
+ map<string, rgw_usage_data>::const_iterator uiter;
+ for (uiter = entry.usage_map.begin(); uiter != entry.usage_map.end(); ++uiter) {
+ const rgw_usage_data& usage = uiter->second;
+ formatter->open_object_section("entry");
+ formatter->dump_string("category", uiter->first);
+ formatter->dump_int("bytes_sent", usage.bytes_sent);
+ formatter->dump_int("bytes_received", usage.bytes_received);
+ formatter->dump_int("ops", usage.ops);
+ formatter->dump_int("successful_ops", usage.successful_ops);
+ formatter->close_section(); // entry
+ }
+ formatter->close_section(); // categories
+}
+
int main(int argc, char **argv)
{
vector<const char*> args;
utime_t ut(entry.epoch, 0);
ut.gmtime(formatter->dump_stream("time"));
formatter->dump_int("epoch", entry.epoch);
- formatter->dump_int("bytes_sent", entry.bytes_sent);
- formatter->dump_int("bytes_received", entry.bytes_received);
- formatter->dump_int("ops", entry.ops);
- formatter->dump_int("successful_ops", entry.successful_ops);
+ dump_usage_categories_info(formatter, entry);
formatter->close_section(); // bucket
formatter->flush(cout);
}
const rgw_usage_log_entry& entry = siter->second;
formatter->open_object_section("user");
formatter->dump_string("user", siter->first);
- formatter->dump_int("bytes_sent", entry.bytes_sent);
- formatter->dump_int("bytes_received", entry.bytes_received);
- formatter->dump_int("ops", entry.ops);
- formatter->dump_int("successful_ops", entry.successful_ops);
- formatter->close_section();
+ dump_usage_categories_info(formatter, entry);
+ formatter->close_section(); // user
formatter->flush(cout);
}
usage_logger = NULL;
}
-static void log_usage(struct req_state *s)
+static void log_usage(struct req_state *s, const string& op_name)
{
if (!usage_logger)
return;
else
user = s->user.user_id;
- rgw_usage_log_entry entry(user, s->bucket.name, s->bytes_sent, s->bytes_received);
+ rgw_usage_log_entry entry(user, s->bucket.name);
- entry.ops = 1;
+ rgw_usage_data data(s->bytes_sent, s->bytes_received);
+
+ data.ops = 1;
if (!s->err.is_err())
- entry.successful_ops = 1;
+ data.successful_ops = 1;
+
+ entry.add(op_name, data);
utime_t ts = ceph_clock_now(s->cct);
usage_logger->insert(ts, entry);
}
-int rgw_log_op(struct req_state *s)
+int rgw_log_op(struct req_state *s, const string& op_name)
{
struct rgw_log_entry entry;
string bucket_id;
if (s->enable_usage_log)
- log_usage(s);
+ log_usage(s, op_name);
if (!s->enable_ops_log)
return 0;
};
WRITE_CLASS_ENCODER(rgw_intent_log_entry)
-int rgw_log_op(struct req_state *s);
+int rgw_log_op(struct req_state *s, const string& op_name);
int rgw_log_intent(rgw_obj& obj, RGWIntentEvent intent, const utime_t& timestamp, bool utc);
int rgw_log_intent(struct req_state *s, rgw_obj& obj, RGWIntentEvent intent);
void rgw_log_usage_init(CephContext *cct);
req->log(s, "executing");
op->execute();
done:
- rgw_log_op(s);
+ rgw_log_op(s, (op ? op->name() : "unknown"));
int http_ret = s->err.http_ret;