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

Expose start, end, and duration in APIs #16

Merged
merged 10 commits into from
May 27, 2022
Merged

Expose start, end, and duration in APIs #16

merged 10 commits into from
May 27, 2022

Conversation

morrisonlevi
Copy link
Contributor

@morrisonlevi morrisonlevi commented May 25, 2022

What does this PR do?

Exposes start, end, and duration in APIs. This is a breaking change.

Also adds a ddprof_ffi_Request_drop function in case you don't want
to send it.

Motivation

This allows the PHP profiler to back-date the start of the profile.
When the node.js profiler was trying to use this library, they also
encountered an issue with these not being exposed.

Additional Notes

I threw in some refactoring for period and period type. Sorry. Should
have been a separate PR.

Also fixed an FFI failure that was caused by Tag being extracted into
ddcommon, which wasn't added to the include section of
cbindgen.toml. I've opened PR #17 to generate the FFI and try to
build the examples against the FFI to prevent such breakages from
happening again.

How to test the change?

IMPORTANT! The following signatures changed:

  • ddprof_ffi_Profile_new. Has an additional parameter for the start
    time. May pass None to have the previous behavior.
  • ddprof_ffi_Profile_serialize. Has additional parameters for the end
    time and duration. May pass None for both. The duration's behavior
    won't quite be the same as before because of potential clock skew,
    but close enough. If you want to avoid that, then track duration
    yourself.

@morrisonlevi morrisonlevi requested a review from a team as a code owner May 25, 2022 22:05
Copy link
Member

@ivoanjo ivoanjo left a comment

Choose a reason for hiding this comment

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

Code-wise the change seems reasonable, but my main point of confusion is not understanding the need for end time and duration to be decoupled.

Regardless of that, I do think it makes a lot of sense for the caller to be able to control the timestamps and other time-related things, as it makes libddprof usable in more scenarios for a low cost in terms of complexity.

Comment on lines 230 to 231
#[export_name = "ddprof_ffi_Request_drop"]
pub extern "C" fn request_drop(_request: Option<Box<Request>>) {}
Copy link
Member

Choose a reason for hiding this comment

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

Minor: I've noticed that in the ffi we have a bit of a mix around function naming -- sometimes we use

#[no_mangle]
pub extern "C" fn ddprof_ffi_this_is_the_C_function_name() {}

others we use

#[export_name = "ddprof_ffi_this_is_the_C_function_name"]
pub extern "C" fn pretty_rust_name() {}

I slightly favor the first option, but regardless of which one we pick, I think it would be nice to be consistent here. Changing it all is perhaps not for this PR, but perhaps we could decide now which version we want and document it somewhere?

(I don't mind submitting a follow-up PR with the clean-up myself so that the ffi is consistent with what we decide)

Comment on lines 79 to 82
let duration = started.elapsed();
profile.set_duration(Some(duration));

match profile.serialize(None) {
Copy link
Member

Choose a reason for hiding this comment

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

I know we somewhat touched this in slack but looking at it again, I realized I didn't understood the ramifications of your proposal.

When would the end time NOT be start + duration? That's how pprof already represents it and intuitively that makes sense to me, so it's kinda weird that when set_duration gets called, we don't set the end time as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Was my explanation in standup good enough? I also changed the behavior when no duration is given to try to calculate it from the end and start times.

ddprof-profiles/src/lib.rs Outdated Show resolved Hide resolved
ddprof-profiles/src/lib.rs Outdated Show resolved Hide resolved
Comment on lines 126 to 129
pub fn build(self) -> Profile {
let mut profile = Profile::new();
let mut profile = Profile::new(self.time.unwrap_or_else(SystemTime::now));

profile.duration = self.duration;
Copy link
Member

Choose a reason for hiding this comment

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

This is a bit weird to me. The ProfileBuilder() is the thing one uses to build a profile, so when would duration not be None here? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm. It seems like setting the duration in multiple places is not great. Let me see what it looks like with just setting it at serialization time.

ddprof-profiles/src/lib.rs Outdated Show resolved Hide resolved
ddprof-profiles/src/lib.rs Outdated Show resolved Hide resolved
Copy link
Member

@ivoanjo ivoanjo left a comment

Choose a reason for hiding this comment

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

This looks good to me.

I'm still not completely convinced of the need to set duration and end_time independently BUT on this latest version of the change I think we have best of both worlds:

  • (What I claim to be) reasonable defaults when passing just NULL for all of start_time/end_time/duration
  • Support for actually setting all three, for advanced use cases

I did spot a potential issue in the pprof encoding, but if I'm right the fix is a one-liner and given our discussion on slack I see no reason for me to hold off on the approval and let you look into it

Comment on lines 33 to 36
- name: "Generate FFI"
run: bash ffi-build.sh /tmp/libddprof
- name: "Test building C bindings"
run: mkdir examples/ffi/build && cd examples/ffi/build && cmake -S .. -DDDProf_ROOT=/tmp/libddprof && cmake --build .
Copy link
Member

Choose a reason for hiding this comment

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

😍 Big thanks for this! This is a really really nice improvement :) :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I ended up pulling this into a stacked PR because getting it to work on Windows has been a challenge and I want to unblock this part: #17.

ddprof-ffi/src/profiles.rs Outdated Show resolved Hide resolved
profile.reset().is_some()
pub unsafe extern "C" fn ddprof_ffi_Profile_reset(
profile: &mut ddprof_profiles::Profile,
time: Option<&Timespec>,
Copy link
Member

Choose a reason for hiding this comment

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

There's still quite a few places in this PR where we use time to mean start_time. I would suggest renaming them all to start_time. (I initially had it as suggested diffs on github but there's like 10 places that need renaming so I think it's just better if the IDE does it :D)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I've got them all renamed now.

ddprof-profiles/src/lib.rs Show resolved Hide resolved
ddprof-profiles/src/lib.rs Show resolved Hide resolved
This allows the PHP profiler to back-date the start of the profile.
When the node.js profiler was trying to use this library, they also
encountered an issue with these not being exposed.
morrisonlevi and others added 3 commits May 27, 2022 07:58
Co-authored-by: Ivo Anjo <ivo.anjo@datadoghq.com>
As per Ivo's recommendation in CR.
Copy link
Member

@ivoanjo ivoanjo left a comment

Choose a reason for hiding this comment

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

👍 Did a quick final pass, LGTM no further comments your honor :)

@morrisonlevi morrisonlevi merged commit 32ca509 into main May 27, 2022
@morrisonlevi morrisonlevi deleted the levi/time branch May 27, 2022 14:27
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