Skip to content

Commit b9b388b

Browse files
Chandhana Solainathanmeta-codesync[bot]
authored andcommitted
Implement StackTraceUploader for Manifold uploads
Summary: Implement StackTraceUploader for generating manifold keys, fires background manifold upload, returns URL Reviewed By: vilatto Differential Revision: D96944480 fbshipit-source-id: 7e21fa2f28efda7a269136941f742a2ba81fcf6b
1 parent 90ba943 commit b9b388b

File tree

5 files changed

+137
-0
lines changed

5 files changed

+137
-0
lines changed

eden/fs/telemetry/BUCK

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,25 @@ cpp_library(
131131
],
132132
)
133133

134+
cpp_library(
135+
name = "stack_trace_uploader",
136+
srcs = [
137+
"StackTraceUploader.cpp",
138+
],
139+
headers = [
140+
"StackTraceUploader.h",
141+
],
142+
deps = [
143+
"fbsource//third-party/fmt:fmt",
144+
"//eden/fs/rust/manifold_ffi:manifold-ffi",
145+
"//eden/fs/rust/manifold_ffi:manifold-ffi@header",
146+
"//folly:random",
147+
"//folly/executors:cpu_thread_pool_executor",
148+
"//folly/logging:logging",
149+
],
150+
exported_deps = [],
151+
)
152+
134153
cpp_library(
135154
name = "error_info",
136155
srcs = [
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This software may be used and distributed according to the terms of the
5+
* GNU General Public License version 2.
6+
*/
7+
8+
#include "eden/fs/telemetry/StackTraceUploader.h"
9+
10+
#include <fmt/core.h>
11+
#include <folly/Random.h>
12+
#include <folly/executors/CPUThreadPoolExecutor.h>
13+
#include <folly/logging/xlog.h>
14+
15+
#include "eden/fs/rust/manifold_ffi/src/lib.rs.h"
16+
17+
namespace facebook::eden {
18+
19+
namespace {
20+
constexpr size_t kUploadPoolSize = 1;
21+
22+
folly::CPUThreadPoolExecutor& getUploadPool() {
23+
static folly::CPUThreadPoolExecutor pool(kUploadPoolSize);
24+
return pool;
25+
}
26+
} // namespace
27+
28+
std::string StackTraceUploader::generateKey() {
29+
auto hi = folly::Random::rand64();
30+
auto lo = folly::Random::rand64();
31+
return fmt::format("flat/{:016x}{:016x}", hi, lo);
32+
}
33+
34+
std::string StackTraceUploader::keyToUrl(const std::string& key) {
35+
return fmt::format("manifold://{}/{}", kBucket, key);
36+
}
37+
38+
std::string StackTraceUploader::uploadToManifold(std::string content) {
39+
auto key = generateKey();
40+
auto url = keyToUrl(key);
41+
42+
// Submit to a dedicated upload pool.
43+
getUploadPool().add([key = std::move(key), content = std::move(content)]() {
44+
try {
45+
manifold_write(
46+
kBucket,
47+
kApiKey,
48+
key,
49+
rust::Slice<const uint8_t>(
50+
reinterpret_cast<const uint8_t*>(content.data()), content.size()),
51+
kUploadTimeoutSeconds * 1000,
52+
kExpirationSeconds,
53+
kClientIdentity);
54+
} catch (const std::exception& ex) {
55+
XLOGF(
56+
WARN,
57+
"Failed to upload stack trace to Manifold key={} bucket={}: {}",
58+
key,
59+
kBucket,
60+
ex.what());
61+
}
62+
});
63+
64+
return url;
65+
}
66+
67+
} // namespace facebook::eden

eden/fs/telemetry/StackTraceUploader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#pragma once
99

10+
#include <cstdint>
1011
#include <string>
1112

1213
namespace facebook::eden {
@@ -18,7 +19,9 @@ class StackTraceUploader {
1819
public:
1920
static constexpr const char* kBucket = "edenfs-errors-stacktraces";
2021
static constexpr const char* kApiKey = "edenfs-errors-stacktraces-key";
22+
static constexpr const char* kClientIdentity = "edenfs_stack_trace_uploader";
2123
static constexpr int kUploadTimeoutSeconds = 10;
24+
static constexpr uint32_t kExpirationSeconds = 30 * 24 * 60 * 60; // 30 days
2225

2326
/**
2427
* Generate a unique Manifold key for a stack trace.

eden/fs/telemetry/test/BUCK

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,18 @@ cpp_unittest(
7575
],
7676
)
7777

78+
cpp_unittest(
79+
name = "stack_trace_uploader_test",
80+
srcs = [
81+
"StackTraceUploaderTest.cpp",
82+
],
83+
supports_static_listing = False,
84+
deps = [
85+
"fbsource//third-party/googletest:gtest",
86+
"//eden/fs/telemetry:stack_trace_uploader",
87+
],
88+
)
89+
7890
cpp_unittest(
7991
name = "error_info_builder_test",
8092
srcs = [
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This software may be used and distributed according to the terms of the
5+
* GNU General Public License version 2.
6+
*/
7+
8+
#include "eden/fs/telemetry/StackTraceUploader.h"
9+
10+
#include <algorithm>
11+
12+
#include <gtest/gtest.h>
13+
14+
namespace facebook::eden {
15+
16+
TEST(StackTraceUploaderTest, generateKeyAndUrlFormat) {
17+
auto key = StackTraceUploader::generateKey();
18+
// Key format: "flat/" + 32 hex characters
19+
EXPECT_EQ(key.substr(0, 5), "flat/");
20+
auto rest = key.substr(5);
21+
EXPECT_EQ(rest.size(), 32);
22+
EXPECT_TRUE(std::all_of(rest.begin(), rest.end(), ::isxdigit))
23+
<< "Expected hex string, got: " << rest;
24+
25+
// URL should embed the bucket name and the generated key
26+
auto url = StackTraceUploader::keyToUrl(key);
27+
EXPECT_EQ(url, "manifold://edenfs-errors-stacktraces/" + key);
28+
}
29+
30+
TEST(StackTraceUploaderTest, generateKeyIsUnique) {
31+
auto key1 = StackTraceUploader::generateKey();
32+
auto key2 = StackTraceUploader::generateKey();
33+
EXPECT_NE(key1, key2);
34+
}
35+
36+
} // namespace facebook::eden

0 commit comments

Comments
 (0)