Skip to content

[lldb][telemetry] Implement LLDB Telemetry (part 1) #119716

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions lldb/include/lldb/Core/Telemetry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//===-- Telemetry.h -------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_CORE_TELEMETRY_H
#define LLDB_CORE_TELEMETRY_H

#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/lldb-forward.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/JSON.h"
#include "llvm/Telemetry/Telemetry.h"
#include <chrono>
#include <ctime>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>

namespace lldb_private {
namespace telemetry {

struct LLDBEntryKind : public ::llvm::telemetry::EntryKind {
static const llvm::telemetry::KindType BaseInfo = 0b11000;
};

/// Defines a convenient type for timestamp of various events.
using SteadyTimePoint = std::chrono::time_point<std::chrono::steady_clock,
std::chrono::nanoseconds>;
struct LLDBBaseTelemetryInfo : public llvm::telemetry::TelemetryInfo {
/// Start time of an event
SteadyTimePoint start_time;
/// End time of an event - may be empty if not meaningful.
std::optional<SteadyTimePoint> end_time;
// TBD: could add some memory stats here too?

Debugger *debugger;

// For dyn_cast, isa, etc operations.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everywhere else we use /// LLVM RTTI support.

llvm::telemetry::KindType getKind() const override {
return LLDBEntryKind::BaseInfo;
}

static bool classof(const llvm::telemetry::TelemetryInfo *t) {
// Subclasses of this is also acceptable.
return (t->getKind() & LLDBEntryKind::BaseInfo) == LLDBEntryKind::BaseInfo;
}

void serialize(llvm::telemetry::Serializer &serializer) const override;
};

/// The base Telemetry manager instance in LLDB
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: missing period.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

/// This class declares additional instrumentation points
/// applicable to LLDB.
class TelemetryManager : public llvm::telemetry::Manager {
public:
TelemetryManager(std::unique_ptr<llvm::telemetry::Config> config);

llvm::Error preDispatch(llvm::telemetry::TelemetryInfo *entry) override;

private:
std::unique_ptr<llvm::telemetry::Config> m_config;
};

} // namespace telemetry
} // namespace lldb_private
#endif // LLDB_CORE_TELEMETRY_H
9 changes: 8 additions & 1 deletion lldb/source/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ if (LLDB_ENABLE_CURSES)
endif()
endif()

if (LLVM_BUILD_TELEMETRY)
set(TELEMETRY_SOURCES Telemetry.cpp)
set(TELEMETRY_DEPS Telemetry)
endif()

# TODO: Add property `NO_PLUGIN_DEPENDENCIES` to lldbCore
add_lldb_library(lldbCore
Address.cpp
Expand Down Expand Up @@ -55,7 +60,8 @@ add_lldb_library(lldbCore
ThreadedCommunication.cpp
UserSettingsController.cpp
Value.cpp

${TELEMETRY_SOURCES}
PARTIAL_SOURCES_INTENDED
DEPENDS
clang-tablegen-targets

Expand All @@ -80,6 +86,7 @@ add_lldb_library(lldbCore
Support
Demangle
TargetParser
${TELEMETRY_DEPS}
)

add_dependencies(lldbCore
Expand Down
69 changes: 69 additions & 0 deletions lldb/source/Core/Telemetry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//===-- Telemetry.cpp -----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/Telemetry.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/UUID.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/RandomNumberGenerator.h"
#include "llvm/Telemetry/Telemetry.h"
#include <chrono>
#include <cstdlib>
#include <memory>
#include <string>
#include <utility>

namespace lldb_private {
namespace telemetry {

using ::llvm::Error;
using ::llvm::telemetry::Destination;
using ::llvm::telemetry::Serializer;
using ::llvm::telemetry::TelemetryInfo;

static uint64_t ToNanosec(const SteadyTimePoint Point) {
return std::chrono::nanoseconds(Point.time_since_epoch()).count();
}

void LLDBBaseTelemetryInfo::serialize(Serializer &serializer) const {
serializer.write("entry_kind", getKind());
serializer.write("session_id", SessionId);
serializer.write("start_time", ToNanosec(start_time));
if (end_time.has_value())
serializer.write("end_time", ToNanosec(end_time.value()));
}

static std::string MakeUUID(lldb_private::Debugger *debugger) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/lldb_private:://, goes for the whole file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(all addressed in #126757)

uint8_t random_bytes[16];
if (auto ec = llvm::getRandomBytes(random_bytes, 16)) {
LLDB_LOG(GetLog(LLDBLog::Object),
"Failed to generate random bytes for UUID: {0}", ec.message());
// fallback to using timestamp + debugger ID.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/fallback/Fallback/

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return llvm::formatv(
"{0}_{1}", std::chrono::steady_clock::now().time_since_epoch().count(),
debugger->GetID());
}
return lldb_private::UUID(random_bytes).GetAsString();
}

TelemetryManager::TelemetryManager(
std::unique_ptr<llvm::telemetry::Config> config)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're using using ::llvm::telemetry::Foo for some other things but not for the Config. Why not use using namespace llvm::telemetry instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

: m_config(std::move(config)) {}

llvm::Error TelemetryManager::preDispatch(TelemetryInfo *entry) {
// Do nothing for now.
// In up-coming patch, this would be where the manager
// attach the session_uuid to the entry.
return Error::success();
}

} // namespace telemetry
} // namespace lldb_private