Skip to content
This repository was archived by the owner on Jul 31, 2023. It is now read-only.

Commit a7568a6

Browse files
authored
Add propagation helpers for the grpc-trace-bin header. (#269)
1 parent 7242755 commit a7568a6

File tree

5 files changed

+405
-0
lines changed

5 files changed

+405
-0
lines changed

opencensus/trace/BUILD

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,21 @@ cc_library(
114114
],
115115
)
116116

117+
cc_library(
118+
name = "grpc_trace_bin",
119+
srcs = [
120+
"internal/grpc_trace_bin.cc",
121+
],
122+
hdrs = [
123+
"propagation/grpc_trace_bin.h",
124+
],
125+
copts = DEFAULT_COPTS,
126+
visibility = ["//visibility:public"],
127+
deps = [
128+
":span_context",
129+
],
130+
)
131+
117132
cc_library(
118133
name = "span_context",
119134
srcs = [
@@ -207,6 +222,17 @@ cc_test(
207222
],
208223
)
209224

225+
cc_test(
226+
name = "grpc_trace_bin_test",
227+
srcs = ["internal/grpc_trace_bin_test.cc"],
228+
copts = TEST_COPTS,
229+
deps = [
230+
":grpc_trace_bin",
231+
":span_context",
232+
"@com_google_googletest//:gtest_main",
233+
],
234+
)
235+
210236
cc_test(
211237
name = "link_test",
212238
srcs = ["internal/link_test.cc"],
@@ -382,6 +408,18 @@ cc_binary(
382408
],
383409
)
384410

411+
cc_binary(
412+
name = "grpc_trace_bin_benchmark",
413+
testonly = 1,
414+
srcs = ["internal/grpc_trace_bin_benchmark.cc"],
415+
copts = TEST_COPTS,
416+
linkstatic = 1,
417+
deps = [
418+
":grpc_trace_bin",
419+
"@com_github_google_benchmark//:benchmark",
420+
],
421+
)
422+
385423
cc_binary(
386424
name = "span_benchmark",
387425
testonly = 1,
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright 2019, OpenCensus 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+
#include "opencensus/trace/propagation/grpc_trace_bin.h"
16+
17+
#include <cstdint>
18+
19+
#include "opencensus/trace/span_context.h"
20+
#include "opencensus/trace/span_id.h"
21+
#include "opencensus/trace/trace_id.h"
22+
#include "opencensus/trace/trace_options.h"
23+
24+
namespace opencensus {
25+
namespace trace {
26+
namespace propagation {
27+
28+
namespace {
29+
30+
constexpr int kVersionLen = 1;
31+
constexpr int kTraceIdLen = 16;
32+
constexpr int kSpanIdLen = 8;
33+
constexpr int kTraceOptionsLen = 1;
34+
35+
constexpr uint8_t kVersionId = 0;
36+
constexpr uint8_t kTraceIdField = 0;
37+
constexpr uint8_t kSpanIdField = 1;
38+
constexpr uint8_t kTraceOptionsField = 2;
39+
40+
constexpr int kVersionOfs = 0;
41+
constexpr int kTraceIdOfs = 1;
42+
constexpr int kSpanIdOfs = kTraceIdOfs + 1 + kTraceIdLen;
43+
constexpr int kTraceOptionsOfs = kSpanIdOfs + 1 + kSpanIdLen;
44+
45+
static_assert(1 + 1 + kTraceIdLen + 1 + kSpanIdLen + 1 + kTraceOptionsLen ==
46+
kGrpcTraceBinHeaderLen,
47+
"header length is wrong");
48+
49+
} // namespace
50+
51+
SpanContext FromGrpcTraceBinHeader(absl::string_view header) {
52+
if (header.size() < kGrpcTraceBinHeaderLen ||
53+
header[kVersionOfs] != kVersionId ||
54+
header[kTraceIdOfs] != kTraceIdField ||
55+
header[kSpanIdOfs] != kSpanIdField ||
56+
header[kTraceOptionsOfs] != kTraceOptionsField) {
57+
return SpanContext(); // Invalid.
58+
}
59+
60+
uint8_t options = header[kTraceOptionsOfs + 1] & 1;
61+
62+
return SpanContext(
63+
TraceId(reinterpret_cast<const uint8_t*>(&header[kTraceIdOfs + 1])),
64+
SpanId(reinterpret_cast<const uint8_t*>(&header[kSpanIdOfs + 1])),
65+
TraceOptions(&options));
66+
}
67+
68+
std::string ToGrpcTraceBinHeader(const SpanContext& ctx) {
69+
std::string out(kGrpcTraceBinHeaderLen, '\0');
70+
ToGrpcTraceBinHeader(ctx, reinterpret_cast<uint8_t*>(&out[0]));
71+
return out;
72+
}
73+
74+
void ToGrpcTraceBinHeader(const SpanContext& ctx, uint8_t* out) {
75+
out[kVersionOfs] = kVersionId;
76+
out[kTraceIdOfs] = kTraceIdField;
77+
ctx.trace_id().CopyTo(reinterpret_cast<uint8_t*>(&out[kTraceIdOfs + 1]));
78+
out[kSpanIdOfs] = kSpanIdField;
79+
ctx.span_id().CopyTo(reinterpret_cast<uint8_t*>(&out[kSpanIdOfs + 1]));
80+
out[kTraceOptionsOfs] = kTraceOptionsField;
81+
ctx.trace_options().CopyTo(
82+
reinterpret_cast<uint8_t*>(&out[kTraceOptionsOfs + 1]));
83+
}
84+
85+
} // namespace propagation
86+
} // namespace trace
87+
} // namespace opencensus
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2019, OpenCensus 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+
#include "opencensus/trace/propagation/grpc_trace_bin.h"
16+
17+
#include "benchmark/benchmark.h"
18+
19+
namespace opencensus {
20+
namespace trace {
21+
namespace propagation {
22+
namespace {
23+
24+
constexpr unsigned char header_data[] = {
25+
0, // version_id
26+
0, // trace_id field
27+
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, // lo
28+
0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, // hi
29+
1, // span_id field
30+
0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, // span_id
31+
2, // trace_options field
32+
1, // tracing enabled
33+
};
34+
35+
void BM_FromGrpcTraceBin(benchmark::State& state) {
36+
absl::string_view header(reinterpret_cast<const char*>(header_data),
37+
sizeof(header_data));
38+
while (state.KeepRunning()) {
39+
FromGrpcTraceBinHeader(header);
40+
}
41+
}
42+
BENCHMARK(BM_FromGrpcTraceBin);
43+
44+
void BM_FromGrpcTraceBin_Invalid(benchmark::State& state) {
45+
while (state.KeepRunning()) {
46+
FromGrpcTraceBinHeader("");
47+
}
48+
}
49+
BENCHMARK(BM_FromGrpcTraceBin_Invalid);
50+
51+
void BM_ToGrpcTraceBin(benchmark::State& state) {
52+
absl::string_view header(reinterpret_cast<const char*>(header_data),
53+
sizeof(header_data));
54+
auto ctx = FromGrpcTraceBinHeader(header);
55+
while (state.KeepRunning()) {
56+
ToGrpcTraceBinHeader(ctx);
57+
}
58+
}
59+
BENCHMARK(BM_ToGrpcTraceBin);
60+
61+
void BM_ToGrpcTraceBin_InPlace(benchmark::State& state) {
62+
absl::string_view header(reinterpret_cast<const char*>(header_data),
63+
sizeof(header_data));
64+
auto ctx = FromGrpcTraceBinHeader(header);
65+
uint8_t out[kGrpcTraceBinHeaderLen];
66+
while (state.KeepRunning()) {
67+
ToGrpcTraceBinHeader(ctx, out);
68+
}
69+
}
70+
BENCHMARK(BM_ToGrpcTraceBin_InPlace);
71+
72+
} // namespace
73+
} // namespace propagation
74+
} // namespace trace
75+
} // namespace opencensus
76+
77+
BENCHMARK_MAIN();
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copyright 2019, OpenCensus 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+
#include "opencensus/trace/propagation/grpc_trace_bin.h"
16+
17+
#include "gmock/gmock.h"
18+
#include "gtest/gtest.h"
19+
#include "opencensus/trace/span_context.h"
20+
#include "opencensus/trace/span_id.h"
21+
#include "opencensus/trace/trace_id.h"
22+
23+
namespace opencensus {
24+
namespace trace {
25+
namespace propagation {
26+
namespace {
27+
28+
MATCHER(IsValid, "is a valid SpanContext") { return arg.IsValid(); }
29+
MATCHER(IsInvalid, "is an invalid SpanContext") { return !arg.IsValid(); }
30+
31+
TEST(GrpcTraceBinTest, ParseFull) {
32+
constexpr unsigned char header_data[] = {
33+
0, // version_id
34+
0, // trace_id field
35+
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, // lo
36+
0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, // hi
37+
1, // span_id field
38+
0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, // span_id
39+
2, // trace_options field
40+
1, // is sampled
41+
};
42+
absl::string_view header(reinterpret_cast<const char*>(header_data),
43+
sizeof(header_data));
44+
SpanContext ctx = FromGrpcTraceBinHeader(header);
45+
EXPECT_THAT(ctx, IsValid());
46+
EXPECT_EQ("64656667686970717273747576777879-8182838485868788-01",
47+
ctx.ToString());
48+
EXPECT_EQ(header, ToGrpcTraceBinHeader(ctx));
49+
}
50+
51+
TEST(GrpcTraceBinTest, ParseNotSampled) {
52+
constexpr unsigned char header_data[] = {
53+
0, // version_id
54+
0, // trace_id field
55+
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, // lo
56+
0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, // hi
57+
1, // span_id field
58+
0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, // span_id
59+
2, // trace_options field
60+
0, // not sampled
61+
};
62+
absl::string_view header(reinterpret_cast<const char*>(header_data),
63+
sizeof(header_data));
64+
SpanContext ctx = FromGrpcTraceBinHeader(header);
65+
EXPECT_THAT(ctx, IsValid());
66+
EXPECT_FALSE(ctx.trace_options().IsSampled())
67+
<< "Expecting to not be sampled.";
68+
EXPECT_EQ("64656667686970717273747576777879-8182838485868788-00",
69+
ctx.ToString());
70+
EXPECT_EQ(header, ToGrpcTraceBinHeader(ctx));
71+
}
72+
73+
TEST(GrpcTraceBinTest, ExpectedFailures) {
74+
#define INVALID(hdr) \
75+
EXPECT_THAT(FromGrpcTraceBinHeader(absl::string_view( \
76+
reinterpret_cast<const char*>(hdr), sizeof(hdr))), \
77+
IsInvalid())
78+
INVALID("");
79+
{
80+
constexpr unsigned char header[] = {
81+
0, // version_id
82+
0, // trace_id field
83+
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, // lo
84+
0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, // hi
85+
1, // span_id field
86+
0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, // span_id
87+
2, // options missing
88+
};
89+
INVALID(header) << "Too short.";
90+
}
91+
{
92+
constexpr unsigned char header[] = {
93+
123, // version_id
94+
0, // trace_id field
95+
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, // lo
96+
0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, // hi
97+
1, // span_id field
98+
0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, // span_id
99+
2, // trace_options field
100+
1, // tracing enabled
101+
};
102+
INVALID(header) << "Wrong version_id.";
103+
}
104+
{
105+
constexpr unsigned char header[] = {
106+
0, // version_id
107+
0, // trace_id field
108+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // lo
109+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // hi
110+
1, // span_id field
111+
0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, // span_id
112+
2, // trace_options field
113+
1, // tracing enabled
114+
};
115+
INVALID(header) << "Invalid trace_id.";
116+
}
117+
{
118+
constexpr unsigned char header[] = {
119+
0, // version_id
120+
0, // trace_id field
121+
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, // lo
122+
0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, // hi
123+
1, // span_id field
124+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // span_id
125+
2, // trace_options field
126+
1, // tracing enabled
127+
};
128+
INVALID(header) << "Invalid span_id.";
129+
}
130+
#undef INVALID
131+
}
132+
133+
} // namespace
134+
} // namespace propagation
135+
} // namespace trace
136+
} // namespace opencensus

0 commit comments

Comments
 (0)