blob: 1ef3d03c7346870c467432b88fb23f7ba96ec812 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
// NOTE: RPC users are not supposed to include this file.
#ifndef BRPC_SPAN_H
#define BRPC_SPAN_H
#include <stdint.h>
#include <string>
#include <deque>
#include <ostream>
#include "butil/macros.h"
#include "butil/endpoint.h"
#include "butil/string_splitter.h"
#include "bvar/collector.h"
#include "bthread/task_meta.h"
#include "brpc/options.pb.h" // ProtocolType
#include "brpc/span.pb.h"
namespace bthread {
extern __thread bthread::LocalStorage tls_bls;
}
namespace brpc {
DECLARE_bool(enable_rpcz);
// Collect information required by /rpcz and tracing system whose idea is
// described in http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/36356.pdf
class Span : public bvar::Collected {
friend class SpanDB;
struct Forbidden {};
public:
// Call CreateServerSpan/CreateClientSpan instead.
Span(Forbidden) {}
~Span() {}
// Create a span to track a request inside server.
static Span* CreateServerSpan(
const std::string& full_method_name,
uint64_t trace_id, uint64_t span_id, uint64_t parent_span_id,
int64_t base_real_us);
// Create a span without name to track a request inside server.
static Span* CreateServerSpan(
uint64_t trace_id, uint64_t span_id, uint64_t parent_span_id,
int64_t base_real_us);
// Clear all annotations and reset name of the span.
void ResetServerSpanName(const std::string& name);
// Create a span to track a request inside channel.
static Span* CreateClientSpan(const std::string& full_method_name,
int64_t base_real_us);
// Create a span to track start bthread
static Span* CreateBthreadSpan(const std::string& full_method_name,
int64_t base_real_us);
static void Submit(Span* span, int64_t cpuwide_time_us);
// Set tls parent.
void AsParent() {
bthread::tls_bls.rpcz_parent_span = this;
}
// Add log with time.
void Annotate(const char* fmt, ...);
void Annotate(const char* fmt, va_list args);
void Annotate(const std::string& info);
// When length <= 0, use strlen instead.
void AnnotateCStr(const char* cstr, size_t length);
// #child spans, Not O(1)
size_t CountClientSpans() const;
int64_t GetStartRealTimeUs() const;
int64_t GetEndRealTimeUs() const;
void set_log_id(uint64_t cid) { _log_id = cid; }
void set_base_cid(bthread_id_t id) { _base_cid = id; }
void set_ending_cid(bthread_id_t id) { _ending_cid = id; }
void set_remote_side(const butil::EndPoint& pt) { _remote_side = pt; }
void set_protocol(ProtocolType p) { _protocol = p; }
void set_error_code(int error_code) { _error_code = error_code; }
void set_request_size(int size) { _request_size = size; }
void set_response_size(int size) { _response_size = size; }
void set_async(bool async) { _async = async; }
void set_base_real_us(int64_t tm) { _base_real_us = tm; }
void set_received_us(int64_t tm)
{ _received_real_us = tm + _base_real_us; }
void set_start_parse_us(int64_t tm)
{ _start_parse_real_us = tm + _base_real_us; }
void set_start_callback_us(int64_t tm)
{ _start_callback_real_us = tm + _base_real_us; }
void set_start_send_us(int64_t tm)
{ _start_send_real_us = tm + _base_real_us; }
void set_sent_us(int64_t tm)
{ _sent_real_us = tm + _base_real_us; }
Span* local_parent() const { return _local_parent; }
static Span* tls_parent() {
return (Span*)bthread::tls_bls.rpcz_parent_span;
}
uint64_t trace_id() const { return _trace_id; }
uint64_t parent_span_id() const { return _parent_span_id; }
uint64_t span_id() const { return _span_id; }
uint64_t log_id() const { return _log_id; }
bthread_id_t base_cid() const { return _base_cid; }
bthread_id_t ending_cid() const { return _ending_cid; }
const butil::EndPoint& remote_side() const { return _remote_side; }
SpanType type() const { return _type; }
ProtocolType protocol() const { return _protocol; }
int error_code() const { return _error_code; }
int request_size() const { return _request_size; }
int response_size() const { return _response_size; }
int64_t received_real_us() const { return _received_real_us; }
int64_t start_parse_real_us() const { return _start_parse_real_us; }
int64_t start_callback_real_us() const { return _start_callback_real_us; }
int64_t start_send_real_us() const { return _start_send_real_us; }
int64_t sent_real_us() const { return _sent_real_us; }
bool async() const { return _async; }
const std::string& full_method_name() const { return _full_method_name; }
const std::string& info() const { return _info; }
private:
DISALLOW_COPY_AND_ASSIGN(Span);
void dump_and_destroy(size_t round_index);
void destroy();
void traversal(Span*, const std::function<void(Span*)>&) const;
bvar::CollectorSpeedLimit* speed_limit();
bvar::CollectorPreprocessor* preprocessor();
void EndAsParent() {
if (this == (Span*)bthread::tls_bls.rpcz_parent_span) {
bthread::tls_bls.rpcz_parent_span = NULL;
}
}
uint64_t _trace_id;
uint64_t _span_id;
uint64_t _parent_span_id;
uint64_t _log_id;
bthread_id_t _base_cid;
bthread_id_t _ending_cid;
butil::EndPoint _remote_side;
SpanType _type;
bool _async;
ProtocolType _protocol;
int _error_code;
int _request_size;
int _response_size;
int64_t _base_real_us;
int64_t _received_real_us;
int64_t _start_parse_real_us;
int64_t _start_callback_real_us;
int64_t _start_send_real_us;
int64_t _sent_real_us;
std::string _full_method_name;
// Format:
// time1_us \s annotation1 <SEP>
// time2_us \s annotation2 <SEP>
// ...
std::string _info;
Span* _local_parent;
Span* _next_client;
Span* _client_list;
Span* _tls_next;
};
// Extract name and annotations from Span::info()
class SpanInfoExtractor {
public:
SpanInfoExtractor(const char* info);
bool PopAnnotation(int64_t before_this_time,
int64_t* time, std::string* annotation);
private:
butil::StringSplitter _sp;
};
// These two functions can be used for composing TRACEPRINT as well as hiding
// span implementations.
bool CanAnnotateSpan();
void AnnotateSpan(const char* fmt, ...);
class SpanFilter {
public:
virtual ~SpanFilter() = default;
virtual bool Keep(const BriefSpan&) = 0;
};
class SpanDB;
// Find a span by its trace_id and span_id, serialize it into `span'.
int FindSpan(uint64_t trace_id, uint64_t span_id, RpczSpan* span);
// Find spans by their trace_id, serialize them into `out'
void FindSpans(uint64_t trace_id, std::deque<RpczSpan>* out);
// Put at most `max_scan' spans before `before_this_time' into `out'.
// If filter is not NULL, only push spans that make SpanFilter::Keep()
// true.
void ListSpans(int64_t before_this_time, size_t max_scan,
std::deque<BriefSpan>* out, SpanFilter* filter);
void DescribeSpanDB(std::ostream& os);
SpanDB* LoadSpanDBFromFile(const char* filepath);
int FindSpan(SpanDB* db, uint64_t trace_id, uint64_t span_id, RpczSpan* span);
void FindSpans(SpanDB* db, uint64_t trace_id, std::deque<RpczSpan>* out);
void ListSpans(SpanDB* db, int64_t before_this_time, size_t max_scan,
std::deque<BriefSpan>* out, SpanFilter* filter);
// Check this function first before creating a span.
// If rpcz of upstream is enabled, local rpcz is enabled automatically.
inline bool IsTraceable(bool is_upstream_traced) {
extern bvar::CollectorSpeedLimit g_span_sl;
return is_upstream_traced ||
(FLAGS_enable_rpcz && bvar::is_collectable(&g_span_sl));
}
inline void* CreateBthreadSpan() {
const int64_t received_us = butil::cpuwide_time_us();
const int64_t base_realtime = butil::gettimeofday_us() - received_us;
return Span::CreateBthreadSpan("Bthread", base_realtime);
}
} // namespace brpc
#endif // BRPC_SPAN_H