diff --git a/eden/common/telemetry/SessionId.cpp b/eden/common/telemetry/SessionId.cpp new file mode 100644 index 00000000..31fef43a --- /dev/null +++ b/eden/common/telemetry/SessionId.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "eden/common/telemetry/SessionId.h" +#include + +namespace { + +uint32_t generateSessionId() { + std::random_device rd; + std::uniform_int_distribution u; + return u(rd); +} + +} // namespace + +namespace facebook::eden { + +uint32_t getSessionId() { + static auto sessionId = generateSessionId(); + return sessionId; +} + +} // namespace facebook::eden diff --git a/eden/common/telemetry/SessionId.h b/eden/common/telemetry/SessionId.h new file mode 100644 index 00000000..edf26a4a --- /dev/null +++ b/eden/common/telemetry/SessionId.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook::eden { + +/** + * Returns a random, process-stable positive integer in the range of [0, + * UINT32_MAX] + */ +uint32_t getSessionId(); + +} // namespace facebook::eden diff --git a/eden/common/telemetry/SessionInfo.cpp b/eden/common/telemetry/SessionInfo.cpp new file mode 100644 index 00000000..ef3a72cf --- /dev/null +++ b/eden/common/telemetry/SessionInfo.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "eden/common/telemetry/SessionInfo.h" + +#include +#include + +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#endif + +#if defined(_WIN32) +#include // @manual +#endif + +#include + +#include "eden/common/utils/SysctlUtil.h" + +namespace { +/** + * Windows limits hostnames to 256 bytes. Linux provides HOST_NAME_MAX + * and MAXHOSTNAMELEN constants, defined as 64. Both Linux and macOS + * define _POSIX_HOST_NAME_MAX as 256. Both Linux and macOS allow + * reading the host name limit at runtime with + * sysconf(_SC_HOST_NAME_MAX). + * + * RFC 1034 limits complete domain names to 255: + * https://tools.ietf.org/html/rfc1034#section-3.1 + * > To simplify implementations, the total number of octets that represent a + * > domain name (i.e., the sum of all label octets and label lengths) is + * > limited to 255. + * + * Rather than querying dynamically or selecting a constant based on platform, + * assume 256 is sufficient everywhere. + */ +constexpr size_t kHostNameMax = 256; +} // namespace + +namespace facebook::eden { + +std::string getOperatingSystemName() { +#if defined(_WIN32) + return "Windows"; +#elif defined(__linux__) + return "Linux"; +#elif defined(__APPLE__) + // Presuming EdenFS doesn't run on iOS, watchOS, or tvOS. :) + return "macOS"; +#else + return "unknown"; +#endif +} + +std::string getOperatingSystemVersion() { +#if defined(_WIN32) + // TODO: Implement build version lookup, e.g. 1903 + // reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v releaseid + return "10"; +#elif defined(__linux__) || defined(__APPLE__) + struct utsname uts; + if (uname(&uts)) { + return "error"; + } + return uts.release; +#else + return "unknown"; +#endif +} + +#if defined(__APPLE__) +std::string getOperatingSystemArchitecture() { + // the c_str strips the trailing null bytes. + return getSysCtlByName("machdep.cpu.brand_string", 64).c_str(); +} +#endif + +std::string getHostname() { + char hostname[kHostNameMax + 1]; + folly::checkUnixError( + gethostname(hostname, sizeof(hostname)), + "gethostname() failed, errno: ", + errno); + + // POSIX does not require implementations of gethostname to + // null-terminate. Ensure null-termination after the call. + hostname[kHostNameMax] = 0; + + return hostname; +} + +std::optional getSandcastleInstanceId() { + auto str = std::getenv("SANDCASTLE_INSTANCE_ID"); + if (!str) { + return std::nullopt; + } + try { + uint64_t id = folly::to(str); + return std::make_optional(id); + } catch (const folly::ConversionError&) { + return std::nullopt; + } +} + +} // namespace facebook::eden diff --git a/eden/common/telemetry/SessionInfo.h b/eden/common/telemetry/SessionInfo.h new file mode 100644 index 00000000..4e945e4c --- /dev/null +++ b/eden/common/telemetry/SessionInfo.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include + +namespace facebook::eden { + +struct SessionInfo { + std::string username; + std::string hostname; + // TODO(nga): sandcastle is Facebook-specific, should not be used in + // opensource version. + std::optional sandcastleInstanceId; + std::string os; + std::string osVersion; + std::string edenVersion; +#ifdef __APPLE__ + std::string systemArchitecture; +#endif +}; + +std::string getOperatingSystemName(); +std::string getOperatingSystemVersion(); +#if defined(__APPLE__) +std::string getOperatingSystemArchitecture(); +#endif + +/** + * Returns the result of calling gethostname() in a std::string. Throws an + * exception on failure. + */ +std::string getHostname(); + +/** + * Return the best guess of sandcastle instance id from the environment, + * or return empty if sandcastle instance id is unknown. + */ +// TODO(nga): sandcastle is Facebook-specific, should not be used in +// opensource version. +std::optional getSandcastleInstanceId(); + +} // namespace facebook::eden