Skip to content

Commit

Permalink
add new SentryFeedback interface and thread callpath to capture in en…
Browse files Browse the repository at this point in the history
…velope
  • Loading branch information
armcknight committed Nov 16, 2024
1 parent 210286d commit 13b0327
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 9 deletions.
4 changes: 4 additions & 0 deletions Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@
84CFA4CA2C9DF884008DA5F4 /* SentryUserFeedbackWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA4C92C9DF884008DA5F4 /* SentryUserFeedbackWidget.swift */; };
84CFA4CD2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA4CC2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.m */; };
84CFA4CE2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFA4CB2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.h */; };
84DBC62C2CE82F12000C4904 /* SentryFeedback.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DBC62B2CE82F0E000C4904 /* SentryFeedback.swift */; };
84DEE86B2B686BD400A7BC17 /* SentrySamplerDecision.h in Headers */ = {isa = PBXBuildFile; fileRef = 84DEE86A2B686BD400A7BC17 /* SentrySamplerDecision.h */; };
84DEE8762B69AD6400A7BC17 /* SentryLaunchProfiling.h in Headers */ = {isa = PBXBuildFile; fileRef = 84DEE8752B69AD6400A7BC17 /* SentryLaunchProfiling.h */; };
84E13B842CBF1D91003B52EC /* SentryUserFeedbackWidgetButtonMegaphoneIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E13B832CBF1D91003B52EC /* SentryUserFeedbackWidgetButtonMegaphoneIconView.swift */; };
Expand Down Expand Up @@ -1777,6 +1778,7 @@
84CFA4C92C9DF884008DA5F4 /* SentryUserFeedbackWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUserFeedbackWidget.swift; sourceTree = "<group>"; };
84CFA4CB2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryUserFeedbackIntegration.h; path = ../../../Sentry/include/SentryUserFeedbackIntegration.h; sourceTree = "<group>"; };
84CFA4CC2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SentryUserFeedbackIntegration.m; path = ../../../Sentry/SentryUserFeedbackIntegration.m; sourceTree = "<group>"; };
84DBC62B2CE82F0E000C4904 /* SentryFeedback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryFeedback.swift; sourceTree = "<group>"; };
84DEE86A2B686BD400A7BC17 /* SentrySamplerDecision.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentrySamplerDecision.h; path = include/SentrySamplerDecision.h; sourceTree = "<group>"; };
84DEE8752B69AD6400A7BC17 /* SentryLaunchProfiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryLaunchProfiling.h; path = Sources/Sentry/include/SentryLaunchProfiling.h; sourceTree = SOURCE_ROOT; };
84E13B832CBF1D91003B52EC /* SentryUserFeedbackWidgetButtonMegaphoneIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUserFeedbackWidgetButtonMegaphoneIconView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3524,6 +3526,7 @@
children = (
849B8F9E2C70091A00148E1F /* Configuration */,
849B8F962C6E906900148E1F /* SentryUserFeedbackIntegrationDriver.swift */,
84DBC62B2CE82F0E000C4904 /* SentryFeedback.swift */,
84CFA4CB2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.h */,
84CFA4CC2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.m */,
84CFA4C92C9DF884008DA5F4 /* SentryUserFeedbackWidget.swift */,
Expand Down Expand Up @@ -4566,6 +4569,7 @@
7B6438AB26A70F24000D0F65 /* UIViewController+Sentry.m in Sources */,
84302A812B5767A50027A629 /* SentryLaunchProfiling.m in Sources */,
63AA76A31EB9CBAA00D153DE /* SentryDsn.m in Sources */,
84DBC62C2CE82F12000C4904 /* SentryFeedback.swift in Sources */,
63B818FA1EC34639002FDF4C /* SentryDebugMeta.m in Sources */,
7B98D7D325FB65AE00C5A389 /* SentryWatchdogTerminationTracker.m in Sources */,
8E564AE8267AF22600FE117D /* SentryNetworkTrackingIntegration.m in Sources */,
Expand Down
10 changes: 10 additions & 0 deletions Sources/Sentry/SentryClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,16 @@ - (void)captureUserFeedback:(SentryUserFeedback *)userFeedback
[self.transportAdapter sendUserFeedback:userFeedback];
}

- (void)captureFeedback:(SentryFeedback *)feedback
{
if ([self isDisabled]) {
[self logDisabledMessage];
return;
}

[self.transportAdapter sendFeedback:feedback];
}

- (void)storeEnvelope:(SentryEnvelope *)envelope
{
[self.fileManager storeEnvelope:envelope];
Expand Down
18 changes: 18 additions & 0 deletions Sources/Sentry/SentryEnvelope.m
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,24 @@ - (instancetype)initWithUserFeedback:(SentryUserFeedback *)userFeedback
data:json];
}

- (instancetype)initWithFeedback:(SentryFeedback *)feedback
{
NSError *error = nil;
NSData *json = [NSJSONSerialization dataWithJSONObject:[feedback serialize]
options:0
error:&error];

if (nil != error) {
SENTRY_LOG_ERROR(@"Couldn't serialize feedback.");
json = [NSData new];
}

return [self initWithHeader:[[SentryEnvelopeItemHeader alloc]
initWithType:SentryEnvelopeItemTypeFeedback
length:json.length]
data:json];
}

- (instancetype)initWithClientReport:(SentryClientReport *)clientReport
{
NSError *error = nil;
Expand Down
8 changes: 8 additions & 0 deletions Sources/Sentry/SentryHub.m
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,14 @@ - (void)captureUserFeedback:(SentryUserFeedback *)userFeedback
}
}

- (void)captureFeedback:(SentryFeedback *)feedback
{
SentryClient *client = _client;
if (client != nil) {
[client captureFeedback:feedback];
}
}

- (void)addBreadcrumb:(SentryBreadcrumb *)crumb
{
SentryOptions *options = [[self client] options];
Expand Down
5 changes: 5 additions & 0 deletions Sources/Sentry/SentrySDK.m
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,11 @@ + (void)captureUserFeedback:(SentryUserFeedback *)userFeedback
[SentrySDK.currentHub captureUserFeedback:userFeedback];
}

+ (void)captureFeedback:(SentryFeedback *)feedback
{
[SentrySDK.currentHub captureFeedback:feedback];
}

+ (void)showUserFeedbackForm
{
// TODO: implement
Expand Down
11 changes: 11 additions & 0 deletions Sources/Sentry/SentryTransportAdapter.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#import "SentryEvent.h"
#import "SentryOptions.h"
#import "SentryUserFeedback.h"
#import "SentrySwift.h"
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN
Expand Down Expand Up @@ -87,6 +88,16 @@ - (void)sendUserFeedback:(SentryUserFeedback *)userFeedback
[self sendEnvelope:envelope];
}

- (void)sendFeedback:(SentryFeedback *)feedback
{
SentryEnvelopeItem *item = [[SentryEnvelopeItem alloc] initWithFeedback:feedback];
SentryEnvelopeHeader *envelopeHeader =
[[SentryEnvelopeHeader alloc] initWithId:feedback.eventId];
SentryEnvelope *envelope = [[SentryEnvelope alloc] initWithHeader:envelopeHeader
singleItem:item];
[self sendEnvelope:envelope];
}

- (void)sendEnvelope:(SentryEnvelope *)envelope
{
for (id<SentryTransport> transport in self.transports) {
Expand Down
10 changes: 6 additions & 4 deletions Sources/Sentry/include/HybridPublic/SentryEnvelope.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@

#endif

@class SentryEvent;
@class SentrySession;
@class SentryId;
@class SentryUserFeedback;
@class SentryAttachment;
@class SentryEnvelopeItemHeader;
@class SentryEvent;
@class SentryFeedback;
@class SentryId;
@class SentrySession;
@class SentryTraceContext;
@class SentryUserFeedback;

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -82,6 +83,7 @@ SENTRY_NO_INIT
- (instancetype)initWithEvent:(SentryEvent *)event;
- (instancetype)initWithSession:(SentrySession *)session;
- (instancetype)initWithUserFeedback:(SentryUserFeedback *)userFeedback;
- (instancetype)initWithFeedback:(SentryFeedback *)feedback;
- (_Nullable instancetype)initWithAttachment:(SentryAttachment *)attachment
maxAttachmentSize:(NSUInteger)maxAttachmentSize;
- (instancetype)initWithHeader:(SentryEnvelopeItemHeader *)header
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
static NSString *const SentryEnvelopeItemTypeEvent = @"event";
static NSString *const SentryEnvelopeItemTypeSession = @"session";
static NSString *const SentryEnvelopeItemTypeUserFeedback = @"user_report";
static NSString *const SentryEnvelopeItemTypeFeedback = @"feedback";
static NSString *const SentryEnvelopeItemTypeTransaction = @"transaction";
static NSString *const SentryEnvelopeItemTypeAttachment = @"attachment";
static NSString *const SentryEnvelopeItemTypeClientReport = @"client_report";
Expand Down
18 changes: 16 additions & 2 deletions Sources/Sentry/include/SentryClient+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@
#import "SentryDataCategory.h"
#import "SentryDiscardReason.h"

@class SentrySession, SentryEnvelopeItem, SentryId, SentryAttachment, SentryThreadInspector,
SentryReplayEvent, SentryReplayRecording, SentryEnvelope;
@class SentryAttachment;
@class SentryEnvelope;
@class SentryEnvelopeItem;
@class SentryFeedback;
@class SentryId;
@class SentryReplayEvent;
@class SentryReplayRecording;
@class SentrySession;
@class SentryThreadInspector;

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -63,6 +70,13 @@ NS_ASSUME_NONNULL_BEGIN
- (void)addAttachmentProcessor:(id<SentryClientAttachmentProcessor>)attachmentProcessor;
- (void)removeAttachmentProcessor:(id<SentryClientAttachmentProcessor>)attachmentProcessor;

/**
* Captures a new-style user feedback and sends it to Sentry.
* @param feedback The user feedback to send to Sentry.
*/
- (void)captureFeedback:(SentryFeedback *)feedback
NS_SWIFT_NAME(capture(feedback:));

@end

NS_ASSUME_NONNULL_END
2 changes: 2 additions & 0 deletions Sources/Sentry/include/SentryHub+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@class SentryTransaction;
@class SentryDispatchQueueWrapper;
@class SentryEnvelope;
@class SentryFeedback;
@class SentryNSTimerFactory;
@class SentrySession;
@class SentryTracer;
Expand Down Expand Up @@ -62,6 +63,7 @@ NS_ASSUME_NONNULL_BEGIN

- (void)storeEnvelope:(SentryEnvelope *)envelope;
- (void)captureEnvelope:(SentryEnvelope *)envelope;
- (void)captureFeedback:(SentryFeedback *)feedback;

- (void)registerSessionListener:(id<SentrySessionListener>)listener;
- (void)unregisterSessionListener:(id<SentrySessionListener>)listener;
Expand Down
8 changes: 7 additions & 1 deletion Sources/Sentry/include/SentrySDK+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
# import "SentrySDK.h"
#endif

@class SentryHub, SentryId, SentryAppStartMeasurement, SentryEnvelope;
@class SentryAppStartMeasurement;
@class SentryEnvelope;
@class SentryFeedback;
@class SentryHub;
@class SentryId;

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -51,6 +55,8 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (void)captureEnvelope:(SentryEnvelope *)envelope;

+ (void)captureFeedback:(SentryFeedback *)feedback;

@end

NS_ASSUME_NONNULL_END
12 changes: 10 additions & 2 deletions Sources/Sentry/include/SentryTransportAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@
#import "SentryDiscardReason.h"
#import "SentryTransport.h"

@class SentryEnvelope, SentryEnvelopeItem, SentryEvent, SentrySession, SentryUserFeedback,
SentryAttachment, SentryTraceContext, SentryOptions;
@class SentryAttachment;
@class SentryEnvelope;
@class SentryEnvelopeItem;
@class SentryEvent;
@class SentryFeedback;
@class SentryOptions;
@class SentrySession;
@class SentryTraceContext;
@class SentryUserFeedback;

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -40,6 +47,7 @@ SENTRY_NO_INIT
attachments:(NSArray<SentryAttachment *> *)attachments;

- (void)sendUserFeedback:(SentryUserFeedback *)userFeedback NS_SWIFT_NAME(send(userFeedback:));
- (void)sendFeedback:(SentryFeedback *)feedback NS_SWIFT_NAME(send(feedback:));

- (void)sendEnvelope:(SentryEnvelope *)envelope NS_SWIFT_NAME(send(envelope:));

Expand Down
57 changes: 57 additions & 0 deletions Sources/Swift/Integrations/UserFeedback/SentryFeedback.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Foundation
#if os(iOS) && !SENTRY_NO_UIKIT
@_implementationOnly import _SentryPrivate
import UIKit

/**
* A user feedback item that serializes to an envelope with the new format described at
* https://develop.sentry.dev/application/feedback-architecture/#feedback-events.
*/
@objcMembers
class SentryFeedback: NSObject, SentrySerializable {
enum Source: String {
case widget
case custom
}

var name: String?
var email: String?
var message: String
var hints: [String: Any]?
var source: Source
let eventId: SentryId

/// The event id that this feedback is associated with, like a crash report.
var associatedEventId: String?

init(name: String?, email: String?, message: String, hints: [String: Any]?, source: Source, associatedEventId: String?) {
self.eventId = SentryId()
self.name = name
self.email = email
self.message = message
self.hints = hints
self.source = source
self.associatedEventId = associatedEventId
super.init()
}

func serialize() -> [String : Any] {
var dict: [String: Any] = [
"message": message
]
if let name = name {
dict["name"] = name
}
if let email = email {
dict["contact_email"] = email
}
if let associatedEventId = associatedEventId {
dict["associated_event_id"] = associatedEventId
}
dict["source"] = source.rawValue

return dict
}
}

#endif // os(iOS) && !SENTRY_NO_UIKIT

0 comments on commit 13b0327

Please sign in to comment.