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

Make Event to be not 'static #655

Closed
tomocrafter opened this issue May 8, 2024 · 2 comments
Closed

Make Event to be not 'static #655

tomocrafter opened this issue May 8, 2024 · 2 comments
Assignees

Comments

@tomocrafter
Copy link

tomocrafter commented May 8, 2024

I want to customize the Event with before_send callback and adding the fingerprint that getting from event.contexts.
but since Event is Event<'static> so it needs static lifetime, therefore adding dynamic string to fingerprint is not straightforward (by using Box::leak, we can make string to be 'static lifetime but as name suggests, it causes memory leak).

event.request = Some(sentry::protocol::Request {

            before_send: Some(Arc::new(|mut event| {
                let tracing_fields = event.contexts.get("Rust Tracing Fields");
                if let Some(Context::Other(fields)) = tracing_fields {
                    let fingerprint = fields.get("fingerprint");
                    if let Some(Value::String(fingerprint)) = fingerprint {
                        event.fingerprint = Cow::Borrowed(&[
                            Cow::Borrowed("{{ default }}"),
                            Cow::Borrowed(&fingerprint), // <-- Here, fingerprint is not 'static, therefore error occurs.
                        ])
                    }
                }
                Some(event)
            })),

I would like to have Event as not 'static, and allow me to modify it dynamically.
Thank you.

@loewenheim
Copy link
Contributor

loewenheim commented May 8, 2024

Hi! All the references with lifetime 'a in Event are behind Cow smart pointers. For example, fingerprint has the type Cow<'a, [Cow<'a, str>]>. In case you're not familiar, a Cow<'a, T> is either a reference &'a T or the "owned form" of T. For example, a Cow<'a, str> is either a &'a str or a String. You can always get a Cow<'static, T> by using the owned form of T. For fingerprint, that means using Vec and String.

Here is a small example on the Rust playground that shows how it works: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e9a894986b86e0d2a2540f96b1142718

Please let me know if that resolves your issue.

Edited to add: Here is your example snippet with my suggestion applied:

            before_send: Some(Arc::new(|mut event| {
                let tracing_fields = event.contexts.get("Rust Tracing Fields");
                if let Some(Context::Other(fields)) = tracing_fields {
                    let fingerprint = fields.get("fingerprint");
                    if let Some(Value::String(fingerprint)) = fingerprint {
                        event.fingerprint = Cow::Owned(vec![ // <-- This needs to be Owned because it's dynamic
                            Cow::Borrowed("{{ default }}"), // <-- This can be Borrowed because it's hardcoded
                            Cow::Owned(fingerprint.clone()), // <-- This needs to be Owned because it's dynamic
                        ])
                    }
                }
                Some(event)
            })),

@loewenheim loewenheim self-assigned this May 8, 2024
@tomocrafter
Copy link
Author

Wow, I misunderstood Cow smart pointer. Your suggestion compiled and worked as expected!
Thank you!

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

No branches or pull requests

2 participants