uint64_t seq, const char *level,
const char *msg);
+/*
+ * This is not a doxygen comment leadin, because doxygen breaks on
+ * a typedef with function params and returns, and I can't figure out
+ * how to fix it.
+ *
+ * Monitor cluster log
+ *
+ * Monitor events logged to the cluster log. The callback get each
+ * log entry both as a single formatted line and with each field in a
+ * separate arg.
+ *
+ * Calling with a cb argument of NULL will deregister any previously
+ * registered callback.
+ *
+ * @param cluster cluster handle
+ * @param level minimum log level (debug, info, warn|warning, err|error)
+ * @param cb callback to run for each log message. It MUST NOT block
+ * nor call back into librados.
+ * @param arg void argument to pass to cb
+ *
+ * @returns 0 on success, negative code on error
+ */
+typedef void (*rados_log_callback2_t)(void *arg,
+ const char *line,
+ const char *who,
+ const char *name,
+ uint64_t sec, uint64_t nsec,
+ uint64_t seq, const char *level,
+ const char *msg);
+
CEPH_RADOS_API int rados_monitor_log(rados_t cluster, const char *level,
rados_log_callback_t cb, void *arg);
+CEPH_RADOS_API int rados_monitor_log2(rados_t cluster, const char *level,
+ rados_log_callback2_t cb, void *arg);
/** @} Mon/OSD/PG commands */
lock("librados::RadosClient::lock"),
timer(cct, lock),
refcnt(1),
- log_last_version(0), log_cb(NULL), log_cb_arg(NULL),
+ log_last_version(0), log_cb(NULL), log_cb2(NULL), log_cb_arg(NULL),
finisher(cct, "radosclient", "fn-radosclient")
{
}
return ret;
}
-int librados::RadosClient::monitor_log(const string& level, rados_log_callback_t cb, void *arg)
+int librados::RadosClient::monitor_log(const string& level,
+ rados_log_callback_t cb,
+ rados_log_callback2_t cb2,
+ void *arg)
{
Mutex::Locker l(lock);
return -ENOTCONN;
}
- if (cb == NULL) {
+ if (cb == NULL && cb2 == NULL) {
// stop watch
- ldout(cct, 10) << __func__ << " removing cb " << (void*)log_cb << dendl;
+ ldout(cct, 10) << __func__ << " removing cb " << (void*)log_cb
+ << " " << (void*)log_cb2 << dendl;
monclient.sub_unwant(log_watch);
log_watch.clear();
log_cb = NULL;
+ log_cb2 = NULL;
log_cb_arg = NULL;
return 0;
}
return -EINVAL;
}
- if (log_cb)
+ if (log_cb || log_cb2)
monclient.sub_unwant(log_watch);
// (re)start watch
- ldout(cct, 10) << __func__ << " add cb " << (void*)cb << " level " << level << dendl;
+ ldout(cct, 10) << __func__ << " add cb " << (void*)cb << " " << (void*)cb2
+ << " level " << level << dendl;
monclient.sub_want(watch_level, 0, 0);
monclient.renew_subs();
log_cb = cb;
+ log_cb2 = cb2;
log_cb_arg = arg;
log_watch = watch_level;
return 0;
if (log_last_version < m->version) {
log_last_version = m->version;
- if (log_cb) {
+ if (log_cb || log_cb2) {
for (std::deque<LogEntry>::iterator it = m->entries.begin(); it != m->entries.end(); ++it) {
LogEntry e = *it;
ostringstream ss;
ss << e.stamp << " " << e.name << " " << e.prio << " " << e.msg;
string line = ss.str();
string who = stringify(e.who);
+ string name = stringify(e.name);
string level = stringify(e.prio);
struct timespec stamp;
e.stamp.to_timespec(&stamp);
ldout(cct, 20) << __func__ << " delivering " << ss.str() << dendl;
- log_cb(log_cb_arg, line.c_str(), who.c_str(),
- stamp.tv_sec, stamp.tv_nsec,
- e.seq, level.c_str(), e.msg.c_str());
+ if (log_cb)
+ log_cb(log_cb_arg, line.c_str(), who.c_str(),
+ stamp.tv_sec, stamp.tv_nsec,
+ e.seq, level.c_str(), e.msg.c_str());
+ if (log_cb2)
+ log_cb2(log_cb_arg, line.c_str(), who.c_str(), name.c_str(),
+ stamp.tv_sec, stamp.tv_nsec,
+ e.seq, level.c_str(), e.msg.c_str());
}
}
version_t log_last_version;
rados_log_callback_t log_cb;
+ rados_log_callback2_t log_cb2;
void *log_cb_arg;
string log_watch;
bufferlist *poutbl, string *prs);
void handle_log(MLog *m);
- int monitor_log(const string& level, rados_log_callback_t cb, void *arg);
+ int monitor_log(const string& level, rados_log_callback_t cb,
+ rados_log_callback2_t cb2, void *arg);
void get();
bool put();
{
tracepoint(librados, rados_monitor_log_enter, cluster, level, cb, arg);
librados::RadosClient *client = (librados::RadosClient *)cluster;
- int retval = client->monitor_log(level, cb, arg);
+ int retval = client->monitor_log(level, cb, nullptr, arg);
tracepoint(librados, rados_monitor_log_exit, retval);
return retval;
}
+extern "C" int rados_monitor_log2(rados_t cluster, const char *level,
+ rados_log_callback2_t cb, void *arg)
+{
+ tracepoint(librados, rados_monitor_log2_enter, cluster, level, cb, arg);
+ librados::RadosClient *client = (librados::RadosClient *)cluster;
+ int retval = client->monitor_log(level, nullptr, cb, arg);
+ tracepoint(librados, rados_monitor_log2_exit, retval);
+ return retval;
+}
+
extern "C" int rados_ioctx_create(rados_t cluster, const char *name, rados_ioctx_t *io)
{
tracepoint(librados, rados_ioctx_create_enter, cluster, name);
)
)
+TRACEPOINT_EVENT(librados, rados_monitor_log2_enter,
+ TP_ARGS(
+ rados_t, cluster,
+ const char*, level,
+ rados_log_callback2_t, callback,
+ void*, arg),
+ TP_FIELDS(
+ ctf_integer_hex(rados_t, cluster, cluster)
+ ceph_ctf_string(level, level)
+ ctf_integer_hex(rados_log_callback2_t, callback, callback)
+ ctf_integer_hex(void*, arg, arg)
+ )
+)
+
+TRACEPOINT_EVENT(librados, rados_monitor_log2_exit,
+ TP_ARGS(
+ int, retval),
+ TP_FIELDS(
+ ctf_integer(int, retval, retval)
+ )
+)
+
TRACEPOINT_EVENT(librados, rados_ioctx_create_enter,
TP_ARGS(
rados_t, cluster,