Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc / deps / grpc / src / core / lib / channel / channelz.h
diff --git a/legacy-libs/grpc/deps/grpc/src/core/lib/channel/channelz.h b/legacy-libs/grpc/deps/grpc/src/core/lib/channel/channelz.h
new file mode 100644 (file)
index 0000000..b023a52
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_CHANNEL_CHANNELZ_H
+#define GRPC_CORE_LIB_CHANNEL_CHANNELZ_H
+
+#include <grpc/impl/codegen/port_platform.h>
+
+#include <grpc/grpc.h>
+
+#include "src/core/lib/channel/channel_trace.h"
+#include "src/core/lib/gpr/time_precise.h"
+#include "src/core/lib/gprpp/inlined_vector.h"
+#include "src/core/lib/gprpp/manual_constructor.h"
+#include "src/core/lib/gprpp/map.h"
+#include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/gprpp/sync.h"
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/json/json.h"
+
+// Channel arg key for channelz node.
+#define GRPC_ARG_CHANNELZ_CHANNEL_NODE "grpc.channelz_channel_node"
+
+// Channel arg key to encode the channelz uuid of the channel's parent.
+#define GRPC_ARG_CHANNELZ_PARENT_UUID "grpc.channelz_parent_uuid"
+
+/** This is the default value for whether or not to enable channelz. If
+ * GRPC_ARG_ENABLE_CHANNELZ is set, it will override this default value. */
+#define GRPC_ENABLE_CHANNELZ_DEFAULT true
+
+/** This is the default value for the maximum amount of memory used by trace
+ * events per channel trace node. If
+ * GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE is set, it will override
+ * this default value. */
+#define GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT 1024 * 4
+
+namespace grpc_core {
+
+namespace channelz {
+
+// Helpers for getting and setting GRPC_ARG_CHANNELZ_PARENT_UUID.
+grpc_arg MakeParentUuidArg(intptr_t parent_uuid);
+intptr_t GetParentUuidFromArgs(const grpc_channel_args& args);
+
+class SocketNode;
+class ListenSocketNode;
+
+namespace testing {
+class CallCountingHelperPeer;
+class ChannelNodePeer;
+}  // namespace testing
+
+// base class for all channelz entities
+class BaseNode : public RefCounted<BaseNode> {
+ public:
+  // There are only four high level channelz entities. However, to support
+  // GetTopChannelsRequest, we split the Channel entity into two different
+  // types. All children of BaseNode must be one of these types.
+  enum class EntityType {
+    kTopLevelChannel,
+    kInternalChannel,
+    kSubchannel,
+    kServer,
+    kSocket,
+  };
+
+ protected:
+  BaseNode(EntityType type, UniquePtr<char> name);
+
+ public:
+  virtual ~BaseNode();
+
+  // All children must implement this function.
+  virtual grpc_json* RenderJson() GRPC_ABSTRACT;
+
+  // Renders the json and returns allocated string that must be freed by the
+  // caller.
+  char* RenderJsonString();
+
+  EntityType type() const { return type_; }
+  intptr_t uuid() const { return uuid_; }
+  const char* name() const { return name_.get(); }
+
+ private:
+  // to allow the ChannelzRegistry to set uuid_ under its lock.
+  friend class ChannelzRegistry;
+  const EntityType type_;
+  intptr_t uuid_;
+  UniquePtr<char> name_;
+};
+
+// This class is a helper class for channelz entities that deal with Channels,
+// Subchannels, and Servers, since those have similar proto definitions.
+// This class has the ability to:
+//   - track calls_{started,succeeded,failed}
+//   - track last_call_started_timestamp
+//   - perform rendering of the above items
+class CallCountingHelper {
+ public:
+  CallCountingHelper();
+
+  void RecordCallStarted();
+  void RecordCallFailed();
+  void RecordCallSucceeded();
+
+  // Common rendering of the call count data and last_call_started_timestamp.
+  void PopulateCallCounts(grpc_json* json);
+
+ private:
+  // testing peer friend.
+  friend class testing::CallCountingHelperPeer;
+
+  // TODO(soheil): add a proper PerCPU helper and use it here.
+  struct AtomicCounterData {
+    // Define the ctors so that we can use this structure in InlinedVector.
+    AtomicCounterData() = default;
+    AtomicCounterData(const AtomicCounterData& that)
+        : calls_started(that.calls_started.Load(MemoryOrder::RELAXED)),
+          calls_succeeded(that.calls_succeeded.Load(MemoryOrder::RELAXED)),
+          calls_failed(that.calls_failed.Load(MemoryOrder::RELAXED)),
+          last_call_started_cycle(
+              that.last_call_started_cycle.Load(MemoryOrder::RELAXED)) {}
+
+    Atomic<intptr_t> calls_started{0};
+    Atomic<intptr_t> calls_succeeded{0};
+    Atomic<intptr_t> calls_failed{0};
+    Atomic<gpr_cycle_counter> last_call_started_cycle{0};
+    // Make sure the size is exactly one cache line.
+    uint8_t padding[GPR_CACHELINE_SIZE - 3 * sizeof(Atomic<intptr_t>) -
+                    sizeof(Atomic<gpr_cycle_counter>)];
+  } GPR_ALIGN_STRUCT(GPR_CACHELINE_SIZE);
+
+  struct CounterData {
+    intptr_t calls_started = 0;
+    intptr_t calls_succeeded = 0;
+    intptr_t calls_failed = 0;
+    gpr_cycle_counter last_call_started_cycle = 0;
+  };
+
+  // collects the sharded data into one CounterData struct.
+  void CollectData(CounterData* out);
+
+  // Really zero-sized, but 0-sized arrays are illegal on MSVC.
+  InlinedVector<AtomicCounterData, 1> per_cpu_counter_data_storage_;
+  size_t num_cores_ = 0;
+};
+
+// Handles channelz bookkeeping for channels
+class ChannelNode : public BaseNode {
+ public:
+  ChannelNode(UniquePtr<char> target, size_t channel_tracer_max_nodes,
+              intptr_t parent_uuid);
+
+  // Returns the string description of the given connectivity state.
+  static const char* GetChannelConnectivityStateChangeString(
+      grpc_connectivity_state state);
+
+  intptr_t parent_uuid() const { return parent_uuid_; }
+
+  grpc_json* RenderJson() override;
+
+  // proxy methods to composed classes.
+  void AddTraceEvent(ChannelTrace::Severity severity, const grpc_slice& data) {
+    trace_.AddTraceEvent(severity, data);
+  }
+  void AddTraceEventWithReference(ChannelTrace::Severity severity,
+                                  const grpc_slice& data,
+                                  RefCountedPtr<BaseNode> referenced_channel) {
+    trace_.AddTraceEventWithReference(severity, data,
+                                      std::move(referenced_channel));
+  }
+  void RecordCallStarted() { call_counter_.RecordCallStarted(); }
+  void RecordCallFailed() { call_counter_.RecordCallFailed(); }
+  void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); }
+
+  void SetConnectivityState(grpc_connectivity_state state);
+
+  // TODO(roth): take in a RefCountedPtr to the child channel so we can retrieve
+  // the human-readable name.
+  void AddChildChannel(intptr_t child_uuid);
+  void RemoveChildChannel(intptr_t child_uuid);
+
+  // TODO(roth): take in a RefCountedPtr to the child subchannel so we can
+  // retrieve the human-readable name.
+  void AddChildSubchannel(intptr_t child_uuid);
+  void RemoveChildSubchannel(intptr_t child_uuid);
+
+ private:
+  void PopulateChildRefs(grpc_json* json);
+
+  // to allow the channel trace test to access trace_.
+  friend class testing::ChannelNodePeer;
+
+  UniquePtr<char> target_;
+  CallCountingHelper call_counter_;
+  ChannelTrace trace_;
+  const intptr_t parent_uuid_;
+
+  // Least significant bit indicates whether the value is set.  Remaining
+  // bits are a grpc_connectivity_state value.
+  Atomic<int> connectivity_state_{0};
+
+  Mutex child_mu_;  // Guards child maps below.
+  // TODO(roth): We don't actually use the values here, only the keys, so
+  // these should be sets instead of maps, but we don't currently have a set
+  // implementation.  Change this if/when we have one.
+  Map<intptr_t, bool> child_channels_;
+  Map<intptr_t, bool> child_subchannels_;
+};
+
+// Handles channelz bookkeeping for servers
+class ServerNode : public BaseNode {
+ public:
+  ServerNode(grpc_server* server, size_t channel_tracer_max_nodes);
+
+  ~ServerNode() override;
+
+  grpc_json* RenderJson() override;
+
+  char* RenderServerSockets(intptr_t start_socket_id, intptr_t max_results);
+
+  void AddChildSocket(RefCountedPtr<SocketNode> node);
+
+  void RemoveChildSocket(intptr_t child_uuid);
+
+  void AddChildListenSocket(RefCountedPtr<ListenSocketNode> node);
+
+  void RemoveChildListenSocket(intptr_t child_uuid);
+
+  // proxy methods to composed classes.
+  void AddTraceEvent(ChannelTrace::Severity severity, const grpc_slice& data) {
+    trace_.AddTraceEvent(severity, data);
+  }
+  void AddTraceEventWithReference(ChannelTrace::Severity severity,
+                                  const grpc_slice& data,
+                                  RefCountedPtr<BaseNode> referenced_channel) {
+    trace_.AddTraceEventWithReference(severity, data,
+                                      std::move(referenced_channel));
+  }
+  void RecordCallStarted() { call_counter_.RecordCallStarted(); }
+  void RecordCallFailed() { call_counter_.RecordCallFailed(); }
+  void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); }
+
+ private:
+  CallCountingHelper call_counter_;
+  ChannelTrace trace_;
+  Mutex child_mu_;  // Guards child maps below.
+  Map<intptr_t, RefCountedPtr<SocketNode>> child_sockets_;
+  Map<intptr_t, RefCountedPtr<ListenSocketNode>> child_listen_sockets_;
+};
+
+// Handles channelz bookkeeping for sockets
+class SocketNode : public BaseNode {
+ public:
+  SocketNode(UniquePtr<char> local, UniquePtr<char> remote,
+             UniquePtr<char> name);
+  ~SocketNode() override {}
+
+  grpc_json* RenderJson() override;
+
+  void RecordStreamStartedFromLocal();
+  void RecordStreamStartedFromRemote();
+  void RecordStreamSucceeded() {
+    gpr_atm_no_barrier_fetch_add(&streams_succeeded_, static_cast<gpr_atm>(1));
+  }
+  void RecordStreamFailed() {
+    gpr_atm_no_barrier_fetch_add(&streams_failed_, static_cast<gpr_atm>(1));
+  }
+  void RecordMessagesSent(uint32_t num_sent);
+  void RecordMessageReceived();
+  void RecordKeepaliveSent() {
+    gpr_atm_no_barrier_fetch_add(&keepalives_sent_, static_cast<gpr_atm>(1));
+  }
+
+  const char* remote() { return remote_.get(); }
+
+ private:
+  gpr_atm streams_started_ = 0;
+  gpr_atm streams_succeeded_ = 0;
+  gpr_atm streams_failed_ = 0;
+  gpr_atm messages_sent_ = 0;
+  gpr_atm messages_received_ = 0;
+  gpr_atm keepalives_sent_ = 0;
+  gpr_atm last_local_stream_created_cycle_ = 0;
+  gpr_atm last_remote_stream_created_cycle_ = 0;
+  gpr_atm last_message_sent_cycle_ = 0;
+  gpr_atm last_message_received_cycle_ = 0;
+  UniquePtr<char> local_;
+  UniquePtr<char> remote_;
+};
+
+// Handles channelz bookkeeping for listen sockets
+class ListenSocketNode : public BaseNode {
+ public:
+  ListenSocketNode(UniquePtr<char> local_addr, UniquePtr<char> name);
+  ~ListenSocketNode() override {}
+
+  grpc_json* RenderJson() override;
+
+ private:
+  UniquePtr<char> local_addr_;
+};
+
+}  // namespace channelz
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_LIB_CHANNEL_CHANNELZ_H */