Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RUMM-788 Add data scrubbing API #367

Merged
merged 5 commits into from
Jan 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions Datadog/Datadog.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@
613E79282577B0EE00DFCC17 /* Writer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 613E79272577B0EE00DFCC17 /* Writer.swift */; };
613E792F2577B0F900DFCC17 /* Reader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 613E792E2577B0F900DFCC17 /* Reader.swift */; };
613E793B2577B6EE00DFCC17 /* DataReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 613E793A2577B6EE00DFCC17 /* DataReader.swift */; };
613E81F025A740140084B751 /* RUMEventsMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 613E81EF25A740140084B751 /* RUMEventsMapper.swift */; };
613E81F725A743600084B751 /* RUMEventsMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 613E81F625A743600084B751 /* RUMEventsMapperTests.swift */; };
613E820525A879AF0084B751 /* RUMDataModelMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 613E820425A879AF0084B751 /* RUMDataModelMocks.swift */; };
613F23E4252B062F006CD2D7 /* TaskInterceptionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 613F23E3252B062F006CD2D7 /* TaskInterceptionTests.swift */; };
613F23F1252B129E006CD2D7 /* URLSessionRUMResourcesHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 613F23F0252B129E006CD2D7 /* URLSessionRUMResourcesHandlerTests.swift */; };
613F23FD252B3755006CD2D7 /* URLSessionAutoInstrumentationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 613F23FC252B3755006CD2D7 /* URLSessionAutoInstrumentationTests.swift */; };
Expand Down Expand Up @@ -270,6 +273,7 @@
61BBD19724ED50040023E65F /* FeaturesConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61BBD19624ED50040023E65F /* FeaturesConfigurationTests.swift */; };
61BCB81F256EB77F0039887B /* ServerDateProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61BCB81E256EB77F0039887B /* ServerDateProvider.swift */; };
61C1510D25AC8C1B00362D4B /* RUMViewIdentityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61C1510C25AC8C1B00362D4B /* RUMViewIdentityTests.swift */; };
61C1513125ADC68D00362D4B /* DataProcessorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61C1513025ADC68D00362D4B /* DataProcessorTests.swift */; };
61C2C20724C098FC00C0321C /* RUMSessionScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61C2C20624C098FC00C0321C /* RUMSessionScope.swift */; };
61C2C20924C0C75500C0321C /* RUMSessionScopeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61C2C20824C0C75500C0321C /* RUMSessionScopeTests.swift */; };
61C2C20B24C1045300C0321C /* SendRUMFixture1ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61C2C20A24C1045300C0321C /* SendRUMFixture1ViewController.swift */; };
Expand Down Expand Up @@ -578,6 +582,9 @@
613E79272577B0EE00DFCC17 /* Writer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Writer.swift; sourceTree = "<group>"; };
613E792E2577B0F900DFCC17 /* Reader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Reader.swift; sourceTree = "<group>"; };
613E793A2577B6EE00DFCC17 /* DataReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataReader.swift; sourceTree = "<group>"; };
613E81EF25A740140084B751 /* RUMEventsMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMEventsMapper.swift; sourceTree = "<group>"; };
613E81F625A743600084B751 /* RUMEventsMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMEventsMapperTests.swift; sourceTree = "<group>"; };
613E820425A879AF0084B751 /* RUMDataModelMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMDataModelMocks.swift; sourceTree = "<group>"; };
613F23E3252B062F006CD2D7 /* TaskInterceptionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskInterceptionTests.swift; sourceTree = "<group>"; };
613F23F0252B129E006CD2D7 /* URLSessionRUMResourcesHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionRUMResourcesHandlerTests.swift; sourceTree = "<group>"; };
613F23FC252B3755006CD2D7 /* URLSessionAutoInstrumentationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionAutoInstrumentationTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -721,6 +728,7 @@
61BBD19624ED50040023E65F /* FeaturesConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeaturesConfigurationTests.swift; sourceTree = "<group>"; };
61BCB81E256EB77F0039887B /* ServerDateProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerDateProvider.swift; sourceTree = "<group>"; };
61C1510C25AC8C1B00362D4B /* RUMViewIdentityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMViewIdentityTests.swift; sourceTree = "<group>"; };
61C1513025ADC68D00362D4B /* DataProcessorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataProcessorTests.swift; sourceTree = "<group>"; };
61C2C20624C098FC00C0321C /* RUMSessionScope.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMSessionScope.swift; sourceTree = "<group>"; };
61C2C20824C0C75500C0321C /* RUMSessionScopeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMSessionScopeTests.swift; sourceTree = "<group>"; };
61C2C20A24C1045300C0321C /* SendRUMFixture1ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendRUMFixture1ViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1211,6 +1219,7 @@
61FB222C244A21ED00902D19 /* LoggingFeatureMocks.swift */,
61AD4E172451C7FF006E34EA /* TracingFeatureMocks.swift */,
61E5333024B75DFC003D6C4E /* RUMFeatureMocks.swift */,
613E820425A879AF0084B751 /* RUMDataModelMocks.swift */,
61B038B92527257B00518F3C /* URLSessionAutoInstrumentationMocks.swift */,
61C3638224361BE200C4D4E6 /* DatadogPrivateMocks.swift */,
61F1A61B2498AD2C00075390 /* SystemFrameworks */,
Expand Down Expand Up @@ -1574,6 +1583,22 @@
path = Reading;
sourceTree = "<group>";
};
613E81EE25A73FB90084B751 /* Scrubbing */ = {
isa = PBXGroup;
children = (
613E81EF25A740140084B751 /* RUMEventsMapper.swift */,
);
path = Scrubbing;
sourceTree = "<group>";
};
613E81F525A743470084B751 /* Scrubbing */ = {
isa = PBXGroup;
children = (
613E81F625A743600084B751 /* RUMEventsMapperTests.swift */,
);
path = Scrubbing;
sourceTree = "<group>";
};
613F23DC252B05BD006CD2D7 /* URLFiltering */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1944,6 +1969,7 @@
children = (
6114FE22257671F00084E372 /* ConsentAwareDataWriterTests.swift */,
61133C292423990D00786299 /* FileWriterTests.swift */,
61C1512F25ADC67500362D4B /* Processing */,
);
path = Writting;
sourceTree = "<group>";
Expand Down Expand Up @@ -2012,6 +2038,14 @@
path = Debugging;
sourceTree = "<group>";
};
61C1512F25ADC67500362D4B /* Processing */ = {
isa = PBXGroup;
children = (
61C1513025ADC68D00362D4B /* DataProcessorTests.swift */,
);
path = Processing;
sourceTree = "<group>";
};
61C3637E2436163400C4D4E6 /* DatadogPrivate */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -2169,6 +2203,7 @@
6156CB8A24DDA186008CB2B2 /* RUMContext */,
61E5333B24B87908003D6C4E /* RUMEvent */,
61FF282224B8A1AE000B3D9B /* RUMEventOutputs */,
613E81EE25A73FB90084B751 /* Scrubbing */,
616CCE11250A181C009FED46 /* AutoInstrumentation */,
618DCFD524C7264100589570 /* UUIDs */,
61B22E5824F3E6A700DC26D2 /* Debugging */,
Expand All @@ -2185,6 +2220,7 @@
6156CB9124DDAA13008CB2B2 /* RUMContext */,
61FF281F24B89807000B3D9B /* RUMEvent */,
61FF282E24BC5E0E000B3D9B /* RUMEventOutputs */,
613E81F525A743470084B751 /* Scrubbing */,
61F3CDA825121F8F00C816E5 /* AutoInstrumentation */,
61786F7524FCDDE2009E6BAB /* Debugging */,
61411B0E24EC15940012EAB2 /* Utils */,
Expand Down Expand Up @@ -2832,6 +2868,7 @@
61B22E5A24F3E6B700DC26D2 /* RUMDebugging.swift in Sources */,
61C5A88B24509A0C00DA608C /* SpanOutput.swift in Sources */,
61133BE42423979B00786299 /* LogEncoder.swift in Sources */,
613E81F025A740140084B751 /* RUMEventsMapper.swift in Sources */,
61D980BA24E28D0100E03345 /* RUMIntegrations.swift in Sources */,
61C5A88424509A0C00DA608C /* DDSpan.swift in Sources */,
61FF281E24B8968D000B3D9B /* RUMEventBuilder.swift in Sources */,
Expand Down Expand Up @@ -2904,13 +2941,15 @@
61AD4E182451C7FF006E34EA /* TracingFeatureMocks.swift in Sources */,
615A4A8924A34FD700233986 /* DDTracerTests.swift in Sources */,
615A4A8724A3452800233986 /* DDTracerConfigurationTests.swift in Sources */,
613E81F725A743600084B751 /* RUMEventsMapperTests.swift in Sources */,
61EF78B7257E37D500EDCCB3 /* MoveDataMigratorTests.swift in Sources */,
61F1A621249A45E400075390 /* DDSpanContextTests.swift in Sources */,
615C3196251DD5080018781C /* UIKitRUMUserActionsHandlerTests.swift in Sources */,
61E917CF2464270500E6C631 /* EncodableValueTests.swift in Sources */,
61133C542423990D00786299 /* NetworkConnectionInfoProviderTests.swift in Sources */,
616B668E259CC28E00968EE8 /* DDRUMMonitorTests.swift in Sources */,
61B558CF2469561C001460D3 /* LoggerBuilderTests.swift in Sources */,
61C1513125ADC68D00362D4B /* DataProcessorTests.swift in Sources */,
61133C4A2423990D00786299 /* DDConfigurationTests.swift in Sources */,
61C5A89F24509C1100DA608C /* UUID.swift in Sources */,
613F23F1252B129E006CD2D7 /* URLSessionRUMResourcesHandlerTests.swift in Sources */,
Expand Down Expand Up @@ -2946,6 +2985,7 @@
61133C6C2423990D00786299 /* SwiftExtensions.swift in Sources */,
61A763DC252DB2B3005A23F2 /* NSURLSessionBridge.m in Sources */,
61C1510D25AC8C1B00362D4B /* RUMViewIdentityTests.swift in Sources */,
613E820525A879AF0084B751 /* RUMDataModelMocks.swift in Sources */,
61133C492423990D00786299 /* DDLoggerBuilderTests.swift in Sources */,
61133C4B2423990D00786299 /* DDLoggerTests.swift in Sources */,
618715FC24DC5F0800FC0F69 /* RUMDataModelsMappingTests.swift in Sources */,
Expand Down
4 changes: 3 additions & 1 deletion Sources/Datadog/Core/Feature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ internal struct FeatureStorage {
featureName: String,
dataFormat: DataFormat,
directories: FeatureDirectories,
eventMapper: EventMapper?,
commonDependencies: FeaturesCommonDependencies
) {
let readWriteQueue = DispatchQueue(
Expand Down Expand Up @@ -69,7 +70,8 @@ internal struct FeatureStorage {
authorizedFileWriter: FileWriter(
dataFormat: dataFormat,
orchestrator: authorizedFilesOrchestrator
)
),
eventMapper: eventMapper
),
dataMigratorFactory: DataMigratorFactory(
directories: directories
Expand Down
7 changes: 7 additions & 0 deletions Sources/Datadog/Core/FeaturesConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ internal struct FeaturesConfiguration {
let uploadURLWithClientToken: URL
let applicationID: String
let sessionSamplingRate: Float
let eventMapper: RUMEventsMapper
/// RUM auto instrumentation configuration, `nil` if not enabled.
let autoInstrumentation: AutoInstrumentation?
}
Expand Down Expand Up @@ -161,6 +162,12 @@ extension FeaturesConfiguration {
),
applicationID: rumApplicationID,
sessionSamplingRate: configuration.rumSessionsSamplingRate,
eventMapper: RUMEventsMapper(
viewEventMapper: configuration.rumViewEventMapper,
errorEventMapper: configuration.rumErrorEventMapper,
resourceEventMapper: configuration.rumResourceEventMapper,
actionEventMapper: configuration.rumActionEventMapper
),
autoInstrumentation: autoInstrumentation
)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,49 @@

import Foundation

/// Data scrubbing interface.
/// It takes an `event` and returns its modified representation or `nil` (for dropping the event).
internal protocol EventMapper {
func map<T: Encodable>(event: T) -> T?
}

internal struct DataProcessorFactory {
/// File writer writting unauthorized data when consent is `.pending`.
let unauthorizedFileWriter: Writer
/// File writer writting authorized data when consent is `.granted`.
let authorizedFileWriter: Writer
/// Event mapper performing eventual modification (or dropping) the event before it gets written.
/// It may be `nil` if not available for this feature.
let eventMapper: EventMapper?

func resolveProcessor(for consent: TrackingConsent) -> DataProcessor? {
switch consent {
case .granted: return DataProcessor(fileWriter: authorizedFileWriter)
case .granted: return DataProcessor(fileWriter: authorizedFileWriter, eventMapper: eventMapper)
case .notGranted: return nil
case .pending: return DataProcessor(fileWriter: unauthorizedFileWriter)
case .pending: return DataProcessor(fileWriter: unauthorizedFileWriter, eventMapper: eventMapper)
}
}
}

/// The processing pipeline for writing data.
internal final class DataProcessor: Writer {
private let fileWriter: Writer
private let eventMapper: EventMapper?

init(fileWriter: Writer) {
init(fileWriter: Writer, eventMapper: EventMapper?) {
self.fileWriter = fileWriter
self.eventMapper = eventMapper
}

// MARK: - Writer

func write<T>(value: T) where T: Encodable {
fileWriter.write(value: value)
if let eventMapper = eventMapper {
if let mappedValue = eventMapper.map(event: value) {
fileWriter.write(value: mappedValue)
}
} else {
fileWriter.write(value: value)
}
}
}
44 changes: 44 additions & 0 deletions Sources/Datadog/DatadogConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ extension Datadog {
private(set) var rumSessionsSamplingRate: Float
private(set) var rumUIKitViewsPredicate: UIKitRUMViewsPredicate?
private(set) var rumUIKitActionsTrackingEnabled: Bool
private(set) var rumViewEventMapper: RUMViewEventMapper?
private(set) var rumResourceEventMapper: RUMResourceEventMapper?
private(set) var rumActionEventMapper: RUMActionEventMapper?
private(set) var rumErrorEventMapper: RUMErrorEventMapper?
private(set) var batchSize: BatchSize
private(set) var uploadFrequency: UploadFrequency

Expand Down Expand Up @@ -233,6 +237,10 @@ extension Datadog {
rumSessionsSamplingRate: 100.0,
rumUIKitViewsPredicate: nil,
rumUIKitActionsTrackingEnabled: false,
rumViewEventMapper: nil,
rumResourceEventMapper: nil,
rumActionEventMapper: nil,
rumErrorEventMapper: nil,
batchSize: .medium,
uploadFrequency: .average
)
Expand Down Expand Up @@ -440,6 +448,42 @@ extension Datadog {
return self
}

/// Sets the custom mapper for `RUMViewEvent`. This can be used to modify RUM View events before they are send to Datadog.
/// - Parameter mapper: the closure taking `RUMViewEvent` as input and expecting `RUMViewEvent` or `nil` as output.
/// The implementation should obtain a mutable version of the `RUMViewEvent`, modify it and return. Returning `nil` will result
/// with dropping the RUM View event entirely, so it won't be send to Datadog.
public func setRUMViewEventMapper(_ mapper: @escaping (RUMViewEvent) -> RUMViewEvent?) -> Builder {
configuration.rumViewEventMapper = mapper
return self
}

/// Sets the custom mapper for `RUMResourceEvent`. This can be used to modify RUM Resource events before they are send to Datadog.
/// - Parameter mapper: the closure taking `RUMResourceEvent` as input and expecting `RUMResourceEvent` or `nil` as output.
/// The implementation should obtain a mutable version of the `RUMResourceEvent`, modify it and return. Returning `nil` will result
/// with dropping the RUM Resource event entirely, so it won't be send to Datadog.
public func setRUMResourceEventMapper(_ mapper: @escaping (RUMResourceEvent) -> RUMResourceEvent?) -> Builder {
configuration.rumResourceEventMapper = mapper
return self
}

/// Sets the custom mapper for `RUMActionEvent`. This can be used to modify RUM Action events before they are send to Datadog.
/// - Parameter mapper: the closure taking `RUMActionEvent` as input and expecting `RUMActionEvent` or `nil` as output.
/// The implementation should obtain a mutable version of the `RUMActionEvent`, modify it and return. Returning `nil` will result
/// with dropping the RUM Action event entirely, so it won't be send to Datadog.
public func setRUMActionEventMapper(_ mapper: @escaping (RUMActionEvent) -> RUMActionEvent?) -> Builder {
configuration.rumActionEventMapper = mapper
return self
}

/// Sets the custom mapper for `RUMErrorEvent`. This can be used to modify RUM Error events before they are send to Datadog.
/// - Parameter mapper: the closure taking `RUMErrorEvent` as input and expecting `RUMErrorEvent` or `nil` as output.
/// The implementation should obtain a mutable version of the `RUMErrorEvent`, modify it and return. Returning `nil` will result
/// with dropping the RUM Error event entirely, so it won't be send to Datadog.
public func setRUMErrorEventMapper(_ mapper: @escaping (RUMErrorEvent) -> RUMErrorEvent?) -> Builder {
configuration.rumErrorEventMapper = mapper
return self
}

// MARK: - Features Common Configuration

/// Sets the default service name associated with data send to Datadog.
Expand Down
1 change: 1 addition & 0 deletions Sources/Datadog/Logging/LoggingFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ internal final class LoggingFeature {
featureName: LoggingFeature.featureName,
dataFormat: LoggingFeature.dataFormat,
directories: directories,
eventMapper: nil,
commonDependencies: commonDependencies
)
}
Expand Down
3 changes: 2 additions & 1 deletion Sources/Datadog/RUM/RUMEvent/RUMEventEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import Foundation
/// `Encodable` representation of RUM event.
internal struct RUMEvent<DM: RUMDataModel>: Encodable {
/// The actual RUM event model created by `RUMMonitor`
let model: DM
/// It's mutable as it may be redacted by the user through data scrubbing API.
var model: DM

/// Custom attributes set by the user
let attributes: [String: Encodable]
Expand Down
13 changes: 11 additions & 2 deletions Sources/Datadog/RUM/RUMFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,16 @@ internal final class RUMFeature {

// MARK: - Initialization

static func createStorage(directories: FeatureDirectories, commonDependencies: FeaturesCommonDependencies) -> FeatureStorage {
static func createStorage(
directories: FeatureDirectories,
eventMapper: RUMEventsMapper,
commonDependencies: FeaturesCommonDependencies
) -> FeatureStorage {
return FeatureStorage(
featureName: RUMFeature.featureName,
dataFormat: RUMFeature.dataFormat,
directories: directories,
eventMapper: eventMapper,
commonDependencies: commonDependencies
)
}
Expand Down Expand Up @@ -100,7 +105,11 @@ internal final class RUMFeature {
configuration: FeaturesConfiguration.RUM,
commonDependencies: FeaturesCommonDependencies
) {
let storage = RUMFeature.createStorage(directories: directories, commonDependencies: commonDependencies)
let storage = RUMFeature.createStorage(
directories: directories,
eventMapper: configuration.eventMapper,
commonDependencies: commonDependencies
)
let upload = RUMFeature.createUpload(storage: storage, configuration: configuration, commonDependencies: commonDependencies)
self.init(
storage: storage,
Expand Down
Loading