//===-- 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/Core/Telemetry.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/UUID.h" #include "lldb/Version/Version.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 #include #include #include #include namespace lldb_private { namespace telemetry { using namespace llvm::telemetry; static uint64_t ToNanosec(const SteadyTimePoint Point) { return std::chrono::nanoseconds(Point.time_since_epoch()).count(); } // Generate a unique string. This should be unique across different runs. // We build such string by combining three parts: // <16 random bytes>_ // This reduces the chances of getting the same UUID, even when the same // user runs the two copies of binary at the same time. static std::string MakeUUID() { uint8_t random_bytes[16]; std::string randomString = "_"; if (auto ec = llvm::getRandomBytes(random_bytes, 16)) { LLDB_LOG(GetLog(LLDBLog::Object), "Failed to generate random bytes for UUID: {0}", ec.message()); } else { randomString = UUID(random_bytes).GetAsString(); } return llvm::formatv( "{0}_{1}", randomString, std::chrono::steady_clock::now().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())); } void DebuggerInfo::serialize(Serializer &serializer) const { LLDBBaseTelemetryInfo::serialize(serializer); serializer.write("lldb_version", lldb_version); serializer.write("is_exit_entry", is_exit_entry); } TelemetryManager::TelemetryManager(std::unique_ptr config) : m_config(std::move(config)), m_id(MakeUUID()) {} llvm::Error TelemetryManager::preDispatch(TelemetryInfo *entry) { // Assign the manager_id, and debugger_id, if available, to this entry. LLDBBaseTelemetryInfo *lldb_entry = llvm::cast(entry); lldb_entry->SessionId = m_id; if (Debugger *debugger = lldb_entry->debugger) lldb_entry->debugger_id = debugger->GetID(); return llvm::Error::success(); } const Config *TelemetryManager::GetConfig() { return m_config.get(); } std::unique_ptr TelemetryManager::g_instance = nullptr; TelemetryManager *TelemetryManager::GetInstance() { if (!Config::BuildTimeEnableTelemetry) return nullptr; return g_instance.get(); } TelemetryManager *TelemetryManager::GetInstanceIfEnabled() { // Telemetry may be enabled at build time but disabled at runtime. if (TelemetryManager *ins = TelemetryManager::GetInstance()) { if (ins->GetConfig()->EnableTelemetry) return ins; } return nullptr; } void TelemetryManager::SetInstance(std::unique_ptr manager) { if (Config::BuildTimeEnableTelemetry) g_instance = std::move(manager); } } // namespace telemetry } // namespace lldb_private