1 // 2 // 3 // Copyright 2021 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 // 18 19 #ifndef GRPC_SRC_CORE_LIB_CHANNEL_CALL_TRACER_H 20 #define GRPC_SRC_CORE_LIB_CHANNEL_CALL_TRACER_H 21 22 #include <grpc/support/port_platform.h> 23 24 #include <memory> 25 #include <string> 26 27 #include "absl/status/status.h" 28 #include "absl/strings/string_view.h" 29 #include "absl/types/optional.h" 30 31 #include <grpc/support/time.h> 32 33 #include "src/core/lib/channel/channel_args.h" 34 #include "src/core/lib/channel/context.h" 35 #include "src/core/lib/channel/tcp_tracer.h" 36 #include "src/core/lib/gprpp/ref_counted_string.h" 37 #include "src/core/lib/iomgr/error.h" 38 #include "src/core/lib/resource_quota/arena.h" 39 #include "src/core/lib/slice/slice_buffer.h" 40 #include "src/core/lib/transport/call_final_info.h" 41 #include "src/core/lib/transport/metadata_batch.h" 42 43 namespace grpc_core { 44 45 // The interface hierarchy is as follows - 46 // CallTracerAnnotationInterface 47 // | | 48 // ClientCallTracer CallTracerInterface 49 // | | 50 // CallAttemptTracer ServerCallTracer 51 52 // The base class for all tracer implementations. 53 class CallTracerAnnotationInterface { 54 public: 55 // Enum associated with types of Annotations. 56 enum class AnnotationType { 57 kMetadataSizes, 58 kHttpTransport, 59 kDoNotUse_MustBeLast, 60 }; 61 62 // Base class to define a new type of annotation. 63 class Annotation { 64 public: Annotation(AnnotationType type)65 explicit Annotation(AnnotationType type) : type_(type) {} type()66 AnnotationType type() const { return type_; } 67 virtual std::string ToString() const = 0; 68 virtual ~Annotation() = default; 69 70 private: 71 const AnnotationType type_; 72 }; 73 ~CallTracerAnnotationInterface()74 virtual ~CallTracerAnnotationInterface() {} 75 // Records an annotation on the call attempt. 76 // TODO(yashykt): If needed, extend this to attach attributes with 77 // annotations. 78 virtual void RecordAnnotation(absl::string_view annotation) = 0; 79 virtual void RecordAnnotation(const Annotation& annotation) = 0; 80 virtual std::string TraceId() = 0; 81 virtual std::string SpanId() = 0; 82 virtual bool IsSampled() = 0; 83 // Indicates whether this tracer is a delegating tracer or not. 84 // `DelegatingClientCallTracer`, `DelegatingClientCallAttemptTracer` and 85 // `DelegatingServerCallTracer` are the only delegating call tracers. IsDelegatingTracer()86 virtual bool IsDelegatingTracer() { return false; } 87 }; 88 89 // The base class for CallAttemptTracer and ServerCallTracer. 90 // TODO(yashykt): What's a better name for this? 91 class CallTracerInterface : public CallTracerAnnotationInterface { 92 public: ~CallTracerInterface()93 ~CallTracerInterface() override {} 94 // Please refer to `grpc_transport_stream_op_batch_payload` for details on 95 // arguments. 96 virtual void RecordSendInitialMetadata( 97 grpc_metadata_batch* send_initial_metadata) = 0; 98 virtual void RecordSendTrailingMetadata( 99 grpc_metadata_batch* send_trailing_metadata) = 0; 100 virtual void RecordSendMessage(const SliceBuffer& send_message) = 0; 101 // Only invoked if message was actually compressed. 102 virtual void RecordSendCompressedMessage( 103 const SliceBuffer& send_compressed_message) = 0; 104 // The `RecordReceivedInitialMetadata()` and `RecordReceivedMessage()` 105 // methods should only be invoked when the metadata/message was 106 // successfully received, i.e., without any error. 107 virtual void RecordReceivedInitialMetadata( 108 grpc_metadata_batch* recv_initial_metadata) = 0; 109 virtual void RecordReceivedMessage(const SliceBuffer& recv_message) = 0; 110 // Only invoked if message was actually decompressed. 111 virtual void RecordReceivedDecompressedMessage( 112 const SliceBuffer& recv_decompressed_message) = 0; 113 virtual void RecordCancel(grpc_error_handle cancel_error) = 0; 114 // Traces a new TCP transport attempt for this call attempt. Note the TCP 115 // transport may finish tracing and unref the TCP tracer before or after the 116 // call completion in gRPC core. No TCP tracing when null is returned. 117 virtual std::shared_ptr<TcpTracerInterface> StartNewTcpTrace() = 0; 118 }; 119 120 // Interface for a tracer that records activities on a call. Actual attempts for 121 // this call are traced with CallAttemptTracer after invoking RecordNewAttempt() 122 // on the ClientCallTracer object. 123 class ClientCallTracer : public CallTracerAnnotationInterface { 124 public: 125 // Interface for a tracer that records activities on a particular call 126 // attempt. 127 // (A single RPC can have multiple attempts due to retry/hedging policies or 128 // as transparent retry attempts.) 129 class CallAttemptTracer : public CallTracerInterface { 130 public: 131 // Note that not all of the optional label keys are exposed as public API. 132 enum class OptionalLabelKey : std::uint8_t { 133 kXdsServiceName, // not public 134 kXdsServiceNamespace, // not public 135 kLocality, 136 kSize // should be last 137 }; 138 ~CallAttemptTracer()139 ~CallAttemptTracer() override {} 140 141 // TODO(yashykt): The following two methods `RecordReceivedTrailingMetadata` 142 // and `RecordEnd` should be moved into CallTracerInterface. 143 // If the call was cancelled before the recv_trailing_metadata op 144 // was started, recv_trailing_metadata and transport_stream_stats 145 // will be null. 146 virtual void RecordReceivedTrailingMetadata( 147 absl::Status status, grpc_metadata_batch* recv_trailing_metadata, 148 const grpc_transport_stream_stats* transport_stream_stats) = 0; 149 // Should be the last API call to the object. Once invoked, the tracer 150 // library is free to destroy the object. 151 virtual void RecordEnd(const gpr_timespec& latency) = 0; 152 153 // Sets an optional label on the per-attempt metrics recorded at the end of 154 // the attempt. 155 virtual void SetOptionalLabel(OptionalLabelKey key, 156 RefCountedStringValue value) = 0; 157 }; 158 ~ClientCallTracer()159 ~ClientCallTracer() override {} 160 161 // Records a new attempt for the associated call. \a transparent denotes 162 // whether the attempt is being made as a transparent retry or as a 163 // non-transparent retry/hedging attempt. (There will be at least one attempt 164 // even if the call is not being retried.) The `ClientCallTracer` object 165 // retains ownership to the newly created `CallAttemptTracer` object. 166 // RecordEnd() serves as an indication that the call stack is done with all 167 // API calls, and the tracer library is free to destroy it after that. 168 virtual CallAttemptTracer* StartNewAttempt(bool is_transparent_retry) = 0; 169 }; 170 171 // Interface for a tracer that records activities on a server call. 172 class ServerCallTracer : public CallTracerInterface { 173 public: ~ServerCallTracer()174 ~ServerCallTracer() override {} 175 // TODO(yashykt): The following two methods `RecordReceivedTrailingMetadata` 176 // and `RecordEnd` should be moved into CallTracerInterface. 177 virtual void RecordReceivedTrailingMetadata( 178 grpc_metadata_batch* recv_trailing_metadata) = 0; 179 // Should be the last API call to the object. Once invoked, the tracer 180 // library is free to destroy the object. 181 virtual void RecordEnd(const grpc_call_final_info* final_info) = 0; 182 }; 183 184 // Interface for a factory that can create a ServerCallTracer object per 185 // server call. 186 class ServerCallTracerFactory { 187 public: 188 struct RawPointerChannelArgTag {}; 189 ~ServerCallTracerFactory()190 virtual ~ServerCallTracerFactory() {} 191 192 virtual ServerCallTracer* CreateNewServerCallTracer( 193 Arena* arena, const ChannelArgs& channel_args) = 0; 194 195 // Returns true if a server is to be traced, false otherwise. IsServerTraced(const ChannelArgs &)196 virtual bool IsServerTraced(const ChannelArgs& /*args*/) { return true; } 197 198 // Use this method to get the server call tracer factory from channel args, 199 // instead of directly fetching it with `GetObject`. 200 static ServerCallTracerFactory* Get(const ChannelArgs& channel_args); 201 202 // Registers a global ServerCallTracerFactory that wil be used by default if 203 // no corresponding channel arg was found. It is only valid to call this 204 // before grpc_init(). It is the responsibility of the caller to maintain 205 // this for the lifetime of the process. 206 static void RegisterGlobal(ServerCallTracerFactory* factory); 207 208 // Deletes any previous registered ServerCallTracerFactory. 209 static void TestOnlyReset(); 210 211 static absl::string_view ChannelArgName(); 212 }; 213 214 // Convenience functions to add call tracers to a call context. Allows setting 215 // multiple call tracers to a single call. It is only valid to add client call 216 // tracers before the client_channel filter sees the send_initial_metadata op. 217 void AddClientCallTracerToContext(grpc_call_context_element* call_context, 218 ClientCallTracer* tracer); 219 220 // TODO(yashykt): We want server call tracers to be registered through the 221 // ServerCallTracerFactory, which has yet to be made into a list. 222 void AddServerCallTracerToContext(grpc_call_context_element* call_context, 223 ServerCallTracer* tracer); 224 225 } // namespace grpc_core 226 227 #endif // GRPC_SRC_CORE_LIB_CHANNEL_CALL_TRACER_H 228