Skip to content

Commit

Permalink
Merge 4c850c9 into 675ef9c
Browse files Browse the repository at this point in the history
  • Loading branch information
philipphofmann authored Jan 31, 2025
2 parents 675ef9c + 4c850c9 commit 1ac9eac
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 2 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased


### Features

- HTTP Breadcrumb level based on response status code (#4779) 4xx is warning, 5xx is error.

## Improvements

- Add `sample_rand` to baggage (#4751)
Expand Down
24 changes: 22 additions & 2 deletions Sources/Sentry/SentryNetworkTracker.m
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,10 @@ - (void)addBreadcrumbForSessionTask:(NSURLSessionTask *)sessionTask
NSDate *requestStart
= objc_getAssociatedObject(sessionTask, &SENTRY_NETWORK_REQUEST_START_DATE);

SentryLevel breadcrumbLevel = sessionTask.error != nil ? kSentryLevelError : kSentryLevelInfo;
NSInteger responseStatusCode = [self urlResponseStatusCode:sessionTask.response];
SentryLevel breadcrumbLevel = [self getBreadcrumbLevel:sessionTask
responseStatusCode:responseStatusCode];

SentryBreadcrumb *breadcrumb = [[SentryBreadcrumb alloc] initWithLevel:breadcrumbLevel
category:@"http"];

Expand All @@ -507,7 +510,7 @@ - (void)addBreadcrumbForSessionTask:(NSURLSessionTask *)sessionTask
[NSNumber numberWithLongLong:sessionTask.countOfBytesSent];
breadcrumbData[@"response_body_size"] =
[NSNumber numberWithLongLong:sessionTask.countOfBytesReceived];
NSInteger responseStatusCode = [self urlResponseStatusCode:sessionTask.response];

if (responseStatusCode != -1) {
NSNumber *statusCode = [NSNumber numberWithInteger:responseStatusCode];
breadcrumbData[@"status_code"] = statusCode;
Expand Down Expand Up @@ -601,4 +604,21 @@ - (SentrySpanStatus)spanStatusForHttpResponseStatusCode:(NSInteger)statusCode
return kSentrySpanStatusUndefined;
}

- (SentryLevel)getBreadcrumbLevel:(NSURLSessionTask *)sessionTask
responseStatusCode:(NSInteger)responseStatusCode
{
SentryLevel breadcrumbLevel = kSentryLevelInfo;
if (responseStatusCode >= 400 && responseStatusCode < 500) {
breadcrumbLevel = kSentryLevelWarning;
} else if (responseStatusCode >= 500 && responseStatusCode < 600) {
breadcrumbLevel = kSentryLevelError;
}

if (sessionTask.error != nil) {
breadcrumbLevel = kSentryLevelError;
}

return breadcrumbLevel;
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,147 @@ class SentryNetworkTrackerTests: XCTestCase {
let breadcrumbs = Dynamic(fixture.scope).breadcrumbArray as [Breadcrumb]?
XCTAssertEqual(breadcrumbs?.count, 0)
}

func test_Breadcrumb_HTTP400_HasLevelWarning() throws {
// Arrange
fixture.options.enableAutoPerformanceTracing = false

let task = createDataTask()
task.setResponse(createResponse(code: 400))
let _ = spanForTask(task: task)!

//Act
try setTaskState(task, state: .completed)

//Assert
let breadcrumbsDynamic = Dynamic(fixture.scope).breadcrumbArray as [Breadcrumb]?
let breadcrumbs = try XCTUnwrap(breadcrumbsDynamic)
XCTAssertEqual(breadcrumbs.count, 1)
let breadcrumb = try XCTUnwrap(breadcrumbs.first)

XCTAssertEqual(breadcrumb.category, "http")
XCTAssertEqual(breadcrumb.level, .warning)
XCTAssertEqual(breadcrumb.type, "http")

let data = try XCTUnwrap(breadcrumb.data)
XCTAssertEqual(SentryNetworkTrackerTests.testUrl, data["url"] as? String)
XCTAssertEqual("GET", data["method"] as? String)
XCTAssertEqual(400, data["status_code"] as? Int)
XCTAssertEqual("bad request", data["reason"] as? String)
}

func test_Breadcrumb_HTTP499_HasLevelWarning() throws {
// Arrange
fixture.options.enableAutoPerformanceTracing = false

let task = createDataTask()
task.setResponse(createResponse(code: 499))
let _ = spanForTask(task: task)!

//Act
try setTaskState(task, state: .completed)

//Assert
let breadcrumbsDynamic = Dynamic(fixture.scope).breadcrumbArray as [Breadcrumb]?
let breadcrumbs = try XCTUnwrap(breadcrumbsDynamic)
XCTAssertEqual(breadcrumbs.count, 1)
let breadcrumb = try XCTUnwrap(breadcrumbs.first)

XCTAssertEqual(breadcrumb.category, "http")
XCTAssertEqual(breadcrumb.level, .warning)
XCTAssertEqual(breadcrumb.type, "http")

let data = try XCTUnwrap(breadcrumb.data)
XCTAssertEqual(SentryNetworkTrackerTests.testUrl, data["url"] as? String)
XCTAssertEqual("GET", data["method"] as? String)
XCTAssertEqual(499, data["status_code"] as? Int)
XCTAssertEqual("client error", data["reason"] as? String)
}

func testBreadcrumb_SessionTaskError_HTTP400_HasLevelError() throws {
// Arrange
fixture.options.enableAutoPerformanceTracing = false

let task = createDataTask()
task.setResponse(createResponse(code: 400))
task.setError(NSError(domain: "Some Error", code: 1, userInfo: nil))
let _ = spanForTask(task: task)!

//Act
try setTaskState(task, state: .completed)

//Assert
let breadcrumbsDynamic = Dynamic(fixture.scope).breadcrumbArray as [Breadcrumb]?
let breadcrumbs = try XCTUnwrap(breadcrumbsDynamic)
XCTAssertEqual(breadcrumbs.count, 1)
let breadcrumb = try XCTUnwrap(breadcrumbs.first)

XCTAssertEqual(breadcrumb.category, "http")
XCTAssertEqual(breadcrumb.level, .error)
XCTAssertEqual(breadcrumb.type, "http")

let data = try XCTUnwrap(breadcrumb.data)
XCTAssertEqual(SentryNetworkTrackerTests.testUrl, data["url"] as? String)
XCTAssertEqual("GET", data["method"] as? String)
XCTAssertEqual(400, data["status_code"] as? Int)
XCTAssertEqual("bad request", data["reason"] as? String)
}

func test_Breadcrumb_HTTP500_HasLevelError() throws {
// Arrange
fixture.options.enableAutoPerformanceTracing = false

let task = createDataTask()
task.setResponse(createResponse(code: 500))
let _ = spanForTask(task: task)!

//Act
try setTaskState(task, state: .completed)

//Assert
let breadcrumbsDynamic = Dynamic(fixture.scope).breadcrumbArray as [Breadcrumb]?
let breadcrumbs = try XCTUnwrap(breadcrumbsDynamic)
XCTAssertEqual(breadcrumbs.count, 1)
let breadcrumb = try XCTUnwrap(breadcrumbs.first)

XCTAssertEqual(breadcrumb.category, "http")
XCTAssertEqual(breadcrumb.level, .error)
XCTAssertEqual(breadcrumb.type, "http")

let data = try XCTUnwrap(breadcrumb.data)
XCTAssertEqual(SentryNetworkTrackerTests.testUrl, data["url"] as? String)
XCTAssertEqual("GET", data["method"] as? String)
XCTAssertEqual(500, data["status_code"] as? Int)
XCTAssertEqual("internal server error", data["reason"] as? String)
}

func test_Breadcrumb_HTTP599_HasLevelError() throws {
// Arrange
fixture.options.enableAutoPerformanceTracing = false

let task = createDataTask()
task.setResponse(createResponse(code: 599))
let _ = spanForTask(task: task)!

//Act
try setTaskState(task, state: .completed)

//Assert
let breadcrumbsDynamic = Dynamic(fixture.scope).breadcrumbArray as [Breadcrumb]?
let breadcrumbs = try XCTUnwrap(breadcrumbsDynamic)
XCTAssertEqual(breadcrumbs.count, 1)
let breadcrumb = try XCTUnwrap(breadcrumbs.first)

XCTAssertEqual(breadcrumb.category, "http")
XCTAssertEqual(breadcrumb.level, .error)
XCTAssertEqual(breadcrumb.type, "http")

let data = try XCTUnwrap(breadcrumb.data)
XCTAssertEqual(SentryNetworkTrackerTests.testUrl, data["url"] as? String)
XCTAssertEqual("GET", data["method"] as? String)
XCTAssertEqual(599, data["status_code"] as? Int)
XCTAssertEqual("server error", data["reason"] as? String)
}

func testResumeAfterCompleted_OnlyOneSpanCreated() throws {
let task = createDataTask()
Expand Down

0 comments on commit 1ac9eac

Please sign in to comment.