summaryrefslogtreecommitdiffstats
path: root/src/rgw/rgw_usage.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rgw/rgw_usage.cc')
-rw-r--r--src/rgw/rgw_usage.cc171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/rgw/rgw_usage.cc b/src/rgw/rgw_usage.cc
new file mode 100644
index 000000000..ca7ca20eb
--- /dev/null
+++ b/src/rgw/rgw_usage.cc
@@ -0,0 +1,171 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab ft=cpp
+
+#include <string>
+#include <map>
+
+#include "rgw_rados.h"
+#include "rgw_usage.h"
+#include "rgw_formats.h"
+#include "rgw_sal.h"
+
+using namespace std;
+
+static void dump_usage_categories_info(Formatter *formatter, const rgw_usage_log_entry& entry, map<string, bool> *categories)
+{
+ 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) {
+ if (categories && !categories->empty() && !categories->count(uiter->first))
+ continue;
+ const rgw_usage_data& usage = uiter->second;
+ formatter->open_object_section("entry");
+ formatter->dump_string("category", uiter->first);
+ formatter->dump_unsigned("bytes_sent", usage.bytes_sent);
+ formatter->dump_unsigned("bytes_received", usage.bytes_received);
+ formatter->dump_unsigned("ops", usage.ops);
+ formatter->dump_unsigned("successful_ops", usage.successful_ops);
+ formatter->close_section(); // entry
+ }
+ formatter->close_section(); // categories
+}
+
+int RGWUsage::show(const DoutPrefixProvider *dpp, rgw::sal::Driver* driver,
+ rgw::sal::User* user , rgw::sal::Bucket* bucket,
+ uint64_t start_epoch, uint64_t end_epoch, bool show_log_entries,
+ bool show_log_sum,
+ map<string, bool> *categories, RGWFormatterFlusher& flusher)
+{
+ uint32_t max_entries = 1000;
+
+ bool is_truncated = true;
+
+ RGWUsageIter usage_iter;
+ Formatter *formatter = flusher.get_formatter();
+
+ map<rgw_user_bucket, rgw_usage_log_entry> usage;
+
+ flusher.start(0);
+
+ formatter->open_object_section("usage");
+ if (show_log_entries) {
+ formatter->open_array_section("entries");
+ }
+ string last_owner;
+ bool user_section_open = false;
+ map<string, rgw_usage_log_entry> summary_map;
+ int ret;
+
+ while (is_truncated) {
+ if (bucket) {
+ ret = bucket->read_usage(dpp, start_epoch, end_epoch, max_entries, &is_truncated,
+ usage_iter, usage);
+ } else if (user) {
+ ret = user->read_usage(dpp, start_epoch, end_epoch, max_entries, &is_truncated,
+ usage_iter, usage);
+ } else {
+ ret = driver->read_all_usage(dpp, start_epoch, end_epoch, max_entries, &is_truncated,
+ usage_iter, usage);
+ }
+
+ if (ret == -ENOENT) {
+ ret = 0;
+ is_truncated = false;
+ }
+
+ if (ret < 0) {
+ return ret;
+ }
+
+ map<rgw_user_bucket, rgw_usage_log_entry>::iterator iter;
+ for (iter = usage.begin(); iter != usage.end(); ++iter) {
+ const rgw_user_bucket& ub = iter->first;
+ const rgw_usage_log_entry& entry = iter->second;
+
+ if (show_log_entries) {
+ if (ub.user.compare(last_owner) != 0) {
+ if (user_section_open) {
+ formatter->close_section();
+ formatter->close_section();
+ }
+ formatter->open_object_section("user");
+ formatter->dump_string("user", ub.user);
+ formatter->open_array_section("buckets");
+ user_section_open = true;
+ last_owner = ub.user;
+ }
+ formatter->open_object_section("bucket");
+ formatter->dump_string("bucket", ub.bucket);
+ utime_t ut(entry.epoch, 0);
+ ut.gmtime(formatter->dump_stream("time"));
+ formatter->dump_int("epoch", entry.epoch);
+ string owner = entry.owner.to_str();
+ string payer = entry.payer.to_str();
+ formatter->dump_string("owner", owner);
+ if (!payer.empty() && payer != owner) {
+ formatter->dump_string("payer", payer);
+ }
+ dump_usage_categories_info(formatter, entry, categories);
+ formatter->close_section(); // bucket
+ flusher.flush();
+ }
+
+ summary_map[ub.user].aggregate(entry, categories);
+ }
+ }
+ if (show_log_entries) {
+ if (user_section_open) {
+ formatter->close_section(); // buckets
+ formatter->close_section(); //user
+ }
+ formatter->close_section(); // entries
+ }
+
+ if (show_log_sum) {
+ formatter->open_array_section("summary");
+ map<string, rgw_usage_log_entry>::iterator siter;
+ for (siter = summary_map.begin(); siter != summary_map.end(); ++siter) {
+ const rgw_usage_log_entry& entry = siter->second;
+ formatter->open_object_section("user");
+ formatter->dump_string("user", siter->first);
+ dump_usage_categories_info(formatter, entry, categories);
+ rgw_usage_data total_usage;
+ entry.sum(total_usage, *categories);
+ formatter->open_object_section("total");
+ encode_json("bytes_sent", total_usage.bytes_sent, formatter);
+ encode_json("bytes_received", total_usage.bytes_received, formatter);
+ encode_json("ops", total_usage.ops, formatter);
+ encode_json("successful_ops", total_usage.successful_ops, formatter);
+ formatter->close_section(); // total
+
+ formatter->close_section(); // user
+
+ flusher.flush();
+ }
+
+ formatter->close_section(); // summary
+ }
+
+ formatter->close_section(); // usage
+ flusher.flush();
+
+ return 0;
+}
+
+int RGWUsage::trim(const DoutPrefixProvider *dpp, rgw::sal::Driver* driver,
+ rgw::sal::User* user , rgw::sal::Bucket* bucket,
+ uint64_t start_epoch, uint64_t end_epoch)
+{
+ if (bucket) {
+ return bucket->trim_usage(dpp, start_epoch, end_epoch);
+ } else if (user) {
+ return user->trim_usage(dpp, start_epoch, end_epoch);
+ } else {
+ return driver->trim_all_usage(dpp, start_epoch, end_epoch);
+ }
+}
+
+int RGWUsage::clear(const DoutPrefixProvider *dpp, rgw::sal::Driver* driver)
+{
+ return driver->clear_usage(dpp);
+}