1 // Copyright 2023 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GRPC_PYTHON_OPENCENSUS_CLIENT_CALL_TRACER_H
16 #define GRPC_PYTHON_OPENCENSUS_CLIENT_CALL_TRACER_H
17 
18 #include <stdint.h>
19 
20 #include <string>
21 
22 #include "absl/base/thread_annotations.h"
23 #include "absl/status/status.h"
24 #include "absl/strings/escaping.h"
25 #include "absl/strings/string_view.h"
26 #include "absl/time/time.h"
27 #include "python_census_context.h"
28 
29 #include <grpc/support/time.h>
30 
31 #include "src/core/lib/channel/call_tracer.h"
32 
33 namespace grpc_observability {
34 
35 class PythonOpenCensusCallTracer : public grpc_core::ClientCallTracer {
36  public:
37   class PythonOpenCensusCallAttemptTracer : public CallAttemptTracer {
38    public:
39     PythonOpenCensusCallAttemptTracer(PythonOpenCensusCallTracer* parent,
40                                       uint64_t attempt_num,
41                                       bool is_transparent_retry);
TraceId()42     std::string TraceId() override {
43       return absl::BytesToHexString(
44           absl::string_view(context_.GetSpanContext().TraceId()));
45     }
46 
SpanId()47     std::string SpanId() override {
48       return absl::BytesToHexString(
49           absl::string_view(context_.GetSpanContext().SpanId()));
50     }
51 
IsSampled()52     bool IsSampled() override { return context_.GetSpanContext().IsSampled(); }
53 
54     void RecordSendInitialMetadata(
55         grpc_metadata_batch* send_initial_metadata) override;
RecordSendTrailingMetadata(grpc_metadata_batch *)56     void RecordSendTrailingMetadata(
57         grpc_metadata_batch* /*send_trailing_metadata*/) override {}
58     void RecordSendMessage(
59         const grpc_core::SliceBuffer& /*send_message*/) override;
RecordSendCompressedMessage(const grpc_core::SliceBuffer &)60     void RecordSendCompressedMessage(
61         const grpc_core::SliceBuffer& /*send_compressed_message*/) override {}
RecordReceivedInitialMetadata(grpc_metadata_batch *)62     void RecordReceivedInitialMetadata(
63         grpc_metadata_batch* /*recv_initial_metadata*/) override {}
64     void RecordReceivedMessage(
65         const grpc_core::SliceBuffer& /*recv_message*/) override;
RecordReceivedDecompressedMessage(const grpc_core::SliceBuffer &)66     void RecordReceivedDecompressedMessage(
67         const grpc_core::SliceBuffer& /*recv_decompressed_message*/) override {}
68     void RecordReceivedTrailingMetadata(
69         absl::Status status, grpc_metadata_batch* recv_trailing_metadata,
70         const grpc_transport_stream_stats* transport_stream_stats) override;
71     void RecordCancel(grpc_error_handle cancel_error) override;
72     void RecordEnd(const gpr_timespec& /*latency*/) override;
73     void RecordAnnotation(absl::string_view annotation) override;
74     void RecordAnnotation(const Annotation& annotation) override;
75     std::shared_ptr<grpc_core::TcpTracerInterface> StartNewTcpTrace() override;
SetOptionalLabel(OptionalLabelKey,grpc_core::RefCountedStringValue)76     void SetOptionalLabel(OptionalLabelKey /*key*/,
77                           grpc_core::RefCountedStringValue /*value*/) override {
78     }
79 
80    private:
81     // Maximum size of trace context is sent on the wire.
82     static constexpr uint32_t kMaxTraceContextLen = 64;
83     // Maximum size of tags that are sent on the wire.
84     static constexpr uint32_t kMaxTagsLen = 2048;
85     PythonOpenCensusCallTracer* parent_;
86     PythonCensusContext context_;
87     // Start time (for measuring latency).
88     absl::Time start_time_;
89     // Number of messages in this RPC.
90     uint64_t recv_message_count_ = 0;
91     uint64_t sent_message_count_ = 0;
92     // End status code
93     absl::StatusCode status_code_;
94   };
95 
96   explicit PythonOpenCensusCallTracer(const char* method, const char* target,
97                                       const char* trace_id,
98                                       const char* parent_span_id,
99                                       bool tracing_enabled);
100   ~PythonOpenCensusCallTracer() override;
101 
TraceId()102   std::string TraceId() override {
103     return absl::BytesToHexString(
104         absl::string_view(context_.GetSpanContext().TraceId()));
105   }
106 
SpanId()107   std::string SpanId() override {
108     return absl::BytesToHexString(
109         absl::string_view(context_.GetSpanContext().SpanId()));
110   }
111 
IsSampled()112   bool IsSampled() override { return context_.GetSpanContext().IsSampled(); }
113 
114   void GenerateContext();
115   PythonOpenCensusCallAttemptTracer* StartNewAttempt(
116       bool is_transparent_retry) override;
117 
118   void RecordAnnotation(absl::string_view annotation) override;
119   void RecordAnnotation(const Annotation& annotation) override;
120 
121  private:
122   PythonCensusContext CreateCensusContextForCallAttempt();
123 
124   // Client method.
125   absl::string_view method_;
126   // Client target.
127   absl::string_view target_;
128   PythonCensusContext context_;
129   bool tracing_enabled_;
130   mutable grpc_core::Mutex mu_;
131   // Non-transparent attempts per call
132   uint64_t retries_ ABSL_GUARDED_BY(&mu_) = 0;
133   // Transparent retries per call
134   uint64_t transparent_retries_ ABSL_GUARDED_BY(&mu_) = 0;
135   // Retry delay
136   absl::Duration retry_delay_ ABSL_GUARDED_BY(&mu_);
137   absl::Time time_at_last_attempt_end_ ABSL_GUARDED_BY(&mu_);
138   uint64_t num_active_rpcs_ ABSL_GUARDED_BY(&mu_) = 0;
139 };
140 
141 }  // namespace grpc_observability
142 
143 #endif  // GRPC_PYTHON_OPENCENSUS_CLIENT_CALL_TRACER_H
144