#include <deque>
#include <ostream>
#include <string>
+#include <sstream>
#include <string_view>
#include <map>
#include <memory>
#include "msg/Message.h"
#include "msg/Messenger.h"
+#include "MDSTracer.h"
+
#include "common/debug.h"
#include "common/errno.h"
#include "common/perf_counters.h"
bool rdlock_authlock = (flags & MDS_TRAVERSE_RDLOCK_AUTHLOCK);
bool forimport = (flags & MDS_TRAVERSE_IMPORT);
+ // Trace child span: path traversal (duration captured automatically)
+ ScopedSpan trace_span(mds->tracer, "path_traverse", mdr ? mdr->trace_span : jspan_ptr(),
+ mdr ? &mdr->trace_data : nullptr);
+
if (forward)
ceph_assert(mdr); // forward requires a request
*/
CInode *MDCache::get_dentry_inode(CDentry *dn, const MDRequestRef& mdr, bool projected)
{
+ ScopedSpan trace_span(mds->tracer, "get_dentry_inode", mdr ? mdr->trace_span : jspan_ptr(), mdr ? &mdr->trace_data : nullptr);
CDentry::linkage_t *dnl;
if (projected)
dnl = dn->get_projected_linkage();
ceph_abort();
}
active_requests[mdr->reqid] = mdr;
+
+ // Initialize tracing for internal operations
+ if (mds->tracer.is_enabled()) {
+ const char* op_name = ceph_mds_op_name(op);
+ std::string trace_name = std::string("mds:internal:") + op_name;
+
+ mdr->trace_span = mds->tracer.start_trace(trace_name.c_str());
+
+
+ std::ostringstream reqid_ss;
+ reqid_ss << mdr->reqid;
+
+ if (mdr->trace_span && mdr->trace_span->IsRecording()) {
+ mdr->trace_span->SetAttribute(MDSTracer::ATTR_OP_TYPE, op);
+ mdr->trace_span->SetAttribute(MDSTracer::ATTR_OP_NAME, op_name);
+ mdr->trace_span->SetAttribute(MDSTracer::ATTR_MDS_RANK, static_cast<int64_t>(mds->get_nodeid()));
+ mdr->trace_span->SetAttribute(MDSTracer::ATTR_INTERNAL_OP, "true");
+ }
+ }
+
dout(7) << __func__ << " " << *mdr << " op " << op << dendl;
return mdr;
}
void MDCache::request_forward(const MDRequestRef& mdr, mds_rank_t who, int port)
{
+ ScopedSpan trace_span(mds->tracer, "request_forward", mdr->trace_span, &mdr->trace_data);
CachedStackStringStream css;
*css << "forwarding request to mds." << who;
mdr->mark_event(css->strv());
if (mds->logger)
log_stat();
+ // Finalize trace span and store in sliding window
+ if (mdr->trace_span && mdr->trace_span->IsRecording()) {
+ mdr->trace_span->AddEvent("request_cleanup");
+ mdr->trace_span->End();
+
+ // Complete trace_data and store in sliding window
+ if (!mdr->trace_data.trace_id.empty()) {
+ mdr->trace_data.end_time = ceph_clock_now();
+ mdr->trace_data.duration_ms = (mdr->trace_data.end_time - mdr->trace_data.start_time) * 1000.0;
+ mds->tracer.store_trace(mdr->trace_data);
+ }
+ }
+
mdr->mark_event("cleaned up request");
}
void MDCache::dispatch_fragment_dir(const MDRequestRef& mdr, bool abort_if_freezing)
{
+ ScopedSpan trace_span(mds->tracer, "fragment_dir", mdr->trace_span, &mdr->trace_data);
dirfrag_t basedirfrag = mdr->more()->fragment_base;
auto it = fragments.find(basedirfrag);
if (it == fragments.end() || it->second.mdr != mdr) {
void MDCache::enqueue_scrub_work(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "enqueue_scrub", mdr->trace_span, &mdr->trace_data);
CInode *in;
CF_MDS_RetryRequestFactory cf(this, mdr, true);
int r = path_traverse(mdr, cf, mdr->get_filepath(),
void MDCache::flush_dentry_work(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "flush_dentry", mdr->trace_span, &mdr->trace_data);
MutationImpl::LockOpVec lov;
CInode *in = mds->server->rdlock_path_pin_ref(mdr, true);
if (!in)
void MDCache::dispatch_quiesce_inode(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "quiesce_inode", mdr->trace_span, &mdr->trace_data);
if (mdr->internal_op_finish == nullptr) {
dout(20) << __func__ << " " << *mdr << " already finished quiesce" << dendl;
return;
void MDCache::dispatch_quiesce_path(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "quiesce_path", mdr->trace_span, &mdr->trace_data);
if (!mds->is_active()) {
dout(20) << __func__ << " is not active!" << dendl;
mds->server->respond_to_request(mdr, -EAGAIN);
void MDCache::dispatch_lock_path(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "lock_path", mdr->trace_span, &mdr->trace_data);
CF_MDS_RetryRequestFactory cf(this, mdr, true);
auto& lps = *static_cast<LockPathState*>(mdr->internal_op_private);
CInode* in = lps.in;
#include "include/compat.h"
#include "osd/OSDMap.h"
#include "fscrypt.h"
+#include "MDSTracer.h"
#include <list>
+#include <sstream>
#include <regex>
#include <string_view>
#include <functional>
MDRequestRef mdr;
void pre_finish(int r) override {
- if (mdr)
+ if (mdr) {
mdr->mark_event("journal_committed: ");
+ // End the pending journal_wait span (started in journal_and_reply)
+ if (mdr->journal_span_id != 0) {
+ mdr->trace_data.end_pending_span(mdr->journal_span_id);
+ mdr->journal_span_id = 0;
+ }
+ }
}
public:
explicit ServerLogContext(Server *s) : server(s) {
dout(10) << "journal_and_reply tracei " << in << " tracedn " << dn << dendl;
ceph_assert(!mdr->has_completed);
+ // Start pending span for async journal wait tracking
+ // This span will be completed in ServerLogContext::pre_finish when journal commits
+ if (!mdr->trace_data.trace_id.empty()) {
+ mdr->journal_span_id = mdr->trace_data.start_pending_span("journal_wait");
+ }
+
// note trace items for eventual reply.
mdr->tracei = in;
if (in)
*/
void Server::respond_to_request(const MDRequestRef& mdr, int r)
{
+ // Trace child span: respond to request (duration captured automatically)
+ ScopedSpan trace_span(mds->tracer, "respond", mdr->trace_span, &mdr->trace_data);
+ trace_span.SetAttribute(MDSTracer::ATTR_RESULT, static_cast<int64_t>(r));
+
mdr->result = r;
+ mdr->trace_data.result = r;
+
if (mdr->client_request) {
if (mdr->is_batch_head()) {
dout(20) << __func__ << ": batch head " << *mdr << dendl;
void Server::early_reply(const MDRequestRef& mdr, CInode *tracei, CDentry *tracedn)
{
+ // Trace child span: early reply (duration captured automatically)
+ ScopedSpan trace_span(mds->tracer, "early_reply", mdr->trace_span);
+
if (!g_conf()->mds_early_reply)
return;
return;
}
+ // Initialize tracing for this request
+ if (mds->tracer.is_enabled()) {
+ // Start or continue a trace
+ if (req->otel_trace.IsValid()) {
+ mdr->trace_span = mds->tracer.add_span("mds:client_request", req->otel_trace);
+ } else {
+ mdr->trace_span = mds->tracer.start_trace("mds:client_request");
+ }
+
+ // Set span attributes
+ const char* op_name = ceph_mds_op_name(req->get_op());
+ std::ostringstream reqid_ss;
+ reqid_ss << req->get_reqid();
+ std::string reqid_str = reqid_ss.str();
+
+ mdr->trace_span->SetAttribute(MDSTracer::ATTR_OP_TYPE, req->get_op());
+ mdr->trace_span->SetAttribute(MDSTracer::ATTR_OP_NAME, op_name);
+ mdr->trace_span->SetAttribute(MDSTracer::ATTR_REQID, reqid_str);
+ mdr->trace_span->SetAttribute(MDSTracer::ATTR_MDS_RANK, static_cast<int64_t>(mds->get_nodeid()));
+
+ if (!req->get_filepath().empty()) {
+ std::string path = req->get_filepath().get_path();
+ mdr->trace_span->SetAttribute(MDSTracer::ATTR_PATH, path);
+ }
+
+ if (req->get_source().is_client()) {
+ mdr->trace_span->SetAttribute(MDSTracer::ATTR_CLIENT_ID,
+ static_cast<int64_t>(req->get_source().num()));
+ }
+
+ // Populate trace_data for sliding window storage
+ mdr->trace_data.trace_id = MDSTracer::get_trace_id(mdr->trace_span);
+ mdr->trace_data.name = "mds:client_request";
+ mdr->trace_data.start_time = ceph_clock_now();
+ mdr->trace_data.attributes[MDSTracer::ATTR_OP_TYPE] = std::to_string(req->get_op());
+ mdr->trace_data.attributes[MDSTracer::ATTR_OP_NAME] = op_name;
+ mdr->trace_data.attributes[MDSTracer::ATTR_REQID] = reqid_str;
+ mdr->trace_data.attributes[MDSTracer::ATTR_MDS_RANK] = std::to_string(mds->get_nodeid());
+ if (!req->get_filepath().empty()) {
+ mdr->trace_data.attributes[MDSTracer::ATTR_PATH] = req->get_filepath().get_path();
+ }
+ if (req->get_source().is_client()) {
+ mdr->trace_data.attributes[MDSTracer::ATTR_CLIENT_ID] =
+ std::to_string(req->get_source().num());
+ }
+ }
+
if (session) {
mdr->session = session;
session->requests.push_back(&mdr->item_session_request);
// we shouldn't be waiting on anyone.
ceph_assert(!mdr->has_more() || mdr->more()->waiting_on_peer.empty());
+ // Trace event: request dispatch
+ if (mdr->trace_span && mdr->trace_span->IsRecording()) {
+ mdr->trace_span->AddEvent("dispatch");
+ }
+
if (mdr->killed) {
// Should already be reset in request_cleanup().
ceph_assert(!mdr->is_batch_head());
CDentry* Server::prepare_stray_dentry(const MDRequestRef& mdr, CInode *in)
{
+ ScopedSpan trace_span(mds->tracer, "prepare_stray_dentry", mdr->trace_span, &mdr->trace_data);
string straydname;
in->name_stray_dentry(straydname);
CInode* Server::prepare_new_inode(const MDRequestRef& mdr, CDir *dir, inodeno_t useino, unsigned mode,
const file_layout_t *layout, bool referent_inode)
{
+ ScopedSpan trace_span(mds->tracer, "prepare_new_inode", mdr->trace_span, &mdr->trace_data);
CInode *in = new CInode(mdcache);
auto _inode = in->_get_inode();
bool want_auth,
bool no_want_auth)
{
+ ScopedSpan trace_span(mds->tracer, "rdlock_path_pin_ref", mdr->trace_span, &mdr->trace_data);
dout(10) << "rdlock_path_pin_ref " << *mdr << " " << refpath << dendl;
if (mdr->locking_state & MutationImpl::PATH_LOCKED)
bool create, bool okexist, bool authexist,
bool want_layout)
{
+ ScopedSpan trace_span(mds->tracer, "rdlock_path_xlock_dentry", mdr->trace_span, &mdr->trace_data);
const filepath& refpath = mdr->get_filepath();
dout(10) << "rdlock_path_xlock_dentry " << *mdr << " " << refpath << dendl;
void Server::handle_client_getattr(const MDRequestRef& mdr, bool is_lookup)
{
+ ScopedSpan trace_span(mds->tracer, is_lookup ? "handle_lookup" : "handle_getattr", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
client_t client = mdr->get_client();
void Server::handle_client_lookup_ino(const MDRequestRef& mdr,
bool want_parent, bool want_dentry)
{
+ ScopedSpan trace_span(mds->tracer, "handle_lookup_ino", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
if ((uint64_t)req->head.args.lookupino.snapid > 0)
void Server::handle_client_open(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_open", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
dout(7) << "open on " << req->get_filepath() << dendl;
void Server::handle_client_openc(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_create", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
client_t client = mdr->get_client();
void Server::handle_client_readdir(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_readdir", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
Session *session = mds->get_session(req);
client_t client = req->get_source().num();
void Server::handle_client_file_setlock(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_file_setlock", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
MutationImpl::LockOpVec lov;
void Server::handle_client_file_readlock(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_file_readlock", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
MutationImpl::LockOpVec lov;
void Server::handle_client_setattr(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_setattr", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
MutationImpl::LockOpVec lov;
CInode *cur = rdlock_path_pin_ref(mdr, true);
/* This function cleans up the passed mdr */
void Server::handle_client_setlayout(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_setlayout", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
CInode *cur = rdlock_path_pin_ref(mdr, true);
if (!cur) return;
void Server::handle_client_setdirlayout(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_setdirlayout", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
// can't use rdlock_path_pin_ref because we need to xlock snaplock/policylock
void Server::handle_client_setvxattr(const MDRequestRef& mdr, CInode *cur)
{
+ ScopedSpan trace_span(mds->tracer, "handle_setvxattr", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
bool is_rmxattr = (req->get_op() == CEPH_MDS_OP_RMXATTR);
MutationImpl::LockOpVec lov;
void Server::handle_client_setxattr(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_setxattr", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
string name(req->get_path2());
void Server::handle_client_removexattr(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_removexattr", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
std::string name(req->get_path2());
void Server::handle_client_getvxattr(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_getvxattr", mdr->trace_span, &mdr->trace_data);
const auto& req = mdr->client_request;
string xattr_name{req->get_path2()};
void Server::handle_client_mknod(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_mknod", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
client_t client = mdr->get_client();
// MKDIR
void Server::handle_client_mkdir(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_mkdir", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
mdr->disable_lock_cache();
void Server::handle_client_symlink(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_symlink", mdr->trace_span, &mdr->trace_data);
const auto& req = mdr->client_request;
mdr->disable_lock_cache();
void Server::handle_client_link(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_link", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
dout(7) << "handle_client_link " << req->get_filepath()
void Server::handle_client_unlink(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_unlink", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
client_t client = mdr->get_client();
*/
void Server::handle_client_rename(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_rename", mdr->trace_span, &mdr->trace_data);
const auto& req = mdr->client_request;
dout(7) << "handle_client_rename " << *req << dendl;
// snaps
void Server::handle_client_lssnap(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_lssnap", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
// traverse to path
void Server::handle_client_mksnap(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_mksnap", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
// make sure we have as new a map as the client
if (req->get_mdsmap_epoch() > mds->mdsmap->get_epoch()) {
void Server::handle_client_rmsnap(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_rmsnap", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
CInode *diri = try_get_auth_inode(mdr, req->get_filepath().get_ino());
void Server::handle_client_renamesnap(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_renamesnap", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest> &req = mdr->client_request;
if (req->get_filepath().get_ino() != req->get_filepath2().get_ino()) {
respond_to_request(mdr, -EINVAL);
void Server::handle_client_file_blockdiff(const MDRequestRef& mdr)
{
+ ScopedSpan trace_span(mds->tracer, "handle_file_blockdiff", mdr->trace_span, &mdr->trace_data);
const cref_t<MClientRequest>& req = mdr->client_request;
dout(10) << __func__ << dendl;