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-776 Add custom timings API for RUM Views #323

Merged

Conversation

ncreated
Copy link
Member

What and why?

📦 This PR introduces custom timings API for RUM:

Global.rum.addTiming(name: "content-ready")

Screenshot 2020-11-30 at 15 16 12

How?

Timing is measured as the number of nanoseconds since the start of the current view.

Timings are encoded as view.custom_timings.<name-of-the-timing> values in RUM event JSON. To make it work, I had to apply workaround for backend issue: we must enforce that view.custom_timings.* appears after the view. object (achieved by enabling .sortedKeys option in JSON encoder).

To test timings with mocked RelativeDateProvider, I had to ensure that it is not used by the storage part of the mocked feature. This is done by injecting SystemDateProvider when partially mocking each feature.

Review checklist

  • Feature or bugfix MUST have appropriate tests (unit, integration)
  • Make sure each commit and the PR mention the Issue number or JIRA reference

this is a workaround for backend issue with overwriting flattened JSON keys when
`view.custom_timings` precedes the `view` object in the RUM event payload.
@ncreated ncreated self-assigned this Nov 30, 2020
@ncreated ncreated marked this pull request as ready for review November 30, 2020 14:29
@ncreated ncreated requested a review from a team as a code owner November 30, 2020 14:29
@@ -15,7 +15,9 @@ extension JSONEncoder {
try container.encode(formatted)
}
if #available(iOS 13.0, OSX 10.15, *) {
encoder.outputFormatting = [.withoutEscapingSlashes]
encoder.outputFormatting = [.withoutEscapingSlashes, .sortedKeys]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can add a comment explaining .sortedKeys

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, done 👌

/// Adds a specific timing in the currently presented View. The timing duration will be computed as the
/// number of nanoseconds between the time the View was started and the time the timing was added.
/// - Parameters:
/// - name: the name of the custom timing attribute.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we also use name as key and they must be unique, that might be worth mentioning here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the note that name must be unique for each timing 👍.

Comment on lines +18 to +19
/// Custom View timings (only available if `DM` is a RUM View model)
let customViewTimings: [String: Int64]?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment doesn't sound like it's intended.?
IMO we can add customViewTimings via an RUMView extension

extension RUMView {
  func addCustomTimingAttribute(_ timing) { self.attributes["view.custom_timings.\(timing.name)"] = timing.value }
  // ...and if needed
  var customViewTimings { return attributes.filter { $0.startsWith("view.custom_timings") } }
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RUMView is created by the user to configure the auto-instrumentation and UIKitRUMViewsPredicate, I don't find it like a good place to store custom timings. Do you mean RUMDataView: RUMDataModel? That one in turn is auto-generated, so I didn't want to extend it with any custom functionality (even through extension in separate file).

As all other encoding logic is done in RUMEventEncoder, I found it quite natural to put timings also in there. Having additional property for timings (customViewTimings) will come handy for data scrubbing, as it adds clear context to those values and we can make them (un-)editable as we want. If merged with attributes, we'd have to additionally filter them out as you suggest, so I prefer the easiest way for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry yes, i meant RUMDataView
ideally this was supposed to be part of RUMDataView but it's not so due to limitations of JSON schema
i'd stay as close as possible to the ideal solution

but i'm resolving because we just follow android here 👌

var four = 1

enum CodingKeys: String, CodingKey {
case one = "aaaaaa"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think our use case is keys with ., no? if we add keys with . here, maybe we can catch potential issues in next iOS versions

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True 👌. Added one more variant: aaa.aaa to cover this.

@ncreated ncreated merged commit c54bfd5 into master Dec 1, 2020
@ncreated ncreated deleted the ncreated/RUMM-776-add-custom-timings-support-in-RUM branch December 1, 2020 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants