The SRG Diagnostics library is a set of lightweight components for collecting various application data for diagnostics purposes. The library is based on two main types of components:
- Reports, for collecting data.
- Services, responsible of report submission.
Reports and services are referenced by name and lazily created when accessed first. This makes it possible to create, fill and submit reports in a decentralized way. Note that diagnostics reports are not considered critical and are therefore not persisted between application sessions. You must never use such reports to convey data you cannot afford to lose.
The library is suitable for applications running on iOS 12, tvOS 12, watchOS 5 and above. The project is meant to be compiled with the latest Xcode version.
If you want to contribute to the project, have a look at our contributing guide.
The library must be integrated using Swift Package Manager directly within Xcode. You can also declare the library as a dependency of another one directly in the associated Package.swift
manifest.
When you want to use classes or functions provided by the library in your code, you must import it from your source files first. In Objective-C:
@import SRGDiagnostics;
or in Swift:
import SRGDiagnostics
To create a report, pick appropriate service and report names first. For example, to collect playback metrics associated with playback of medias, we could use playback as service name, and create a report for each media being played based on its identifier:
SRGDiagnosticsReport *report = [[SRGDiagnosticsService serviceWithName:@"playback"] reportWithName:@"1-23456-789"];
Report information is filled using -set...:forKey:
methods:
[report setInteger:3000 forKey:@"kbps"];
[report setString:@"HD" forKey:@"quality"];
Time measurements (in milliseconds) can be easily added to a report. For example, to start a measurement saved under the buffering
key, call:
[report startTimeMeasurementForKey:@"buffering"];
and to stop the measurement, call:
[report stopTimeMeasurementForKey:@"buffering"];
Information can be nested in a report. We could for example imagine saving network-related information together:
SRGDiagnosticInformation *information = [report informationForKey:@"network"];
[information setString:@"wifi" forKey:@"connection"];
[information setString:@"good" forKey:@"signal"];
Finally, when your report is finished, mark it as such:
[report finish];
Since services and reports are retrieved based on names, filling information, performing time measurements or marking a report as finished can be made from any application subsystem in a decentralized way, from any thread.
Once a report has been marked as finished, the associated service will automatically attempt to submit it after a while. Submission is made by serializing the report as JSON and calling a submission block on the service, which you can use to specify how the data is submitted.
For example, you can POST the data to a webservice expecting it as body:
[SRGDiagnosticsService serviceWithName:@"playback_metrics"].submissionBlock = ^(NSDictionary * _Nonnull JSONDictionary, void (^ _Nonnull completionBlock)(BOOL)) {
NSURL *URL = ...;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
request.HTTPMethod = @"POST";
request.HTTPBody = [NSJSONSerialization dataWithJSONObject:JSONDictionary options:0 error:NULL];
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
completionBlock(error == nil);
}] resume];
};
or simply log the report to the console:
[SRGDiagnosticsService serviceWithName:@"playback_metrics"].submissionBlock = ^(NSDictionary * _Nonnull JSONDictionary, void (^ _Nonnull completionBlock)(BOOL)) {
NSLog(@"Report: %@", JSONDictionary);
completionBlock(YES);
};
The submission block can be updated at any time, though it should in general be setup once early in the application lifecycle. Once submission has been made, the supplied completionBlock
must be called, with YES
iff the submission was successful. Successfully submitted reports are discarded, otherwise the service will attempt to submit it later. The submissionInterval
property lets you customize at which interval submissions are made.
Reports stay alive until submitted. If for some reason a report will never be sent, you should discard it to free the associated resources:
[report discard];
See the LICENSE file for more information.