Skip to content

Commit 686d8a0

Browse files
committed
[clangd] Add index server request logging
- Add verbose logging of payloads - Add public logging of request summaries - fix non-logging of messages in request scopes (oops!) - add test for public/non-public logging, extending pipeline_helper a bit. We've accumulated quite a lot of duplication in the request handlers by now. I should factor that out, but not in this patch... Differential Revision: https://reviews.llvm.org/D90654
1 parent e5ec94a commit 686d8a0

File tree

3 files changed

+86
-7
lines changed

3 files changed

+86
-7
lines changed

clang-tools-extra/clangd/index/remote/server/Server.cpp

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,14 @@ class RemoteIndexServer final : public v1::SymbolIndex::Service {
9494
}
9595

9696
private:
97+
using stopwatch = std::chrono::steady_clock;
98+
9799
grpc::Status Lookup(grpc::ServerContext *Context,
98100
const LookupRequest *Request,
99101
grpc::ServerWriter<LookupReply> *Reply) override {
100-
WithContextValue(CurrentRequest, Context);
102+
auto StartTime = stopwatch::now();
103+
WithContextValue WithRequestContext(CurrentRequest, Context);
104+
logRequest(*Request);
101105
trace::Span Tracer("LookupRequest");
102106
auto Req = ProtobufMarshaller->fromProtobuf(Request);
103107
if (!Req) {
@@ -116,21 +120,26 @@ class RemoteIndexServer final : public v1::SymbolIndex::Service {
116120
}
117121
LookupReply NextMessage;
118122
*NextMessage.mutable_stream_result() = *SerializedItem;
123+
logResponse(NextMessage);
119124
Reply->Write(NextMessage);
120125
++Sent;
121126
});
122127
LookupReply LastMessage;
123128
LastMessage.mutable_final_result()->set_has_more(true);
129+
logResponse(LastMessage);
124130
Reply->Write(LastMessage);
125131
SPAN_ATTACH(Tracer, "Sent", Sent);
126132
SPAN_ATTACH(Tracer, "Failed to send", FailedToSend);
133+
logRequestSummary("v1/Lookup", Sent, StartTime);
127134
return grpc::Status::OK;
128135
}
129136

130137
grpc::Status FuzzyFind(grpc::ServerContext *Context,
131138
const FuzzyFindRequest *Request,
132139
grpc::ServerWriter<FuzzyFindReply> *Reply) override {
133-
WithContextValue(CurrentRequest, Context);
140+
auto StartTime = stopwatch::now();
141+
WithContextValue WithRequestContext(CurrentRequest, Context);
142+
logRequest(*Request);
134143
trace::Span Tracer("FuzzyFindRequest");
135144
auto Req = ProtobufMarshaller->fromProtobuf(Request);
136145
if (!Req) {
@@ -150,20 +159,25 @@ class RemoteIndexServer final : public v1::SymbolIndex::Service {
150159
}
151160
FuzzyFindReply NextMessage;
152161
*NextMessage.mutable_stream_result() = *SerializedItem;
162+
logResponse(NextMessage);
153163
Reply->Write(NextMessage);
154164
++Sent;
155165
});
156166
FuzzyFindReply LastMessage;
157167
LastMessage.mutable_final_result()->set_has_more(HasMore);
168+
logResponse(LastMessage);
158169
Reply->Write(LastMessage);
159170
SPAN_ATTACH(Tracer, "Sent", Sent);
160171
SPAN_ATTACH(Tracer, "Failed to send", FailedToSend);
172+
logRequestSummary("v1/FuzzyFind", Sent, StartTime);
161173
return grpc::Status::OK;
162174
}
163175

164176
grpc::Status Refs(grpc::ServerContext *Context, const RefsRequest *Request,
165177
grpc::ServerWriter<RefsReply> *Reply) override {
166-
WithContextValue(CurrentRequest, Context);
178+
auto StartTime = stopwatch::now();
179+
WithContextValue WithRequestContext(CurrentRequest, Context);
180+
logRequest(*Request);
167181
trace::Span Tracer("RefsRequest");
168182
auto Req = ProtobufMarshaller->fromProtobuf(Request);
169183
if (!Req) {
@@ -182,21 +196,26 @@ class RemoteIndexServer final : public v1::SymbolIndex::Service {
182196
}
183197
RefsReply NextMessage;
184198
*NextMessage.mutable_stream_result() = *SerializedItem;
199+
logResponse(NextMessage);
185200
Reply->Write(NextMessage);
186201
++Sent;
187202
});
188203
RefsReply LastMessage;
189204
LastMessage.mutable_final_result()->set_has_more(HasMore);
205+
logResponse(LastMessage);
190206
Reply->Write(LastMessage);
191207
SPAN_ATTACH(Tracer, "Sent", Sent);
192208
SPAN_ATTACH(Tracer, "Failed to send", FailedToSend);
209+
logRequestSummary("v1/Refs", Sent, StartTime);
193210
return grpc::Status::OK;
194211
}
195212

196213
grpc::Status Relations(grpc::ServerContext *Context,
197214
const RelationsRequest *Request,
198215
grpc::ServerWriter<RelationsReply> *Reply) override {
199-
WithContextValue(CurrentRequest, Context);
216+
auto StartTime = stopwatch::now();
217+
WithContextValue WithRequestContext(CurrentRequest, Context);
218+
logRequest(*Request);
200219
trace::Span Tracer("RelationsRequest");
201220
auto Req = ProtobufMarshaller->fromProtobuf(Request);
202221
if (!Req) {
@@ -217,17 +236,44 @@ class RemoteIndexServer final : public v1::SymbolIndex::Service {
217236
}
218237
RelationsReply NextMessage;
219238
*NextMessage.mutable_stream_result() = *SerializedItem;
239+
logResponse(NextMessage);
220240
Reply->Write(NextMessage);
221241
++Sent;
222242
});
223243
RelationsReply LastMessage;
224244
LastMessage.mutable_final_result()->set_has_more(true);
245+
logResponse(LastMessage);
225246
Reply->Write(LastMessage);
226247
SPAN_ATTACH(Tracer, "Sent", Sent);
227248
SPAN_ATTACH(Tracer, "Failed to send", FailedToSend);
249+
logRequestSummary("v1/Relations", Sent, StartTime);
228250
return grpc::Status::OK;
229251
}
230252

253+
// Proxy object to allow proto messages to be lazily serialized as text.
254+
struct TextProto {
255+
const google::protobuf::Message &M;
256+
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
257+
const TextProto &P) {
258+
return OS << P.M.DebugString();
259+
}
260+
};
261+
262+
void logRequest(const google::protobuf::Message &M) {
263+
vlog("<<< {0}\n{1}", M.GetDescriptor()->name(), TextProto{M});
264+
}
265+
void logResponse(const google::protobuf::Message &M) {
266+
vlog(">>> {0}\n{1}", M.GetDescriptor()->name(), TextProto{M});
267+
}
268+
void logRequestSummary(llvm::StringLiteral RequestName, unsigned Sent,
269+
stopwatch::time_point StartTime) {
270+
auto Duration = stopwatch::now() - StartTime;
271+
auto Millis =
272+
std::chrono::duration_cast<std::chrono::milliseconds>(Duration).count();
273+
log("[public] request {0} => OK: {1} results in {2}ms", RequestName, Sent,
274+
Millis);
275+
}
276+
231277
std::unique_ptr<Marshaller> ProtobufMarshaller;
232278
clangd::SymbolIndex &Index;
233279
};

clang-tools-extra/clangd/test/remote-index/pipeline_helper.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ def main():
2828
parser.add_argument('--input-file-name', required=True)
2929
parser.add_argument('--project-root', required=True)
3030
parser.add_argument('--index-file', required=True)
31+
parser.add_argument('--server-arg', action='append', default=[])
32+
parser.add_argument('--server-log', nargs='?', type=argparse.FileType('wb'), default=os.devnull)
3133

3234
args = parser.parse_args()
3335

@@ -40,7 +42,7 @@ def main():
4042
index_server_process = subprocess.Popen([
4143
'clangd-index-server', '--server-address=' + server_address,
4244
args.index_file, args.project_root
43-
],
45+
] + args.server_arg,
4446
stderr=subprocess.PIPE)
4547

4648
# This will kill index_server_process if it hangs without printing init
@@ -53,7 +55,10 @@ def main():
5355
# Wait for the server to warm-up.
5456
found_init_message = False
5557
while index_server_process.poll() is None:
56-
if b'Server listening' in index_server_process.stderr.readline():
58+
line = index_server_process.stderr.readline()
59+
args.server_log.write(line)
60+
args.server_log.flush()
61+
if b'Server listening' in line:
5762
print('Server initialization complete.', file=sys.stderr)
5863
found_init_message = True
5964
break
@@ -70,12 +75,14 @@ def main():
7075
'--project-root=' + args.project_root, '--lit-test', '--sync'
7176
],
7277
stdin=in_file)
73-
7478
clangd_process.wait()
7579
print(
7680
'Clangd executed successfully, shutting down child processes.',
7781
file=sys.stderr)
7882
index_server_process.kill()
83+
for line in index_server_process.stderr:
84+
args.server_log.write(line)
85+
args.server_log.flush()
7986

8087

8188
if __name__ == '__main__':
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# RUN: rm -rf %t
2+
# RUN: clangd-indexer %S/Inputs/Source.cpp > %t.idx
3+
# RUN: %python %S/pipeline_helper.py --input-file-name=%s --server-arg=--log=verbose --server-arg=-log-public --server-log=%t.public.log --project-root=%S --index-file=%t.idx > /dev/null
4+
# RUN: %python %S/pipeline_helper.py --input-file-name=%s --server-arg=--log=verbose --server-log=%t.log --project-root=%S --index-file=%t.idx > /dev/null
5+
# RUN: FileCheck --check-prefixes=LOG,LOG-PUBLIC %s < %t.public.log
6+
# RUN: FileCheck --check-prefixes=LOG,LOG-ALL %s < %t.log
7+
# REQUIRES: clangd-remote-index
8+
9+
# LOG: Server listening on
10+
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
11+
---
12+
# Verify that request and response bodies are included in the verbose logs,
13+
# but not when --log-public is on.
14+
# The request summary should be included in either case.
15+
{"jsonrpc":"2.0","id":1,"method":"workspace/symbol","params":{"query":"gFoo"}}
16+
# LOG-ALL: <<< FuzzyFindRequest
17+
# LOG-ALL: query: "gFoo"
18+
# LOG-ALL: >>> FuzzyFindReply
19+
# LOG-ALL: name: "getFoo"
20+
# LOG-PUBLIC-NOT: gFoo
21+
# LOG-PUBLIC-NOT: getFoo
22+
# LOG: request v1/FuzzyFind => OK: 1 results in {{.*}}ms
23+
---
24+
{"jsonrpc":"2.0","id":4,"method":"shutdown"}
25+
---
26+
{"jsonrpc":"2.0","method":"exit"}

0 commit comments

Comments
 (0)