rgw-admin: command to list sync error logs

$ radosgw-admin sync error list

Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
This commit is contained in:
Yehuda Sadeh 2016-02-15 17:04:05 -08:00
parent 288501429e
commit 10cda14b51
5 changed files with 127 additions and 65 deletions

View File

@ -26,7 +26,7 @@
#include "rgw_rados.h"
#include "rgw_acl.h"
#include "rgw_acl_s3.h"
#include "rgw_log.h"
#include "rgw_formats.h"
#include "rgw_usage.h"
#include "rgw_replica_log.h"
@ -333,6 +333,7 @@ enum {
OPT_MDLOG_TRIM,
OPT_MDLOG_FETCH,
OPT_MDLOG_STATUS,
OPT_SYNC_ERROR_LIST,
OPT_BILOG_LIST,
OPT_BILOG_TRIM,
OPT_DATA_SYNC_STATUS,
@ -381,6 +382,7 @@ static int get_cmd(const char *cmd, const char *prev_cmd, const char *prev_prev_
strcmp(cmd, "caps") == 0 ||
strcmp(cmd, "data") == 0 ||
strcmp(cmd, "datalog") == 0 ||
strcmp(cmd, "error") == 0 ||
strcmp(cmd, "gc") == 0 ||
strcmp(cmd, "key") == 0 ||
strcmp(cmd, "log") == 0 ||
@ -401,6 +403,7 @@ static int get_cmd(const char *cmd, const char *prev_cmd, const char *prev_prev_
strcmp(cmd, "regionmap") == 0 ||
strcmp(cmd, "replicalog") == 0 ||
strcmp(cmd, "subuser") == 0 ||
strcmp(cmd, "sync") == 0 ||
strcmp(cmd, "temp") == 0 ||
strcmp(cmd, "usage") == 0 ||
strcmp(cmd, "user") == 0 ||
@ -664,6 +667,10 @@ static int get_cmd(const char *cmd, const char *prev_cmd, const char *prev_prev_
return OPT_METADATA_SYNC_INIT;
if (strcmp(cmd, "run") == 0)
return OPT_METADATA_SYNC_RUN;
} else if ((prev_prev_cmd && strcmp(prev_prev_cmd, "sync") == 0) &&
(strcmp(prev_cmd, "error") == 0)) {
if (strcmp(cmd, "list") == 0)
return OPT_SYNC_ERROR_LIST;
} else if (strcmp(prev_cmd, "mdlog") == 0) {
if (strcmp(cmd, "list") == 0)
return OPT_MDLOG_LIST;
@ -4731,41 +4738,78 @@ next:
}
}
if (opt_cmd == OPT_BILOG_LIST) {
if (bucket_name.empty()) {
cerr << "ERROR: bucket not specified" << std::endl;
return -EINVAL;
}
RGWBucketInfo bucket_info;
int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
if (ret < 0) {
cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
return -ret;
}
formatter->open_array_section("entries");
bool truncated;
int count = 0;
if (max_entries < 0)
if (opt_cmd == OPT_SYNC_ERROR_LIST) {
if (max_entries < 0) {
max_entries = 1000;
}
do {
list<rgw_bi_log_entry> entries;
ret = store->list_bi_log_entries(bucket, shard_id, marker, max_entries - count, entries, &truncated);
if (ret < 0) {
cerr << "ERROR: list_bi_log_entries(): " << cpp_strerror(-ret) << std::endl;
return -ret;
bool truncated;
utime_t start_time, end_time;
int ret = parse_date_str(start_date, start_time);
if (ret < 0)
return -ret;
ret = parse_date_str(end_date, end_time);
if (ret < 0)
return -ret;
if (shard_id < 0) {
shard_id = 0;
}
formatter->open_array_section("entries");
for (; shard_id < ERROR_LOGGER_SHARDS; ++shard_id) {
formatter->open_object_section("shard");
encode_json("shard_id", shard_id, formatter);
formatter->open_array_section("entries");
int count = 0;
string oid = RGWSyncErrorLogger::get_shard_oid(RGW_SYNC_ERROR_LOG_SHARD_PREFIX, shard_id);
do {
list<cls_log_entry> entries;
ret = store->time_log_list(oid, start_time, end_time, max_entries - count, entries,
marker, &marker, &truncated);
if (ret == -ENOENT) {
break;
}
if (ret < 0) {
cerr << "ERROR: store->time_log_list(): " << cpp_strerror(-ret) << std::endl;
return -ret;
}
count += entries.size();
for (auto& cls_entry : entries) {
rgw_sync_error_info log_entry;
auto iter = cls_entry.data.begin();
try {
::decode(log_entry, iter);
} catch (buffer::error& err) {
cerr << "ERROR: failed to decode log entry" << std::endl;
continue;
}
formatter->open_object_section("entry");
encode_json("id", cls_entry.id, formatter);
encode_json("section", cls_entry.section, formatter);
encode_json("name", cls_entry.name, formatter);
encode_json("timestamp", cls_entry.timestamp, formatter);
encode_json("info", log_entry, formatter);
formatter->close_section();
formatter->flush(cout);
}
} while (truncated && count < max_entries);
formatter->close_section();
formatter->close_section();
if (specified_shard_id) {
break;
}
count += entries.size();
for (list<rgw_bi_log_entry>::iterator iter = entries.begin(); iter != entries.end(); ++iter) {
rgw_bi_log_entry& entry = *iter;
encode_json("entry", entry, formatter);
marker = entry.id;
}
formatter->flush(cout);
} while (truncated && count < max_entries);
}
formatter->close_section();
formatter->flush(cout);

View File

@ -684,7 +684,8 @@ public:
sync_status = retcode;
if (sync_status < 0) {
yield call(sync_env->error_logger->log_error_cr("data", bucket_name + ":" + bucket_instance, -sync_status, string("failed to sync bucket instance: ") + cpp_strerror(-sync_status)));
yield call(sync_env->error_logger->log_error_cr(sync_env->conn->get_remote_id(), "data", bucket_name + ":" + bucket_instance,
-sync_status, string("failed to sync bucket instance: ") + cpp_strerror(-sync_status)));
}
#warning what do do in case of error
if (!entry_marker.empty()) {

View File

@ -11,6 +11,7 @@
#include "rgw_keystone.h"
#include "rgw_basic_types.h"
#include "rgw_op.h"
#include "rgw_sync.h"
#include "common/ceph_json.h"
#include "common/Formatter.h"
@ -1189,3 +1190,9 @@ void rgw_meta_sync_status::dump(Formatter *f) const {
encode_json("info", sync_info, f);
encode_json("markers", sync_markers, f);
}
void rgw_sync_error_info::dump(Formatter *f) const {
encode_json("source_zone", source_zone, f);
encode_json("error_code", error_code, f);
encode_json("message", message, f);
}

View File

@ -25,42 +25,21 @@ static string mdlog_sync_status_oid = "mdlog.sync-status";
static string mdlog_sync_status_shard_prefix = "mdlog.sync-status.shard";
static string mdlog_sync_full_sync_index_prefix = "meta.full-sync.index";
struct rgw_sync_error_info {
uint32_t error_code;
string message;
rgw_sync_error_info() : error_code(0) {}
rgw_sync_error_info(uint32_t _error_code, const string& _message) : error_code(_error_code), message(_message) {}
void encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);
::encode(error_code, bl);
::encode(message, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::iterator& bl) {
DECODE_START(1, bl);
::decode(error_code, bl);
::decode(message, bl);
DECODE_FINISH(bl);
}
};
WRITE_CLASS_ENCODER(rgw_sync_error_info)
RGWSyncErrorLogger::RGWSyncErrorLogger(RGWRados *_store, const string oid_prefix, int _num_shards) : store(_store), num_shards(_num_shards) {
char buf[oid_prefix.size() + 16];
for (int i = 0; i < num_shards; i++) {
snprintf(buf, sizeof(buf), "%s.%d", oid_prefix.c_str(), i);
oids.push_back(buf);
oids.push_back(get_shard_oid(oid_prefix, i));
}
}
string RGWSyncErrorLogger::get_shard_oid(const string& oid_prefix, int shard_id) {
char buf[oid_prefix.size() + 16];
snprintf(buf, sizeof(buf), "%s.%d", oid_prefix.c_str(), shard_id);
return string(buf);
}
RGWCoroutine *RGWSyncErrorLogger::log_error_cr(const string& section, const string& name, uint32_t error_code, const string& message) {
RGWCoroutine *RGWSyncErrorLogger::log_error_cr(const string& source_zone, const string& section, const string& name, uint32_t error_code, const string& message) {
cls_log_entry entry;
rgw_sync_error_info info(error_code, message);
rgw_sync_error_info info(source_zone, error_code, message);
bufferlist bl;
::encode(info, bl);
store->time_log_prepare_entry(entry, ceph_clock_now(store->ctx()), section, name, bl);
@ -1082,7 +1061,8 @@ int RGWMetaSyncSingleEntryCR::operate() {
if (sync_status < 0) {
ldout(sync_env->cct, 10) << *this << ": failed to send read remote metadata entry: section=" << section << " key=" << key << " status=" << sync_status << dendl;
log_error() << "failed to send read remote metadata entry: section=" << section << " key=" << key << " status=" << sync_status << std::endl;
yield call(sync_env->error_logger->log_error_cr(section, key, -sync_status, string("failed to read remote metadata entry: ") + cpp_strerror(-sync_status)));
yield call(sync_env->error_logger->log_error_cr(sync_env->conn->get_remote_id(), section, key, -sync_status,
string("failed to read remote metadata entry: ") + cpp_strerror(-sync_status)));
return set_cr_error(sync_status);
}

View File

@ -33,9 +33,39 @@ class RGWSyncErrorLogger {
atomic_t counter;
public:
RGWSyncErrorLogger(RGWRados *_store, const string oid_prefix, int _num_shards);
RGWCoroutine *log_error_cr(const string& section, const string& name, uint32_t error_code, const string& message);
RGWCoroutine *log_error_cr(const string& source_zone, const string& section, const string& name, uint32_t error_code, const string& message);
static string get_shard_oid(const string& oid_prefix, int shard_id);
};
struct rgw_sync_error_info {
string source_zone;
uint32_t error_code;
string message;
rgw_sync_error_info() : error_code(0) {}
rgw_sync_error_info(const string& _source_zone, uint32_t _error_code, const string& _message) : source_zone(_source_zone), error_code(_error_code), message(_message) {}
void encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);
::encode(source_zone, bl);
::encode(error_code, bl);
::encode(message, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::iterator& bl) {
DECODE_START(1, bl);
::decode(source_zone, bl);
::decode(error_code, bl);
::decode(message, bl);
DECODE_FINISH(bl);
}
void dump(Formatter *f) const;
};
WRITE_CLASS_ENCODER(rgw_sync_error_info)
#define DEFAULT_BACKOFF_MAX 30
class RGWSyncBackoff {