1 //
2 // Copyright 2022 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "src/cpp/ext/gcp/observability_logging_sink.h"
18
19 #include "absl/strings/escaping.h"
20 #include "absl/strings/str_format.h"
21 #include "gmock/gmock.h"
22 #include "google/protobuf/text_format.h"
23 #include "gtest/gtest.h"
24 #include "src/core/util/json/json_reader.h"
25 #include "test/core/test_util/test_config.h"
26
27 namespace grpc {
28 namespace internal {
29
30 namespace {
31
32 using grpc_core::LoggingSink;
33
TEST(GcpObservabilityLoggingSinkTest,LoggingConfigEmpty)34 TEST(GcpObservabilityLoggingSinkTest, LoggingConfigEmpty) {
35 const char* json_str = R"json({
36 "cloud_logging": {
37 }
38 })json";
39 auto json = grpc_core::JsonParse(json_str);
40 ASSERT_TRUE(json.ok()) << json.status();
41 grpc_core::ValidationErrors errors;
42 auto config = grpc_core::LoadFromJson<GcpObservabilityConfig>(
43 *json, grpc_core::JsonArgs(), &errors);
44 ASSERT_TRUE(errors.ok()) << errors.status(absl::StatusCode::kInvalidArgument,
45 "unexpected errors");
46 ObservabilityLoggingSink sink(config.cloud_logging.value(), "test", {});
47 // client test
48 EXPECT_FALSE(sink.FindMatch(true, "foo", "bar").ShouldLog());
49 // server test
50 EXPECT_FALSE(sink.FindMatch(false, "foo", "bar").ShouldLog());
51 }
52
TEST(GcpObservabilityLoggingSinkTest,LoggingConfigClientWildCardEntries)53 TEST(GcpObservabilityLoggingSinkTest, LoggingConfigClientWildCardEntries) {
54 const char* json_str = R"json({
55 "cloud_logging": {
56 "client_rpc_events": [
57 {
58 "methods": ["*"],
59 "max_metadata_bytes": 1024,
60 "max_message_bytes": 4096
61 }
62 ]
63 }
64 })json";
65 auto json = grpc_core::JsonParse(json_str);
66 ASSERT_TRUE(json.ok()) << json.status();
67 grpc_core::ValidationErrors errors;
68 auto config = grpc_core::LoadFromJson<GcpObservabilityConfig>(
69 *json, grpc_core::JsonArgs(), &errors);
70 ASSERT_TRUE(errors.ok()) << errors.status(absl::StatusCode::kInvalidArgument,
71 "unexpected errors");
72 ObservabilityLoggingSink sink(config.cloud_logging.value(), "test", {});
73 // client test
74 EXPECT_EQ(sink.FindMatch(true, "foo", "bar"),
75 LoggingSink::Config(1024, 4096));
76 // server test
77 EXPECT_FALSE(sink.FindMatch(false, "foo", "bar").ShouldLog());
78 }
79
TEST(GcpObservabilityLoggingSinkTest,LoggingConfigBadPath)80 TEST(GcpObservabilityLoggingSinkTest, LoggingConfigBadPath) {
81 const char* json_str = R"json({
82 "cloud_logging": {
83 "client_rpc_events": [
84 {
85 "methods": ["*"],
86 "max_metadata_bytes": 1024,
87 "max_message_bytes": 4096
88 }
89 ]
90 }
91 })json";
92 auto json = grpc_core::JsonParse(json_str);
93 ASSERT_TRUE(json.ok()) << json.status();
94 grpc_core::ValidationErrors errors;
95 auto config = grpc_core::LoadFromJson<GcpObservabilityConfig>(
96 *json, grpc_core::JsonArgs(), &errors);
97 ASSERT_TRUE(errors.ok()) << errors.status(absl::StatusCode::kInvalidArgument,
98 "unexpected errors");
99 ObservabilityLoggingSink sink(config.cloud_logging.value(), "test", {});
100 EXPECT_FALSE(sink.FindMatch(true, "foo", "").ShouldLog());
101 }
102
TEST(GcpObservabilityLoggingSinkTest,LoggingConfigClientWildCardServiceEntries)103 TEST(GcpObservabilityLoggingSinkTest,
104 LoggingConfigClientWildCardServiceEntries) {
105 const char* json_str = R"json({
106 "cloud_logging": {
107 "client_rpc_events": [
108 {
109 "methods": ["service/*"],
110 "max_metadata_bytes": 1024,
111 "max_message_bytes": 4096
112 }
113 ]
114 }
115 })json";
116 auto json = grpc_core::JsonParse(json_str);
117 ASSERT_TRUE(json.ok()) << json.status();
118 grpc_core::ValidationErrors errors;
119 auto config = grpc_core::LoadFromJson<GcpObservabilityConfig>(
120 *json, grpc_core::JsonArgs(), &errors);
121 ASSERT_TRUE(errors.ok()) << errors.status(absl::StatusCode::kInvalidArgument,
122 "unexpected errors");
123 ObservabilityLoggingSink sink(config.cloud_logging.value(), "test", {});
124 // client test
125 EXPECT_EQ(sink.FindMatch(true, "service", "bar"),
126 LoggingSink::Config(1024, 4096));
127 EXPECT_FALSE(sink.FindMatch(true, "foo", "bar").ShouldLog());
128 // server test
129 EXPECT_FALSE(sink.FindMatch(false, "service", "bar").ShouldLog());
130 EXPECT_FALSE(sink.FindMatch(false, "foo", "bar").ShouldLog());
131 }
132
133 TEST(GcpObservabilityLoggingSinkTest,
134 LoggingConfigClientMultipleMethodEntries) {
135 const char* json_str = R"json({
136 "cloud_logging": {
137 "client_rpc_events": [
138 {
139 "methods": ["foo/bar", "foo/baz"],
140 "max_metadata_bytes": 1024,
141 "max_message_bytes": 4096
142 }
143 ]
144 }
145 })json";
146 auto json = grpc_core::JsonParse(json_str);
147 ASSERT_TRUE(json.ok()) << json.status();
148 grpc_core::ValidationErrors errors;
149 auto config = grpc_core::LoadFromJson<GcpObservabilityConfig>(
150 *json, grpc_core::JsonArgs(), &errors);
151 ASSERT_TRUE(errors.ok()) << errors.status(absl::StatusCode::kInvalidArgument,
152 "unexpected errors");
153 ObservabilityLoggingSink sink(config.cloud_logging.value(), "test", {});
154 // client test
155 EXPECT_EQ(sink.FindMatch(true, "foo", "bar"),
156 LoggingSink::Config(1024, 4096));
157 EXPECT_EQ(sink.FindMatch(true, "foo", "baz"),
158 LoggingSink::Config(1024, 4096));
159 // server test
160 EXPECT_FALSE(sink.FindMatch(false, "foo", "bar").ShouldLog());
161 EXPECT_FALSE(sink.FindMatch(false, "foo", "baz").ShouldLog());
162 }
163
164 TEST(GcpObservabilityLoggingSinkTest, LoggingConfigClientMultipleEventEntries) {
165 const char* json_str = R"json({
166 "cloud_logging": {
167 "client_rpc_events": [
168 {
169 "methods": ["foo/bar"],
170 "max_metadata_bytes": 1024,
171 "max_message_bytes": 4096
172 },
173 {
174 "methods": ["foo/baz"],
175 "max_metadata_bytes": 512,
176 "max_message_bytes": 2048
177 }
178 ]
179 }
180 })json";
181 auto json = grpc_core::JsonParse(json_str);
182 ASSERT_TRUE(json.ok()) << json.status();
183 grpc_core::ValidationErrors errors;
184 auto config = grpc_core::LoadFromJson<GcpObservabilityConfig>(
185 *json, grpc_core::JsonArgs(), &errors);
186 ASSERT_TRUE(errors.ok()) << errors.status(absl::StatusCode::kInvalidArgument,
187 "unexpected errors");
188 ObservabilityLoggingSink sink(config.cloud_logging.value(), "test", {});
189 // client test
190 EXPECT_EQ(sink.FindMatch(true, "foo", "bar"),
191 LoggingSink::Config(1024, 4096));
192 EXPECT_EQ(sink.FindMatch(true, "foo", "baz"), LoggingSink::Config(512, 2048));
193 // server test
194 EXPECT_FALSE(sink.FindMatch(false, "foo", "bar").ShouldLog());
195 EXPECT_FALSE(sink.FindMatch(false, "foo", "baz").ShouldLog());
196 }
197
198 TEST(GcpObservabilityLoggingSinkTest, LoggingConfigServerWildCardEntries) {
199 const char* json_str = R"json({
200 "cloud_logging": {
201 "server_rpc_events": [
202 {
203 "methods": ["*"],
204 "max_metadata_bytes": 1024,
205 "max_message_bytes": 4096
206 }
207 ]
208 }
209 })json";
210 auto json = grpc_core::JsonParse(json_str);
211 ASSERT_TRUE(json.ok()) << json.status();
212 grpc_core::ValidationErrors errors;
213 auto config = grpc_core::LoadFromJson<GcpObservabilityConfig>(
214 *json, grpc_core::JsonArgs(), &errors);
215 ASSERT_TRUE(errors.ok()) << errors.status(absl::StatusCode::kInvalidArgument,
216 "unexpected errors");
217 ObservabilityLoggingSink sink(config.cloud_logging.value(), "test", {});
218 // client test
219 EXPECT_FALSE(sink.FindMatch(true, "foo", "bar").ShouldLog());
220 // server test
221 EXPECT_EQ(sink.FindMatch(false, "foo", "bar"),
222 LoggingSink::Config(1024, 4096));
223 }
224
225 TEST(GcpObservabilityLoggingSinkTest,
226 LoggingConfigServerWildCardServiceEntries) {
227 const char* json_str = R"json({
228 "cloud_logging": {
229 "server_rpc_events": [
230 {
231 "methods": ["service/*"],
232 "max_metadata_bytes": 1024,
233 "max_message_bytes": 4096
234 }
235 ]
236 }
237 })json";
238 auto json = grpc_core::JsonParse(json_str);
239 ASSERT_TRUE(json.ok()) << json.status();
240 grpc_core::ValidationErrors errors;
241 auto config = grpc_core::LoadFromJson<GcpObservabilityConfig>(
242 *json, grpc_core::JsonArgs(), &errors);
243 ASSERT_TRUE(errors.ok()) << errors.status(absl::StatusCode::kInvalidArgument,
244 "unexpected errors");
245 ObservabilityLoggingSink sink(config.cloud_logging.value(), "test", {});
246 // client test
247 EXPECT_FALSE(sink.FindMatch(true, "service", "bar").ShouldLog());
248 EXPECT_FALSE(sink.FindMatch(true, "foo", "bar").ShouldLog());
249 // server test
250 EXPECT_EQ(sink.FindMatch(false, "service", "bar"),
251 LoggingSink::Config(1024, 4096));
252 EXPECT_FALSE(sink.FindMatch(false, "foo", "bar").ShouldLog());
253 }
254
255 TEST(GcpObservabilityLoggingSinkTest,
256 LoggingConfigServerMultipleMethodEntries) {
257 const char* json_str = R"json({
258 "cloud_logging": {
259 "server_rpc_events": [
260 {
261 "methods": ["foo/bar", "foo/baz"],
262 "max_metadata_bytes": 1024,
263 "max_message_bytes": 4096
264 }
265 ]
266 }
267 })json";
268 auto json = grpc_core::JsonParse(json_str);
269 ASSERT_TRUE(json.ok()) << json.status();
270 grpc_core::ValidationErrors errors;
271 auto config = grpc_core::LoadFromJson<GcpObservabilityConfig>(
272 *json, grpc_core::JsonArgs(), &errors);
273 ASSERT_TRUE(errors.ok()) << errors.status(absl::StatusCode::kInvalidArgument,
274 "unexpected errors");
275 ObservabilityLoggingSink sink(config.cloud_logging.value(), "test", {});
276 // client test
277 EXPECT_FALSE(sink.FindMatch(true, "foo", "bar").ShouldLog());
278 EXPECT_FALSE(sink.FindMatch(true, "foo", "baz").ShouldLog());
279 // server test
280 EXPECT_EQ(sink.FindMatch(false, "foo", "bar"),
281 LoggingSink::Config(1024, 4096));
282 EXPECT_EQ(sink.FindMatch(false, "foo", "baz"),
283 LoggingSink::Config(1024, 4096));
284 }
285
286 TEST(GcpObservabilityLoggingSinkTest, LoggingConfigServerMultipleEventEntries) {
287 const char* json_str = R"json({
288 "cloud_logging": {
289 "server_rpc_events": [
290 {
291 "methods": ["foo/bar"],
292 "max_metadata_bytes": 1024,
293 "max_message_bytes": 4096
294 },
295 {
296 "methods": ["foo/baz"],
297 "max_metadata_bytes": 512,
298 "max_message_bytes": 2048
299 }
300 ]
301 }
302 })json";
303 auto json = grpc_core::JsonParse(json_str);
304 ASSERT_TRUE(json.ok()) << json.status();
305 grpc_core::ValidationErrors errors;
306 auto config = grpc_core::LoadFromJson<GcpObservabilityConfig>(
307 *json, grpc_core::JsonArgs(), &errors);
308 ASSERT_TRUE(errors.ok()) << errors.status(absl::StatusCode::kInvalidArgument,
309 "unexpected errors");
310 ObservabilityLoggingSink sink(config.cloud_logging.value(), "test", {});
311 // client test
312 EXPECT_FALSE(sink.FindMatch(true, "foo", "bar").ShouldLog());
313 EXPECT_FALSE(sink.FindMatch(true, "foo", "baz").ShouldLog());
314 // server test
315 EXPECT_EQ(sink.FindMatch(false, "foo", "bar"),
316 LoggingSink::Config(1024, 4096));
317 EXPECT_EQ(sink.FindMatch(false, "foo", "baz"),
318 LoggingSink::Config(512, 2048));
319 }
320
321 TEST(EntryToJsonStructTest, ClientHeader) {
322 LoggingSink::Entry entry;
323 entry.call_id = 1234;
324 entry.sequence_id = 1;
325 entry.type = LoggingSink::Entry::EventType::kClientHeader;
326 entry.payload.metadata["key"] = "value";
327 entry.payload.timeout = grpc_core::Duration::Seconds(100);
328 entry.payload_truncated = true;
329 entry.peer.type = LoggingSink::Entry::Address::Type::kIpv4;
330 entry.peer.address = "127.0.0.1";
331 entry.peer.ip_port = 12345;
332 entry.authority = "authority";
333 entry.service_name = "service_name";
334 entry.method_name = "method_name";
335
336 google::protobuf::Struct proto;
337 EntryToJsonStructProto(std::move(entry), &proto);
338 std::string output;
339 ::google::protobuf::TextFormat::PrintToString(proto, &output);
340 const char* pb_str =
341 "fields {\n"
342 " key: \"authority\"\n"
343 " value {\n"
344 " string_value: \"authority\"\n"
345 " }\n"
346 "}\n"
347 "fields {\n"
348 " key: \"callId\"\n"
349 " value {\n"
350 " string_value: \"00000000-0000-4000-8000-0000000004d2\"\n"
351 " }\n"
352 "}\n"
353 "fields {\n"
354 " key: \"logger\"\n"
355 " value {\n"
356 " string_value: \"LOGGER_UNKNOWN\"\n"
357 " }\n"
358 "}\n"
359 "fields {\n"
360 " key: \"methodName\"\n"
361 " value {\n"
362 " string_value: \"method_name\"\n"
363 " }\n"
364 "}\n"
365 "fields {\n"
366 " key: \"payload\"\n"
367 " value {\n"
368 " struct_value {\n"
369 " fields {\n"
370 " key: \"metadata\"\n"
371 " value {\n"
372 " struct_value {\n"
373 " fields {\n"
374 " key: \"key\"\n"
375 " value {\n"
376 " string_value: \"value\"\n"
377 " }\n"
378 " }\n"
379 " }\n"
380 " }\n"
381 " }\n"
382 " fields {\n"
383 " key: \"timeout\"\n"
384 " value {\n"
385 " string_value: \"100.000000000s\"\n"
386 " }\n"
387 " }\n"
388 " }\n"
389 " }\n"
390 "}\n"
391 "fields {\n"
392 " key: \"payloadTruncated\"\n"
393 " value {\n"
394 " bool_value: true\n"
395 " }\n"
396 "}\n"
397 "fields {\n"
398 " key: \"peer\"\n"
399 " value {\n"
400 " struct_value {\n"
401 " fields {\n"
402 " key: \"address\"\n"
403 " value {\n"
404 " string_value: \"127.0.0.1\"\n"
405 " }\n"
406 " }\n"
407 " fields {\n"
408 " key: \"ipPort\"\n"
409 " value {\n"
410 " number_value: 12345\n"
411 " }\n"
412 " }\n"
413 " fields {\n"
414 " key: \"type\"\n"
415 " value {\n"
416 " string_value: \"TYPE_IPV4\"\n"
417 " }\n"
418 " }\n"
419 " }\n"
420 " }\n"
421 "}\n"
422 "fields {\n"
423 " key: \"sequenceId\"\n"
424 " value {\n"
425 " number_value: 1\n"
426 " }\n"
427 "}\n"
428 "fields {\n"
429 " key: \"serviceName\"\n"
430 " value {\n"
431 " string_value: \"service_name\"\n"
432 " }\n"
433 "}\n"
434 "fields {\n"
435 " key: \"type\"\n"
436 " value {\n"
437 " string_value: \"CLIENT_HEADER\"\n"
438 " }\n"
439 "}\n";
440 EXPECT_EQ(output, pb_str);
441 }
442
443 TEST(EntryToJsonStructTest, ServerHeader) {
444 LoggingSink::Entry entry;
445 entry.call_id = 1234;
446 entry.sequence_id = 2;
447 entry.type = LoggingSink::Entry::EventType::kServerHeader;
448 entry.logger = LoggingSink::Entry::Logger::kServer;
449 entry.payload.metadata["key"] = "value";
450 entry.peer.type = LoggingSink::Entry::Address::Type::kIpv4;
451 entry.peer.address = "127.0.0.1";
452 entry.peer.ip_port = 1234;
453 entry.authority = "authority";
454 entry.service_name = "service_name";
455 entry.method_name = "method_name";
456
457 google::protobuf::Struct proto;
458 EntryToJsonStructProto(std::move(entry), &proto);
459 std::string output;
460 ::google::protobuf::TextFormat::PrintToString(proto, &output);
461 const char* pb_str =
462 "fields {\n"
463 " key: \"authority\"\n"
464 " value {\n"
465 " string_value: \"authority\"\n"
466 " }\n"
467 "}\n"
468 "fields {\n"
469 " key: \"callId\"\n"
470 " value {\n"
471 " string_value: \"00000000-0000-4000-8000-0000000004d2\"\n"
472 " }\n"
473 "}\n"
474 "fields {\n"
475 " key: \"logger\"\n"
476 " value {\n"
477 " string_value: \"SERVER\"\n"
478 " }\n"
479 "}\n"
480 "fields {\n"
481 " key: \"methodName\"\n"
482 " value {\n"
483 " string_value: \"method_name\"\n"
484 " }\n"
485 "}\n"
486 "fields {\n"
487 " key: \"payload\"\n"
488 " value {\n"
489 " struct_value {\n"
490 " fields {\n"
491 " key: \"metadata\"\n"
492 " value {\n"
493 " struct_value {\n"
494 " fields {\n"
495 " key: \"key\"\n"
496 " value {\n"
497 " string_value: \"value\"\n"
498 " }\n"
499 " }\n"
500 " }\n"
501 " }\n"
502 " }\n"
503 " }\n"
504 " }\n"
505 "}\n"
506 "fields {\n"
507 " key: \"peer\"\n"
508 " value {\n"
509 " struct_value {\n"
510 " fields {\n"
511 " key: \"address\"\n"
512 " value {\n"
513 " string_value: \"127.0.0.1\"\n"
514 " }\n"
515 " }\n"
516 " fields {\n"
517 " key: \"ipPort\"\n"
518 " value {\n"
519 " number_value: 1234\n"
520 " }\n"
521 " }\n"
522 " fields {\n"
523 " key: \"type\"\n"
524 " value {\n"
525 " string_value: \"TYPE_IPV4\"\n"
526 " }\n"
527 " }\n"
528 " }\n"
529 " }\n"
530 "}\n"
531 "fields {\n"
532 " key: \"sequenceId\"\n"
533 " value {\n"
534 " number_value: 2\n"
535 " }\n"
536 "}\n"
537 "fields {\n"
538 " key: \"serviceName\"\n"
539 " value {\n"
540 " string_value: \"service_name\"\n"
541 " }\n"
542 "}\n"
543 "fields {\n"
544 " key: \"type\"\n"
545 " value {\n"
546 " string_value: \"SERVER_HEADER\"\n"
547 " }\n"
548 "}\n";
549 EXPECT_EQ(output, pb_str);
550 }
551
552 TEST(EntryToJsonStructTest, ClientMessage) {
553 LoggingSink::Entry entry;
554 entry.call_id = 1234;
555 entry.sequence_id = 3;
556 entry.type = LoggingSink::Entry::EventType::kClientMessage;
557 entry.logger = LoggingSink::Entry::Logger::kClient;
558 entry.payload.message = "hello";
559 entry.payload.message_length = 5;
560 entry.peer.type = LoggingSink::Entry::Address::Type::kIpv4;
561 entry.peer.address = "127.0.0.1";
562 entry.peer.ip_port = 1234;
563 entry.authority = "authority";
564 entry.service_name = "service_name";
565 entry.method_name = "method_name";
566
567 google::protobuf::Struct proto;
568 EntryToJsonStructProto(std::move(entry), &proto);
569 std::string output;
570 ::google::protobuf::TextFormat::PrintToString(proto, &output);
571 std::string pb_str = absl::StrFormat(
572 "fields {\n"
573 " key: \"authority\"\n"
574 " value {\n"
575 " string_value: \"authority\"\n"
576 " }\n"
577 "}\n"
578 "fields {\n"
579 " key: \"callId\"\n"
580 " value {\n"
581 " string_value: \"00000000-0000-4000-8000-0000000004d2\"\n"
582 " }\n"
583 "}\n"
584 "fields {\n"
585 " key: \"logger\"\n"
586 " value {\n"
587 " string_value: \"CLIENT\"\n"
588 " }\n"
589 "}\n"
590 "fields {\n"
591 " key: \"methodName\"\n"
592 " value {\n"
593 " string_value: \"method_name\"\n"
594 " }\n"
595 "}\n"
596 "fields {\n"
597 " key: \"payload\"\n"
598 " value {\n"
599 " struct_value {\n"
600 " fields {\n"
601 " key: \"message\"\n"
602 " value {\n"
603 " string_value: \"%s\"\n"
604 " }\n"
605 " }\n"
606 " fields {\n"
607 " key: \"messageLength\"\n"
608 " value {\n"
609 " number_value: 5\n"
610 " }\n"
611 " }\n"
612 " }\n"
613 " }\n"
614 "}\n"
615 "fields {\n"
616 " key: \"peer\"\n"
617 " value {\n"
618 " struct_value {\n"
619 " fields {\n"
620 " key: \"address\"\n"
621 " value {\n"
622 " string_value: \"127.0.0.1\"\n"
623 " }\n"
624 " }\n"
625 " fields {\n"
626 " key: \"ipPort\"\n"
627 " value {\n"
628 " number_value: 1234\n"
629 " }\n"
630 " }\n"
631 " fields {\n"
632 " key: \"type\"\n"
633 " value {\n"
634 " string_value: \"TYPE_IPV4\"\n"
635 " }\n"
636 " }\n"
637 " }\n"
638 " }\n"
639 "}\n"
640 "fields {\n"
641 " key: \"sequenceId\"\n"
642 " value {\n"
643 " number_value: 3\n"
644 " }\n"
645 "}\n"
646 "fields {\n"
647 " key: \"serviceName\"\n"
648 " value {\n"
649 " string_value: \"service_name\"\n"
650 " }\n"
651 "}\n"
652 "fields {\n"
653 " key: \"type\"\n"
654 " value {\n"
655 " string_value: \"CLIENT_MESSAGE\"\n"
656 " }\n"
657 "}\n",
658 absl::Base64Escape("hello"));
659 EXPECT_EQ(output, pb_str);
660 }
661
662 TEST(EntryToJsonStructTest, ServerMessage) {
663 LoggingSink::Entry entry;
664 entry.call_id = 1234;
665 entry.sequence_id = 4;
666 entry.type = LoggingSink::Entry::EventType::kServerMessage;
667 entry.logger = LoggingSink::Entry::Logger::kServer;
668 entry.payload.message = "world";
669 entry.payload.message_length = 5;
670 entry.peer.type = LoggingSink::Entry::Address::Type::kIpv4;
671 entry.peer.address = "127.0.0.1";
672 entry.peer.ip_port = 12345;
673 entry.authority = "authority";
674 entry.service_name = "service_name";
675 entry.method_name = "method_name";
676
677 google::protobuf::Struct proto;
678 EntryToJsonStructProto(std::move(entry), &proto);
679 std::string output;
680 ::google::protobuf::TextFormat::PrintToString(proto, &output);
681 std::string pb_str = absl::StrFormat(
682 "fields {\n"
683 " key: \"authority\"\n"
684 " value {\n"
685 " string_value: \"authority\"\n"
686 " }\n"
687 "}\n"
688 "fields {\n"
689 " key: \"callId\"\n"
690 " value {\n"
691 " string_value: \"00000000-0000-4000-8000-0000000004d2\"\n"
692 " }\n"
693 "}\n"
694 "fields {\n"
695 " key: \"logger\"\n"
696 " value {\n"
697 " string_value: \"SERVER\"\n"
698 " }\n"
699 "}\n"
700 "fields {\n"
701 " key: \"methodName\"\n"
702 " value {\n"
703 " string_value: \"method_name\"\n"
704 " }\n"
705 "}\n"
706 "fields {\n"
707 " key: \"payload\"\n"
708 " value {\n"
709 " struct_value {\n"
710 " fields {\n"
711 " key: \"message\"\n"
712 " value {\n"
713 " string_value: \"%s\"\n"
714 " }\n"
715 " }\n"
716 " fields {\n"
717 " key: \"messageLength\"\n"
718 " value {\n"
719 " number_value: 5\n"
720 " }\n"
721 " }\n"
722 " }\n"
723 " }\n"
724 "}\n"
725 "fields {\n"
726 " key: \"peer\"\n"
727 " value {\n"
728 " struct_value {\n"
729 " fields {\n"
730 " key: \"address\"\n"
731 " value {\n"
732 " string_value: \"127.0.0.1\"\n"
733 " }\n"
734 " }\n"
735 " fields {\n"
736 " key: \"ipPort\"\n"
737 " value {\n"
738 " number_value: 12345\n"
739 " }\n"
740 " }\n"
741 " fields {\n"
742 " key: \"type\"\n"
743 " value {\n"
744 " string_value: \"TYPE_IPV4\"\n"
745 " }\n"
746 " }\n"
747 " }\n"
748 " }\n"
749 "}\n"
750 "fields {\n"
751 " key: \"sequenceId\"\n"
752 " value {\n"
753 " number_value: 4\n"
754 " }\n"
755 "}\n"
756 "fields {\n"
757 " key: \"serviceName\"\n"
758 " value {\n"
759 " string_value: \"service_name\"\n"
760 " }\n"
761 "}\n"
762 "fields {\n"
763 " key: \"type\"\n"
764 " value {\n"
765 " string_value: \"SERVER_MESSAGE\"\n"
766 " }\n"
767 "}\n",
768 absl::Base64Escape("world"));
769 EXPECT_EQ(output, pb_str);
770 }
771
772 TEST(EntryToJsonStructTest, ClientHalfClose) {
773 LoggingSink::Entry entry;
774 entry.call_id = 1234;
775 entry.sequence_id = 5;
776 entry.type = LoggingSink::Entry::EventType::kClientHalfClose;
777 entry.logger = LoggingSink::Entry::Logger::kClient;
778 entry.peer.type = LoggingSink::Entry::Address::Type::kIpv4;
779 entry.peer.address = "127.0.0.1";
780 entry.peer.ip_port = 1234;
781 entry.authority = "authority";
782 entry.service_name = "service_name";
783 entry.method_name = "method_name";
784
785 google::protobuf::Struct proto;
786 EntryToJsonStructProto(std::move(entry), &proto);
787 std::string output;
788 ::google::protobuf::TextFormat::PrintToString(proto, &output);
789 const char* pb_str =
790 "fields {\n"
791 " key: \"authority\"\n"
792 " value {\n"
793 " string_value: \"authority\"\n"
794 " }\n"
795 "}\n"
796 "fields {\n"
797 " key: \"callId\"\n"
798 " value {\n"
799 " string_value: \"00000000-0000-4000-8000-0000000004d2\"\n"
800 " }\n"
801 "}\n"
802 "fields {\n"
803 " key: \"logger\"\n"
804 " value {\n"
805 " string_value: \"CLIENT\"\n"
806 " }\n"
807 "}\n"
808 "fields {\n"
809 " key: \"methodName\"\n"
810 " value {\n"
811 " string_value: \"method_name\"\n"
812 " }\n"
813 "}\n"
814 "fields {\n"
815 " key: \"payload\"\n"
816 " value {\n"
817 " struct_value {\n"
818 " }\n"
819 " }\n"
820 "}\n"
821 "fields {\n"
822 " key: \"peer\"\n"
823 " value {\n"
824 " struct_value {\n"
825 " fields {\n"
826 " key: \"address\"\n"
827 " value {\n"
828 " string_value: \"127.0.0.1\"\n"
829 " }\n"
830 " }\n"
831 " fields {\n"
832 " key: \"ipPort\"\n"
833 " value {\n"
834 " number_value: 1234\n"
835 " }\n"
836 " }\n"
837 " fields {\n"
838 " key: \"type\"\n"
839 " value {\n"
840 " string_value: \"TYPE_IPV4\"\n"
841 " }\n"
842 " }\n"
843 " }\n"
844 " }\n"
845 "}\n"
846 "fields {\n"
847 " key: \"sequenceId\"\n"
848 " value {\n"
849 " number_value: 5\n"
850 " }\n"
851 "}\n"
852 "fields {\n"
853 " key: \"serviceName\"\n"
854 " value {\n"
855 " string_value: \"service_name\"\n"
856 " }\n"
857 "}\n"
858 "fields {\n"
859 " key: \"type\"\n"
860 " value {\n"
861 " string_value: \"CLIENT_HALF_CLOSE\"\n"
862 " }\n"
863 "}\n";
864 EXPECT_EQ(output, pb_str);
865 }
866
867 TEST(EntryToJsonStructTest, ServerTrailer) {
868 LoggingSink::Entry entry;
869 entry.call_id = 1234;
870 entry.sequence_id = 6;
871 entry.type = LoggingSink::Entry::EventType::kServerTrailer;
872 entry.logger = LoggingSink::Entry::Logger::kServer;
873 entry.payload.metadata["key"] = "value";
874 entry.peer.type = LoggingSink::Entry::Address::Type::kIpv4;
875 entry.peer.address = "127.0.0.1";
876 entry.peer.ip_port = 1234;
877 entry.authority = "authority";
878 entry.service_name = "service_name";
879 entry.method_name = "method_name";
880
881 google::protobuf::Struct proto;
882 EntryToJsonStructProto(std::move(entry), &proto);
883 std::string output;
884 ::google::protobuf::TextFormat::PrintToString(proto, &output);
885 const char* pb_str =
886 "fields {\n"
887 " key: \"authority\"\n"
888 " value {\n"
889 " string_value: \"authority\"\n"
890 " }\n"
891 "}\n"
892 "fields {\n"
893 " key: \"callId\"\n"
894 " value {\n"
895 " string_value: \"00000000-0000-4000-8000-0000000004d2\"\n"
896 " }\n"
897 "}\n"
898 "fields {\n"
899 " key: \"logger\"\n"
900 " value {\n"
901 " string_value: \"SERVER\"\n"
902 " }\n"
903 "}\n"
904 "fields {\n"
905 " key: \"methodName\"\n"
906 " value {\n"
907 " string_value: \"method_name\"\n"
908 " }\n"
909 "}\n"
910 "fields {\n"
911 " key: \"payload\"\n"
912 " value {\n"
913 " struct_value {\n"
914 " fields {\n"
915 " key: \"metadata\"\n"
916 " value {\n"
917 " struct_value {\n"
918 " fields {\n"
919 " key: \"key\"\n"
920 " value {\n"
921 " string_value: \"value\"\n"
922 " }\n"
923 " }\n"
924 " }\n"
925 " }\n"
926 " }\n"
927 " }\n"
928 " }\n"
929 "}\n"
930 "fields {\n"
931 " key: \"peer\"\n"
932 " value {\n"
933 " struct_value {\n"
934 " fields {\n"
935 " key: \"address\"\n"
936 " value {\n"
937 " string_value: \"127.0.0.1\"\n"
938 " }\n"
939 " }\n"
940 " fields {\n"
941 " key: \"ipPort\"\n"
942 " value {\n"
943 " number_value: 1234\n"
944 " }\n"
945 " }\n"
946 " fields {\n"
947 " key: \"type\"\n"
948 " value {\n"
949 " string_value: \"TYPE_IPV4\"\n"
950 " }\n"
951 " }\n"
952 " }\n"
953 " }\n"
954 "}\n"
955 "fields {\n"
956 " key: \"sequenceId\"\n"
957 " value {\n"
958 " number_value: 6\n"
959 " }\n"
960 "}\n"
961 "fields {\n"
962 " key: \"serviceName\"\n"
963 " value {\n"
964 " string_value: \"service_name\"\n"
965 " }\n"
966 "}\n"
967 "fields {\n"
968 " key: \"type\"\n"
969 " value {\n"
970 " string_value: \"SERVER_TRAILER\"\n"
971 " }\n"
972 "}\n";
973 EXPECT_EQ(output, pb_str);
974 }
975
976 TEST(EntryToJsonStructTest, Cancel) {
977 LoggingSink::Entry entry;
978 entry.call_id = 1234;
979 entry.sequence_id = 7;
980 entry.type = LoggingSink::Entry::EventType::kCancel;
981 entry.logger = LoggingSink::Entry::Logger::kClient;
982 entry.peer.type = LoggingSink::Entry::Address::Type::kIpv4;
983 entry.peer.address = "127.0.0.1";
984 entry.peer.ip_port = 1234;
985 entry.authority = "authority";
986 entry.service_name = "service_name";
987 entry.method_name = "method_name";
988
989 google::protobuf::Struct proto;
990 EntryToJsonStructProto(std::move(entry), &proto);
991 std::string output;
992 ::google::protobuf::TextFormat::PrintToString(proto, &output);
993 const char* pb_str =
994 "fields {\n"
995 " key: \"authority\"\n"
996 " value {\n"
997 " string_value: \"authority\"\n"
998 " }\n"
999 "}\n"
1000 "fields {\n"
1001 " key: \"callId\"\n"
1002 " value {\n"
1003 " string_value: \"00000000-0000-4000-8000-0000000004d2\"\n"
1004 " }\n"
1005 "}\n"
1006 "fields {\n"
1007 " key: \"logger\"\n"
1008 " value {\n"
1009 " string_value: \"CLIENT\"\n"
1010 " }\n"
1011 "}\n"
1012 "fields {\n"
1013 " key: \"methodName\"\n"
1014 " value {\n"
1015 " string_value: \"method_name\"\n"
1016 " }\n"
1017 "}\n"
1018 "fields {\n"
1019 " key: \"payload\"\n"
1020 " value {\n"
1021 " struct_value {\n"
1022 " }\n"
1023 " }\n"
1024 "}\n"
1025 "fields {\n"
1026 " key: \"peer\"\n"
1027 " value {\n"
1028 " struct_value {\n"
1029 " fields {\n"
1030 " key: \"address\"\n"
1031 " value {\n"
1032 " string_value: \"127.0.0.1\"\n"
1033 " }\n"
1034 " }\n"
1035 " fields {\n"
1036 " key: \"ipPort\"\n"
1037 " value {\n"
1038 " number_value: 1234\n"
1039 " }\n"
1040 " }\n"
1041 " fields {\n"
1042 " key: \"type\"\n"
1043 " value {\n"
1044 " string_value: \"TYPE_IPV4\"\n"
1045 " }\n"
1046 " }\n"
1047 " }\n"
1048 " }\n"
1049 "}\n"
1050 "fields {\n"
1051 " key: \"sequenceId\"\n"
1052 " value {\n"
1053 " number_value: 7\n"
1054 " }\n"
1055 "}\n"
1056 "fields {\n"
1057 " key: \"serviceName\"\n"
1058 " value {\n"
1059 " string_value: \"service_name\"\n"
1060 " }\n"
1061 "}\n"
1062 "fields {\n"
1063 " key: \"type\"\n"
1064 " value {\n"
1065 " string_value: \"CANCEL\"\n"
1066 " }\n"
1067 "}\n";
1068 EXPECT_EQ(output, pb_str);
1069 }
1070
1071 } // namespace
1072
1073 } // namespace internal
1074 } // namespace grpc
1075
1076 int main(int argc, char** argv) {
1077 grpc::testing::TestEnvironment env(&argc, argv);
1078 ::testing::InitGoogleTest(&argc, argv);
1079 return RUN_ALL_TESTS();
1080 }
1081