• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //
3 // Copyright 2016 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 #include <grpc/grpc.h>
20 #include <grpc/status.h>
21 
22 #include <atomic>
23 #include <map>
24 #include <regex>
25 #include <string>
26 #include <utility>
27 
28 #include "absl/log/check.h"
29 #include "absl/log/globals.h"
30 #include "absl/log/log.h"
31 #include "absl/log/log_entry.h"
32 #include "absl/log/log_sink.h"
33 #include "absl/log/log_sink_registry.h"
34 #include "absl/strings/str_cat.h"
35 #include "absl/strings/string_view.h"
36 #include "absl/types/optional.h"
37 #include "gtest/gtest.h"
38 #include "src/core/lib/debug/trace.h"
39 #include "src/core/util/time.h"
40 #include "test/core/end2end/end2end_tests.h"
41 
42 namespace grpc_core {
43 
44 class VerifyLogNoiseLogSink : public absl::LogSink {
45  public:
VerifyLogNoiseLogSink(const absl::LogSeverityAtLeast severity,const int verbosity)46   explicit VerifyLogNoiseLogSink(const absl::LogSeverityAtLeast severity,
47                                  const int verbosity)
48       : log_noise_absent_(true) {
49     saved_absl_severity_ = absl::MinLogLevel();
50     absl::SetMinLogLevel(severity);
51     // SetGlobalVLogLevel sets verbosity and returns previous verbosity.
52     saved_absl_verbosity_ = absl::SetGlobalVLogLevel(verbosity);
53     grpc_tracer_set_enabled("all", false);
54     absl::AddLogSink(this);
55   }
56 
~VerifyLogNoiseLogSink()57   ~VerifyLogNoiseLogSink() override {
58     CHECK(log_noise_absent_)
59         << "Unwanted logs present. This will cause log noise. Either user a "
60            "tracer (example GRPC_TRACE_LOG or GRPC_TRACE_VLOG) or convert the "
61            "statement to VLOG(2).";
62     //  Reverse everything done in the constructor.
63     absl::RemoveLogSink(this);
64     saved_trace_flags_.Restore();
65     absl::SetGlobalVLogLevel(saved_absl_verbosity_);
66     absl::SetMinLogLevel(saved_absl_severity_);
67   }
68 
69   // This function is called each time LOG or VLOG is called.
Send(const absl::LogEntry & entry)70   void Send(const absl::LogEntry& entry) override { CheckForNoisyLogs(entry); }
71 
72   VerifyLogNoiseLogSink(const VerifyLogNoiseLogSink& other) = delete;
73   VerifyLogNoiseLogSink& operator=(const VerifyLogNoiseLogSink& other) = delete;
74 
75  private:
IsVlogWithVerbosityMoreThan1(const absl::LogEntry & entry) const76   bool IsVlogWithVerbosityMoreThan1(const absl::LogEntry& entry) const {
77     return entry.log_severity() == absl::LogSeverity::kInfo &&
78            entry.verbosity() >= 1;
79   }
80 
CheckForNoisyLogs(const absl::LogEntry & entry)81   void CheckForNoisyLogs(const absl::LogEntry& entry) {
82     // TODO(tjagtap) : Add a hard upper limit on number of times each log should
83     // appear. We can keep this number slightly higher to avoid our tests
84     // becoming flaky. Right now all entries in this list get a free pass to log
85     // infinitely - That may create log noise issues in the future.
86     //
87     // This list is an allow list of all LOG(INFO), LOG(WARNING), and LOG(ERROR)
88     // logs which will appear. For now we have decided to allow these instances.
89     // We should be very conservative while adding new entries to this list,
90     // because this has potential to cause massive log noise. Several users are
91     // using INFO log level setting for production.
92     static const auto* const allowed_logs_by_module =
93         new std::map<absl::string_view, std::regex>(
94             {{"cq_verifier.cc", std::regex("^Verify .* for [0-9]+ms")},
95              {"chaotic_good_server.cc",
96               std::regex("Failed to bind some addresses for.*")},
97              {"log.cc",
98               std::regex("Prefer WARNING or ERROR. However if you see this "
99                          "message in a debug environment or test environment "
100                          "it is safe to ignore this message.")}});
101 
102     if (IsVlogWithVerbosityMoreThan1(entry)) {
103       return;
104     }
105 
106     absl::string_view filename = entry.source_filename();
107     auto slash = filename.rfind('/');
108     if (slash != absl::string_view::npos) {
109       filename = filename.substr(slash + 1);
110     }
111     slash = filename.rfind('\\');
112     if (slash != absl::string_view::npos) {
113       filename = filename.substr(slash + 1);
114     }
115     auto it = allowed_logs_by_module->find(filename);
116     if (it != allowed_logs_by_module->end() &&
117         std::regex_search(std::string(entry.text_message()), it->second)) {
118       return;
119     }
120 
121     // If we reach here means we have log noise. log_noise_absent_ will make the
122     // test fail.
123     log_noise_absent_ = false;
124     LOG(ERROR) << "�� Unwanted log at location : " << entry.source_filename()
125                << ":" << entry.source_line() << " " << entry.text_message();
126   }
127 
128   absl::LogSeverityAtLeast saved_absl_severity_;
129   int saved_absl_verbosity_;
130   SavedTraceFlags saved_trace_flags_;
131   bool log_noise_absent_;
132 };
133 
SimpleRequest(CoreEnd2endTest & test)134 void SimpleRequest(CoreEnd2endTest& test) {
135   auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
136   EXPECT_NE(c.GetPeer(), absl::nullopt);
137   IncomingMetadata server_initial_metadata;
138   IncomingStatusOnClient server_status;
139   c.NewBatch(1)
140       .SendInitialMetadata({})
141       .SendCloseFromClient()
142       .RecvInitialMetadata(server_initial_metadata)
143       .RecvStatusOnClient(server_status);
144   auto s = test.RequestCall(101);
145   test.Expect(101, true);
146   test.Step();
147   EXPECT_NE(c.GetPeer(), absl::nullopt);
148   EXPECT_NE(s.GetPeer(), absl::nullopt);
149   IncomingCloseOnServer client_close;
150   s.NewBatch(102)
151       .SendInitialMetadata({})
152       .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {})
153       .RecvCloseOnServer(client_close);
154   test.Expect(102, true);
155   test.Expect(1, true);
156   test.Step();
157   EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED);
158   EXPECT_EQ(server_status.message(), "xyz");
159   EXPECT_EQ(s.method(), "/foo");
160   EXPECT_FALSE(client_close.was_cancelled());
161 }
162 
CORE_END2END_TEST(NoLoggingTest,NoLoggingTest)163 CORE_END2END_TEST(NoLoggingTest, NoLoggingTest) {
164 // This test makes sure that we don't get log noise when making an rpc
165 // especially when rpcs are successful.
166 
167 // TODO(hork): remove when the listener flake is identified
168 #ifdef GPR_WINDOWS
169   if (IsEventEngineListenerEnabled()) {
170     GTEST_SKIP() << "not for windows + event engine listener";
171   }
172 #endif
173   VerifyLogNoiseLogSink nolog_verifier(absl::LogSeverityAtLeast::kInfo, 2);
174   for (int i = 0; i < 10; i++) {
175     SimpleRequest(*this);
176   }
177 }
178 
179 }  // namespace grpc_core
180