Skip to content

Commit f159836

Browse files
authored
[lldb-dap] Adding logging helpers. (#130653)
Improving logging by defining new helpers for more uniform log handling. This should help us clearly identify log messages and helps abstract the underlying log type within the macro in case we want to update the log handler in the future.
1 parent 1324dfe commit f159836

File tree

5 files changed

+83
-56
lines changed

5 files changed

+83
-56
lines changed

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "DAP.h"
10+
#include "DAPLog.h"
1011
#include "Handler/ResponseHandler.h"
1112
#include "JSONUtils.h"
1213
#include "LLDBUtils.h"
@@ -25,6 +26,7 @@
2526
#include "llvm/ADT/ArrayRef.h"
2627
#include "llvm/ADT/ScopeExit.h"
2728
#include "llvm/ADT/StringExtras.h"
29+
#include "llvm/ADT/StringRef.h"
2830
#include "llvm/ADT/Twine.h"
2931
#include "llvm/Support/Error.h"
3032
#include "llvm/Support/ErrorHandling.h"
@@ -61,10 +63,10 @@ const char DEV_NULL[] = "/dev/null";
6163

6264
namespace lldb_dap {
6365

64-
DAP::DAP(std::string name, llvm::StringRef path, std::ofstream *log,
66+
DAP::DAP(llvm::StringRef client_name, llvm::StringRef path, std::ofstream *log,
6567
lldb::IOObjectSP input, lldb::IOObjectSP output, ReplMode repl_mode,
6668
std::vector<std::string> pre_init_commands)
67-
: name(std::move(name)), debug_adapter_path(path), log(log),
69+
: client_name(client_name), debug_adapter_path(path), log(log),
6870
input(std::move(input)), output(std::move(output)),
6971
broadcaster("lldb-dap"), exception_breakpoints(),
7072
pre_init_commands(std::move(pre_init_commands)),
@@ -239,14 +241,7 @@ void DAP::SendJSON(const llvm::json::Value &json) {
239241
std::lock_guard<std::mutex> locker(mutex);
240242
SendJSON(json_str);
241243

242-
if (log) {
243-
auto now = std::chrono::duration<double>(
244-
std::chrono::system_clock::now().time_since_epoch());
245-
*log << llvm::formatv("{0:f9} {1} <-- ", now.count(), name).str()
246-
<< std::endl
247-
<< "Content-Length: " << json_str.size() << "\r\n\r\n"
248-
<< llvm::formatv("{0:2}", json).str() << std::endl;
249-
}
244+
DAP_LOG(log, "({0}) <-- {1}", client_name, json_str);
250245
}
251246

252247
// Read a JSON packet from the "in" stream.
@@ -270,13 +265,7 @@ std::string DAP::ReadJSON() {
270265
if (!input.read_full(log, length, json_str))
271266
return json_str;
272267

273-
if (log) {
274-
auto now = std::chrono::duration<double>(
275-
std::chrono::system_clock::now().time_since_epoch());
276-
*log << llvm::formatv("{0:f9} {1} --> ", now.count(), name).str()
277-
<< std::endl
278-
<< "Content-Length: " << length << "\r\n\r\n";
279-
}
268+
DAP_LOG(log, "({0}) --> {1}", client_name, json_str);
280269
return json_str;
281270
}
282271

@@ -711,22 +700,15 @@ PacketStatus DAP::GetNextObject(llvm::json::Object &object) {
711700

712701
llvm::StringRef json_sref(json);
713702
llvm::Expected<llvm::json::Value> json_value = llvm::json::parse(json_sref);
714-
if (auto error = json_value.takeError()) {
715-
std::string error_str = llvm::toString(std::move(error));
716-
if (log)
717-
*log << "error: failed to parse JSON: " << error_str << std::endl
718-
<< json << std::endl;
703+
if (!json_value) {
704+
DAP_LOG_ERROR(log, json_value.takeError(),
705+
"({1}) failed to parse JSON: {0}", client_name);
719706
return PacketStatus::JSONMalformed;
720707
}
721708

722-
if (log) {
723-
*log << llvm::formatv("{0:2}", *json_value).str() << std::endl;
724-
}
725-
726709
llvm::json::Object *object_ptr = json_value->getAsObject();
727710
if (!object_ptr) {
728-
if (log)
729-
*log << "error: json packet isn't a object" << std::endl;
711+
DAP_LOG(log, "({0}) error: json packet isn't a object", client_name);
730712
return PacketStatus::JSONNotObject;
731713
}
732714
object = *object_ptr;
@@ -744,9 +726,7 @@ bool DAP::HandleObject(const llvm::json::Object &object) {
744726
return true; // Success
745727
}
746728

747-
if (log)
748-
*log << "error: unhandled command \"" << command.data() << "\""
749-
<< std::endl;
729+
DAP_LOG(log, "({0}) error: unhandled command '{1}'", client_name, command);
750730
return false; // Fail
751731
}
752732

lldb/tools/lldb-dap/DAP.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ struct SendEventRequestHandler : public lldb::SBCommandPluginInterface {
145145
};
146146

147147
struct DAP {
148-
std::string name;
148+
llvm::StringRef client_name;
149149
llvm::StringRef debug_adapter_path;
150150
std::ofstream *log;
151151
InputStream input;
@@ -210,7 +210,7 @@ struct DAP {
210210
// will contain that expression.
211211
std::string last_nonempty_var_expression;
212212

213-
DAP(std::string name, llvm::StringRef path, std::ofstream *log,
213+
DAP(llvm::StringRef client_name, llvm::StringRef path, std::ofstream *log,
214214
lldb::IOObjectSP input, lldb::IOObjectSP output, ReplMode repl_mode,
215215
std::vector<std::string> pre_init_commands);
216216
~DAP();

lldb/tools/lldb-dap/DAPLog.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//===-- DAPLog.h ----------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLDB_TOOLS_LLDB_DAP_DAPLOG_H
10+
#define LLDB_TOOLS_LLDB_DAP_DAPLOG_H
11+
12+
#include "llvm/Support/Error.h"
13+
#include "llvm/Support/FormatAdapters.h"
14+
#include "llvm/Support/FormatVariadic.h"
15+
#include <chrono>
16+
#include <fstream>
17+
#include <string>
18+
19+
// Write a message to log, if logging is enabled.
20+
#define DAP_LOG(log, ...) \
21+
do { \
22+
::std::ofstream *log_private = (log); \
23+
if (log_private) { \
24+
::std::chrono::duration<double> now{ \
25+
::std::chrono::system_clock::now().time_since_epoch()}; \
26+
*log_private << ::llvm::formatv("{0:f9} ", now.count()).str() \
27+
<< ::llvm::formatv(__VA_ARGS__).str() << std::endl; \
28+
} \
29+
} while (0)
30+
31+
// Write message to log, if error is set. In the log message refer to the error
32+
// with {0}. Error is cleared regardless of whether logging is enabled.
33+
#define DAP_LOG_ERROR(log, error, ...) \
34+
do { \
35+
::std::ofstream *log_private = (log); \
36+
::llvm::Error error_private = (error); \
37+
if (log_private && error_private) { \
38+
::std::chrono::duration<double> now{ \
39+
std::chrono::system_clock::now().time_since_epoch()}; \
40+
*log_private << ::llvm::formatv("{0:f9} ", now.count()).str() \
41+
<< ::lldb_dap::FormatError(::std::move(error_private), \
42+
__VA_ARGS__) \
43+
<< std::endl; \
44+
} else \
45+
::llvm::consumeError(::std::move(error_private)); \
46+
} while (0)
47+
48+
namespace lldb_dap {
49+
50+
template <typename... Args>
51+
inline auto FormatError(llvm::Error error, const char *format, Args &&...args) {
52+
return llvm::formatv(format, llvm::toString(std::move(error)),
53+
std::forward<Args>(args)...)
54+
.str();
55+
}
56+
} // namespace lldb_dap
57+
58+
#endif

lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ void ProgressEventThreadFunction(DAP &dap) {
111111
// them prevent multiple threads from writing simultaneously so no locking
112112
// is required.
113113
static void EventThreadFunction(DAP &dap) {
114-
llvm::set_thread_name(dap.name + ".event_handler");
114+
llvm::set_thread_name(dap.client_name + ".event_handler");
115115
lldb::SBEvent event;
116116
lldb::SBListener listener = dap.debugger.GetListener();
117117
dap.broadcaster.AddListener(listener, eBroadcastBitStopEventThread);

lldb/tools/lldb-dap/lldb-dap.cpp

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "DAP.h"
10+
#include "DAPLog.h"
1011
#include "EventHelper.h"
1112
#include "Handler/RequestHandler.h"
1213
#include "RunInTerminal.h"
@@ -294,8 +295,7 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
294295
}
295296

296297
std::string address = llvm::join(listener->GetListeningConnectionURI(), ", ");
297-
if (log)
298-
*log << "started with connection listeners " << address << "\n";
298+
DAP_LOG(log, "started with connection listeners {0}", address);
299299

300300
llvm::outs() << "Listening for: " << address << "\n";
301301
// Ensure listening address are flushed for calles to retrieve the resolve
@@ -315,22 +315,17 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
315315
&dap_sessions_mutex, &dap_sessions,
316316
&clientCount](
317317
std::unique_ptr<Socket> sock) {
318-
std::string name = llvm::formatv("client_{0}", clientCount++).str();
319-
if (log) {
320-
auto now = std::chrono::duration<double>(
321-
std::chrono::system_clock::now().time_since_epoch());
322-
*log << llvm::formatv("{0:f9}", now.count()).str()
323-
<< " client connected: " << name << "\n";
324-
}
318+
std::string client_name = llvm::formatv("client_{0}", clientCount++).str();
319+
DAP_LOG(log, "({0}) client connected", client_name);
325320

326321
lldb::IOObjectSP io(std::move(sock));
327322

328323
// Move the client into a background thread to unblock accepting the next
329324
// client.
330325
std::thread client([=, &dap_sessions_condition, &dap_sessions_mutex,
331326
&dap_sessions]() {
332-
llvm::set_thread_name(name + ".runloop");
333-
DAP dap = DAP(name, program_path, log, io, io, default_repl_mode,
327+
llvm::set_thread_name(client_name + ".runloop");
328+
DAP dap = DAP(client_name, program_path, log, io, io, default_repl_mode,
334329
pre_init_commands);
335330

336331
if (auto Err = dap.ConfigureIO()) {
@@ -351,13 +346,7 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
351346
"DAP session error: ");
352347
}
353348

354-
if (log) {
355-
auto now = std::chrono::duration<double>(
356-
std::chrono::system_clock::now().time_since_epoch());
357-
*log << llvm::formatv("{0:f9}", now.count()).str()
358-
<< " client closed: " << name << "\n";
359-
}
360-
349+
DAP_LOG(log, "({0}) client disconnected", client_name);
361350
std::unique_lock<std::mutex> lock(dap_sessions_mutex);
362351
dap_sessions.erase(io.get());
363352
std::notify_all_at_thread_exit(dap_sessions_condition, std::move(lock));
@@ -374,9 +363,9 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
374363
return status.takeError();
375364
}
376365

377-
if (log)
378-
*log << "lldb-dap server shutdown requested, disconnecting remaining "
379-
"clients...\n";
366+
DAP_LOG(
367+
log,
368+
"lldb-dap server shutdown requested, disconnecting remaining clients...");
380369

381370
bool client_failed = false;
382371
{
@@ -385,7 +374,7 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
385374
auto error = dap->Disconnect();
386375
if (error.Fail()) {
387376
client_failed = true;
388-
llvm::errs() << "DAP client " << dap->name
377+
llvm::errs() << "DAP client " << dap->client_name
389378
<< " disconnected failed: " << error.GetCString() << "\n";
390379
}
391380
// Close the socket to ensure the DAP::Loop read finishes.

0 commit comments

Comments
 (0)