Skip to content

Commit c3f824d

Browse files
Chandhana Solainathanmeta-codesync[bot]
authored andcommitted
Combine source location with throw-site stack trace
Summary: Combines source location and throw-site stack trace in the builder constructor. Reviewed By: vilatto Differential Revision: D99200513 fbshipit-source-id: 22eb699427d3fc0b17de3f9406c37329f08e6fac
1 parent 5d9f1c3 commit c3f824d

File tree

3 files changed

+62
-22
lines changed

3 files changed

+62
-22
lines changed

eden/fs/telemetry/EdenErrorInfoBuilder.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ EdenErrorInfo EdenErrorInfoBuilder::create() {
5050
info.errorCode = errorCode_;
5151
info.errorName = std::move(errorName_);
5252
info.exceptionType = std::move(exceptionType_);
53-
// Currently stores source location (file:line in func), will be replaced
54-
// with a Manifold URL for full stack traces
5553
info.stackTrace = std::move(sourceLocation_);
5654
info.clientCommandName = std::move(clientCommandName_);
5755
info.inode = inode_;
@@ -70,6 +68,17 @@ EdenErrorInfoBuilder::EdenErrorInfoBuilder(
7068
errorName_(error.errorName),
7169
exceptionType_(error.exceptionType),
7270
sourceLocation_(
73-
fmt::format("{}:{} in {}", loc.file, loc.line, loc.func)) {}
71+
error.stackTrace.has_value()
72+
? fmt::format(
73+
"Source: {}:{} in {}\n\nStack trace:\n{}",
74+
loc.file,
75+
loc.line,
76+
loc.func,
77+
*error.stackTrace)
78+
: fmt::format(
79+
"Source: {}:{} in {}",
80+
loc.file,
81+
loc.line,
82+
loc.func)) {}
7483

7584
} // namespace facebook::eden

eden/fs/telemetry/test/BUCK

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ cpp_unittest(
9696
deps = [
9797
"fbsource//third-party/googletest:gtest",
9898
"//eden/fs/telemetry:error_info",
99+
"//eden/fs/telemetry:throw_trace_capture", # @manual needed for --wrap __cxa_throw linker flag
100+
"//folly:c_portability",
99101
],
100102
)
101103

eden/fs/telemetry/test/EdenErrorInfoBuilderTest.cpp

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,56 @@
88
#include "eden/fs/telemetry/EdenErrorInfoBuilder.h"
99
#include <gtest/gtest.h>
1010
#include <cerrno>
11+
#include <stdexcept>
1112
#include <system_error>
1213

14+
#include <folly/CPortability.h>
15+
16+
#include "eden/fs/telemetry/ErrorArg.h"
17+
1318
using namespace facebook::eden;
1419

20+
namespace {
21+
[[noreturn]] FOLLY_NOINLINE void throwRuntimeError() {
22+
throw std::runtime_error("fuse read failed");
23+
}
24+
} // namespace
25+
1526
TEST(EdenErrorInfoTest, InitializeFuseEdenErrorInfoWithException) {
16-
std::runtime_error ex("fuse read failed");
17-
int line = __LINE__ + 1;
18-
auto info = EdenErrorInfo::fuse(ex, 42, "/mnt/repo").create();
27+
try {
28+
throwRuntimeError();
29+
} catch (const std::exception& ex) {
30+
// ErrorArg captures the throw-site stack trace inside a catch block.
31+
ErrorArg error(ex);
32+
#ifdef __linux__
33+
ASSERT_TRUE(error.stackTrace.has_value())
34+
<< "ErrorArg should capture a stack trace from a thrown exception";
35+
EXPECT_NE(error.stackTrace->find("throwRuntimeError"), std::string::npos)
36+
<< "Stack trace should contain the throwing function, got: "
37+
<< *error.stackTrace;
38+
#endif
1939

20-
EXPECT_EQ(info.component, EdenComponent::Fuse);
21-
EXPECT_EQ(info.errorMessage, "fuse read failed");
22-
EXPECT_EQ(info.inode.value(), 42);
23-
EXPECT_EQ(info.mountPoint.value(), "/mnt/repo");
24-
EXPECT_FALSE(info.errorCode.has_value());
25-
EXPECT_NE(
26-
info.exceptionType.value().find("runtime_error"), std::string::npos);
27-
EXPECT_TRUE(info.stackTrace.has_value());
28-
auto& trace = info.stackTrace.value();
29-
EXPECT_NE(trace.find("EdenErrorInfoBuilderTest.cpp"), std::string::npos);
30-
EXPECT_NE(trace.find(":" + std::to_string(line) + " in "), std::string::npos);
31-
EXPECT_NE(trace.find("TestBody"), std::string::npos);
40+
// create() stores the raw combined trace in info.stackTrace.
41+
auto info = EdenErrorInfo::fuse(ex, 42, "/mnt/repo").create();
42+
43+
EXPECT_EQ(info.component, EdenComponent::Fuse);
44+
EXPECT_EQ(info.errorMessage, "fuse read failed");
45+
EXPECT_EQ(info.inode.value(), 42);
46+
EXPECT_EQ(info.mountPoint.value(), "/mnt/repo");
47+
EXPECT_FALSE(info.errorCode.has_value());
48+
EXPECT_NE(
49+
info.exceptionType.value().find("runtime_error"), std::string::npos);
50+
ASSERT_TRUE(info.stackTrace.has_value());
51+
EXPECT_NE(
52+
info.stackTrace->find("EdenErrorInfoBuilderTest.cpp"),
53+
std::string::npos)
54+
<< "Stack trace should contain source file, got: " << *info.stackTrace;
55+
#ifdef __linux__
56+
EXPECT_NE(info.stackTrace->find("Stack trace:"), std::string::npos)
57+
<< "Stack trace should contain raw trace section, got: "
58+
<< *info.stackTrace;
59+
#endif
60+
}
3261
}
3362

3463
TEST(EdenErrorInfoTest, InitializeFuseEdenErrorInfoWithStringMessage) {
@@ -41,10 +70,10 @@ TEST(EdenErrorInfoTest, InitializeFuseEdenErrorInfoWithStringMessage) {
4170
EXPECT_FALSE(info.errorCode.has_value());
4271
EXPECT_FALSE(info.errorName.has_value());
4372
EXPECT_FALSE(info.exceptionType.has_value());
44-
EXPECT_TRUE(info.stackTrace.has_value());
45-
auto& loc = info.stackTrace.value();
46-
EXPECT_NE(loc.find("EdenErrorInfoBuilderTest.cpp"), std::string::npos)
47-
<< "Expected source file in location, got: " << loc;
73+
ASSERT_TRUE(info.stackTrace.has_value());
74+
EXPECT_NE(
75+
info.stackTrace->find("EdenErrorInfoBuilderTest.cpp"), std::string::npos)
76+
<< "Stack trace should contain source file, got: " << *info.stackTrace;
4877
}
4978

5079
TEST(EdenErrorInfoTest, FuseErrorInfoOverridesErrorCodeAndName) {

0 commit comments

Comments
 (0)