From: Venky Shankar Date: Thu, 17 Jan 2019 06:52:46 +0000 (-0500) Subject: client: new message type for providing client side metrics X-Git-Tag: v16.1.0~2176^2~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c669de12e076bcedf3fe6cfe52377713f06d7ceb;p=ceph.git client: new message type for providing client side metrics Signed-off-by: Venky Shankar --- diff --git a/alpine/APKBUILD.in b/alpine/APKBUILD.in index a9a9a58ecfc..7b04393eddd 100644 --- a/alpine/APKBUILD.in +++ b/alpine/APKBUILD.in @@ -396,7 +396,7 @@ libcephfs_dev() { pkgdesc="Ceph distributed file system client library headers" depends="libcephfs librados-devel" - _pkg $_includedir/cephfs ceph_ll_client.h libcephfs.h + _pkg $_includedir/cephfs ceph_ll_client.h libcephfs.h metrics/Types.h _pkg $_libdir libcephfs.so } diff --git a/ceph.spec.in b/ceph.spec.in index eda4c6a8da7..2ab2042ff9b 100644 --- a/ceph.spec.in +++ b/ceph.spec.in @@ -2186,6 +2186,7 @@ fi %dir %{_includedir}/cephfs %{_includedir}/cephfs/libcephfs.h %{_includedir}/cephfs/ceph_ll_client.h +%{_includedir}/cephfs/metrics/Types.h %{_libdir}/libcephfs.so %files -n python%{python3_pkgversion}-cephfs diff --git a/debian/libcephfs-dev.install b/debian/libcephfs-dev.install index fbc1e4b95ff..e06363ad700 100644 --- a/debian/libcephfs-dev.install +++ b/debian/libcephfs-dev.install @@ -1,3 +1,4 @@ usr/include/cephfs/ceph_ll_client.h usr/include/cephfs/libcephfs.h +usr/include/cephfs/metrics/Types.h usr/lib/libcephfs.so diff --git a/src/include/ceph_fs.h b/src/include/ceph_fs.h index b01b09adda5..d8ae8271e2f 100644 --- a/src/include/ceph_fs.h +++ b/src/include/ceph_fs.h @@ -151,6 +151,7 @@ extern const char *ceph_con_mode_name(int con_mode); #define CEPH_MSG_CLIENT_REPLY 26 #define CEPH_MSG_CLIENT_RECLAIM 27 #define CEPH_MSG_CLIENT_RECLAIM_REPLY 28 +#define CEPH_MSG_CLIENT_METRICS 29 #define CEPH_MSG_CLIENT_CAPS 0x310 #define CEPH_MSG_CLIENT_LEASE 0x311 #define CEPH_MSG_CLIENT_SNAP 0x312 diff --git a/src/include/cephfs/metrics/Types.h b/src/include/cephfs/metrics/Types.h new file mode 100644 index 00000000000..01f4d7ed087 --- /dev/null +++ b/src/include/cephfs/metrics/Types.h @@ -0,0 +1,284 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_INCLUDE_CEPHFS_METRICS_TYPES_H +#define CEPH_INCLUDE_CEPHFS_METRICS_TYPES_H + +#include +#include + +#include "common/Formatter.h" +#include "include/buffer_fwd.h" +#include "include/encoding.h" +#include "include/int_types.h" +#include "include/stringify.h" +#include "include/utime.h" + +namespace ceph { class Formatter; } + +enum ClientMetricType { + CLIENT_METRIC_TYPE_CAP_INFO, + CLIENT_METRIC_TYPE_READ_LATENCY, + CLIENT_METRIC_TYPE_WRITE_LATENCY, + CLIENT_METRIC_TYPE_METADATA_LATENCY, +}; +inline std::ostream &operator<<(std::ostream &os, const ClientMetricType &type) { + switch(type) { + case ClientMetricType::CLIENT_METRIC_TYPE_CAP_INFO: + os << "CAP_INFO"; + break; + case ClientMetricType::CLIENT_METRIC_TYPE_READ_LATENCY: + os << "READ_LATENCY"; + break; + case ClientMetricType::CLIENT_METRIC_TYPE_WRITE_LATENCY: + os << "WRITE_LATENCY"; + break; + case ClientMetricType::CLIENT_METRIC_TYPE_METADATA_LATENCY: + os << "METADATA_LATENCY"; + break; + default: + ceph_abort(); + } + + return os; +} + +struct CapInfoPayload { + static const ClientMetricType METRIC_TYPE = ClientMetricType::CLIENT_METRIC_TYPE_CAP_INFO; + + uint64_t cap_hits = 0; + uint64_t cap_misses = 0; + uint64_t nr_caps = 0; + + CapInfoPayload() { } + CapInfoPayload(uint64_t cap_hits, uint64_t cap_misses, uint64_t nr_caps) + : cap_hits(cap_hits), cap_misses(cap_misses), nr_caps(nr_caps) { + } + + void encode(bufferlist &bl) const { + using ceph::encode; + ENCODE_START(1, 1, bl); + encode(cap_hits, bl); + encode(cap_misses, bl); + encode(nr_caps, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator &iter) { + using ceph::decode; + DECODE_START(1, iter); + decode(cap_hits, iter); + decode(cap_misses, iter); + decode(nr_caps, iter); + DECODE_FINISH(iter); + } + + void dump(Formatter *f) const { + f->dump_int("cap_hits", cap_hits); + f->dump_int("cap_misses", cap_misses); + f->dump_int("num_caps", nr_caps); + } +}; + +struct ReadLatencyPayload { + static const ClientMetricType METRIC_TYPE = ClientMetricType::CLIENT_METRIC_TYPE_READ_LATENCY; + + utime_t lat; + + ReadLatencyPayload() { } + ReadLatencyPayload(utime_t lat) + : lat(lat) { + } + + void encode(bufferlist &bl) const { + using ceph::encode; + ENCODE_START(1, 1, bl); + encode(lat, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator &iter) { + using ceph::decode; + DECODE_START(1, iter); + decode(lat, iter); + DECODE_FINISH(iter); + } + + void dump(Formatter *f) const { + f->dump_int("latency", lat); + } +}; + +struct WriteLatencyPayload { + static const ClientMetricType METRIC_TYPE = ClientMetricType::CLIENT_METRIC_TYPE_WRITE_LATENCY; + + utime_t lat; + + WriteLatencyPayload() { } + WriteLatencyPayload(utime_t lat) + : lat(lat) { + } + + void encode(bufferlist &bl) const { + using ceph::encode; + ENCODE_START(1, 1, bl); + encode(lat, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator &iter) { + using ceph::decode; + DECODE_START(1, iter); + decode(lat, iter); + DECODE_FINISH(iter); + } + + void dump(Formatter *f) const { + f->dump_int("latency", lat); + } +}; + +struct MetadataLatencyPayload { + static const ClientMetricType METRIC_TYPE = ClientMetricType::CLIENT_METRIC_TYPE_METADATA_LATENCY; + + utime_t lat; + + MetadataLatencyPayload() { } + MetadataLatencyPayload(utime_t lat) + : lat(lat) { + } + + void encode(bufferlist &bl) const { + using ceph::encode; + ENCODE_START(1, 1, bl); + encode(lat, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator &iter) { + using ceph::decode; + DECODE_START(1, iter); + decode(lat, iter); + DECODE_FINISH(iter); + } + + void dump(Formatter *f) const { + f->dump_int("latency", lat); + } +}; + +struct UnknownPayload { + static const ClientMetricType METRIC_TYPE = static_cast(-1); + + UnknownPayload() { } + + void encode(bufferlist &bl) const { + } + + void decode(bufferlist::const_iterator &iter) { + } + + void dump(Formatter *f) const { + } +}; + +typedef boost::variant ClientMetricPayload; + +// metric update message sent by clients +struct ClientMetricMessage { +public: + ClientMetricMessage(const ClientMetricPayload &payload = UnknownPayload()) + : payload(payload) { + } + + class EncodePayloadVisitor : public boost::static_visitor { + public: + explicit EncodePayloadVisitor(bufferlist &bl) : m_bl(bl) { + } + + template + inline void operator()(const ClientMetricPayload &payload) const { + using ceph::encode; + encode(static_cast(ClientMetricPayload::METRIC_TYPE), m_bl); + payload.encode(m_bl); + } + + private: + bufferlist &m_bl; + }; + + class DecodePayloadVisitor : public boost::static_visitor { + public: + DecodePayloadVisitor(bufferlist::const_iterator &iter) : m_iter(iter) { + } + + template + inline void operator()(ClientMetricPayload &payload) const { + using ceph::decode; + payload.decode(m_iter); + } + + private: + bufferlist::const_iterator &m_iter; + }; + + class DumpPayloadVisitor : public boost::static_visitor { + public: + explicit DumpPayloadVisitor(Formatter *formatter) : m_formatter(formatter) { + } + + template + inline void operator()(const ClientMetricPayload &payload) const { + ClientMetricType metric_type = ClientMetricPayload::METRIC_TYPE; + m_formatter->dump_string("client_metric_type", stringify(metric_type)); + payload.dump(m_formatter); + } + + private: + Formatter *m_formatter; + }; + + void encode(bufferlist &bl) const { + boost::apply_visitor(EncodePayloadVisitor(bl), payload); + } + + void decode(bufferlist::const_iterator &iter) { + using ceph::decode; + + uint32_t metric_type; + decode(metric_type, iter); + + switch (metric_type) { + case ClientMetricType::CLIENT_METRIC_TYPE_CAP_INFO: + payload = CapInfoPayload(); + break; + case ClientMetricType::CLIENT_METRIC_TYPE_READ_LATENCY: + payload = ReadLatencyPayload(); + break; + case ClientMetricType::CLIENT_METRIC_TYPE_WRITE_LATENCY: + payload = WriteLatencyPayload(); + break; + case ClientMetricType::CLIENT_METRIC_TYPE_METADATA_LATENCY: + payload = MetadataLatencyPayload(); + break; + default: + payload = UnknownPayload(); + break; + } + + boost::apply_visitor(DecodePayloadVisitor(iter), payload); + } + + void dump(Formatter *f) const { + apply_visitor(DumpPayloadVisitor(f), payload); + } + + ClientMetricPayload payload; +}; +WRITE_CLASS_ENCODER(ClientMetricMessage); + +#endif // CEPH_INCLUDE_CEPHFS_METRICS_TYPES_H diff --git a/src/messages/MClientMetrics.h b/src/messages/MClientMetrics.h new file mode 100644 index 00000000000..c348586ed89 --- /dev/null +++ b/src/messages/MClientMetrics.h @@ -0,0 +1,51 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_MDS_CLIENT_METRICS_H +#define CEPH_MDS_CLIENT_METRICS_H + +#include + +#include "msg/Message.h" +#include "include/cephfs/metrics/Types.h" + +class MClientMetrics : public SafeMessage { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; +public: + std::vector updates; + +protected: + MClientMetrics() : MClientMetrics(std::vector{}) { } + MClientMetrics(std::vector updates) + : SafeMessage(CEPH_MSG_CLIENT_METRICS, HEAD_VERSION, COMPAT_VERSION), updates(updates) { + } + ~MClientMetrics() { } + +public: + std::string_view get_type_name() const override { + return "client_metrics"; + } + + void print(ostream &out) const override { + out << "client_metrics"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(updates, payload); + } + + void decode_payload() override { + using ceph::decode; + auto iter = payload.cbegin(); + decode(updates, iter); + } + +private: + template + friend boost::intrusive_ptr ceph::make_message(Args&&... args); +}; + +#endif // CEPH_MDS_CLIENT_METRICS_H diff --git a/src/msg/Message.cc b/src/msg/Message.cc index 27ef95d9db0..6ca3cd492af 100644 --- a/src/msg/Message.cc +++ b/src/msg/Message.cc @@ -128,6 +128,7 @@ #include "messages/MClientLease.h" #include "messages/MClientSnap.h" #include "messages/MClientQuota.h" +#include "messages/MClientMetrics.h" #include "messages/MMDSSlaveRequest.h" @@ -682,6 +683,9 @@ Message *decode_message(CephContext *cct, case CEPH_MSG_CLIENT_QUOTA: m = make_message(); break; + case CEPH_MSG_CLIENT_METRICS: + m = make_message(); + break; // mds case MSG_MDS_SLAVE_REQUEST: