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

Enforce Standard Logging Compliance by Abstraction #934

Merged
merged 12 commits into from
Nov 8, 2022

Conversation

coleFD
Copy link
Contributor

@coleFD coleFD commented Oct 7, 2022

The goal of this commit is to force compliance of standard logging practices so more efficient indexing features can be developed in the future such as a logs bloom filter by event name. See the original discussion here: near/NEPs#297

! NOTE:
Please see discussion in the linked issue above to determine if it would be better to make the standard and version field optional

! BREAKING CHANGE:
For this change to be useful, we will need to privatize/remove the env::log() and env::log_str() functions, which has not been implemented yet in this commit. May not be a breaking change, but adding this to this section, so it is recognized

@coleFD coleFD changed the title Enforce Standard Logging Compliance by Abstraction WIP: Enforce Standard Logging Compliance by Abstraction Oct 10, 2022
@coleFD
Copy link
Contributor Author

coleFD commented Oct 10, 2022

Changed to WIP because I would like to convert to a single derive attribute with kwargs, and I need to resolve issues with lifetimes. I also still need to privatize env::log(), env::log_str(), and remove log!(). Any feedback on this pattern (see ./src/types/events.rs test for what it would look like in a contract). Also, I am not sure if it is better to have 2 functions to emit events or just have one, but I like the Event::emit() option since it's easier to spot when skimming code.

Another possible idea is to add it to the near_bindgen attribute, so like near_bindgen(event), and events could be added to the abi a future issue??

@frol frol marked this pull request as draft October 11, 2022 11:51
@frol
Copy link
Collaborator

frol commented Oct 11, 2022

@coleFD Exposing events via ABI would be awesome! I feel it is a much heavier lift than the initial idea, but I see it as a cool challenge 😃

@coleFD
Copy link
Contributor Author

coleFD commented Oct 11, 2022

near_bindgen(event)

For sure, I dont think adding events to the abi should be added to this issue. I dont want to add to many changes into 1 issue, but If I utilize near_bindgen instead of creating a new macro, it will put us in a better spot to add the abi functionality in the future.

@coleFD coleFD force-pushed the feat/enforced-event-standard-logging branch 3 times, most recently from e486714 to 2a548aa Compare October 12, 2022 15:40
@coleFD coleFD marked this pull request as ready for review October 12, 2022 15:40
@coleFD
Copy link
Contributor Author

coleFD commented Oct 12, 2022

The implementation is done, but I still need to remove the previous logging functions. I do not know what that process should look like since it will affect all of the examples and smart-contract-standards contracts as well. I can update these as needed, but getting approval first would be better. We could even create another issue for the transition..

near-sdk-macros/src/core_impl/event/mod.rs Outdated Show resolved Hide resolved
near-sdk-macros/src/core_impl/event/mod.rs Outdated Show resolved Hide resolved
@frol
Copy link
Collaborator

frol commented Oct 13, 2022

I still need to remove the previous logging functions.

Please, clarify which logging functions you refer to.

@frol
Copy link
Collaborator

frol commented Oct 13, 2022

@austinabell Could you recommend someone to review this PR?

@coleFD
Copy link
Contributor Author

coleFD commented Oct 13, 2022

I still need to remove the previous logging functions.

Please, clarify which logging functions you refer to.

The goal of this is to prevent logging without having the standard metadata fields standard, version, event, and data, so any logging functionality that does not do that should be removed from the users' toolbox in my opinion. I think the only functions that do this are env::log(), env::log_str(), and the macro log!().

Are there any concerns with doing this?

@coleFD coleFD force-pushed the feat/enforced-event-standard-logging branch 2 times, most recently from bc1c77a to baa178d Compare October 13, 2022 13:14
@frol
Copy link
Collaborator

frol commented Oct 13, 2022

log_str and its derivatives should be left as is. There is no problem with using logs in contracts, though, we should definitely promote usage of events. Also, I would imagine we reimplement NFT and FT events using this facility. I see that @austinabell is out of office until next week, so we will need to wait until he gets back and gets time to review it.

@coleFD coleFD changed the title WIP: Enforce Standard Logging Compliance by Abstraction Enforce Standard Logging Compliance by Abstraction Oct 13, 2022
@frol
Copy link
Collaborator

frol commented Oct 17, 2022

By the way, I have just learned about this prior art: https://github.com/NEARFoundation/near-contract-tools#events

@coleFD
Copy link
Contributor Author

coleFD commented Oct 17, 2022

By the way, I have just learned about this prior art: https://github.com/NEARFoundation/near-contract-tools#events

interesting, is there still incentive to add this to near-sdk?

@frol
Copy link
Collaborator

frol commented Oct 17, 2022

I would like to hear what @austinabell thinks

@coleFD coleFD force-pushed the feat/enforced-event-standard-logging branch from baa178d to f263fba Compare October 17, 2022 13:50
Copy link
Contributor

@austinabell austinabell left a comment

Choose a reason for hiding this comment

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

Thanks for working on this! I think this can be useful to have in the SDK somewhere (unsure if it should live in near_sdk or near_contract_standards crate, I'll think about that more.

@itegulov wdyt about this? Do you think the implications of enum vs struct annotation would have any implication on integrating into the ABI?

Comment on lines 23 to 28
#[near_bindgen(events)]
pub enum TestEvents<'a, 'b, T>
where
T: crate::serde::Serialize + Clone,
{
#[event_meta(standard = "swap_standard", version = "1.0.0")]
Copy link
Contributor

Choose a reason for hiding this comment

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

Curious why the decision to group all events in one enum? Would this not just be simpler if it was an attribute on a struct? I suppose this is a bit opinionated, but wondering if there is a reason this must be an enum

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 went this route based on frol's comment above. It looked clean as an enum since it grouped events together. I can convert it to implement structs if we decide to go that route

Copy link
Contributor

Choose a reason for hiding this comment

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

nope, that's fine. It's opinionated, was just sharing my intuition. I suppose we could also just support both if it doesn't increase complexity meaningfully.

cc @itegulov wdyt?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I treat events as some sort of standard and an enum in my head represents the fact that there is a finite number of types of events that a contract can emit. That said, I would consider extracting standard = "..." to the enum declaration level instead of the enum variants level. This way we could have FtEvents, NftEvents, MtEvents, FayyrEvents, etc, so one could import and use them in a composable way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the last thing I need clarification on before committing the new changes. Should I move forward with keeping this as an enum and moving standard to the enum declaration level?

Copy link
Contributor

Choose a reason for hiding this comment

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

@itegulov wdyt about this? Do you think the implications of enum vs struct annotation would have any implication on integrating into the ABI?

I don't think it matters, we should be able to generate ABI for both options.

Personally, I find that having a mega-enum covering all standards used in this contract is a bit of an antipattern, but not a strong opinion. What @frol suggested makes more sense to me - having an enum per standard looks cleaner.

near-sdk-macros/src/lib.rs Outdated Show resolved Hide resolved
@@ -0,0 +1,95 @@
pub trait StandardEvent {
fn format(&self) -> String;
fn emit(&self);
Copy link
Contributor

Choose a reason for hiding this comment

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

This could have a default implementation to prevent devs from having to implement it manually if they choose.

Suggested change
fn emit(&self);
fn emit(&self) {
crate::env::log_str(&format!("EVENT_JSON:{}", &standard_event.format()));
}

near-sdk/src/types/event.rs Outdated Show resolved Hide resolved
@mooori
Copy link
Contributor

mooori commented Oct 31, 2022

Using darling to parse attributes passed to #[near_bindgen] could help to remove custom parsing logic.

Another benefit of using darling is related to supporting other attributes besides events. That could be done by adding fields to the structs into which attributes are parsed, instead of adding more custom parsing logic.

For example, this PR shows how darling could be used for near_bindgen and handling multiple attributes might look like this.

near-sdk-macros/src/lib.rs Outdated Show resolved Hide resolved
near-sdk/src/types/event.rs Outdated Show resolved Hide resolved
near-sdk/src/types/event.rs Outdated Show resolved Hide resolved
near-sdk-macros/src/lib.rs Outdated Show resolved Hide resolved
near-sdk-macros/src/lib.rs Outdated Show resolved Hide resolved
near-sdk-macros/src/lib.rs Outdated Show resolved Hide resolved
@coleFD coleFD force-pushed the feat/enforced-event-standard-logging branch from 00dffda to 6eecebe Compare October 31, 2022 20:52
@coleFD
Copy link
Contributor Author

coleFD commented Nov 3, 2022

any feedback on the latest commit?

@austinabell
Copy link
Contributor

any feedback on the latest commit?

There's actually a much simpler way to make sure there is no overlap here. I made the commit 1e6c09e.

Feel free to cherry-pick, make a similar change yourself, or let me know if I can push it to this branch. It's a small nit but with this, you can still have a collision when you don't need that to be the case.

@coleFD
Copy link
Contributor Author

coleFD commented Nov 3, 2022

any feedback on the latest commit?

There's actually a much simpler way to make sure there is no overlap here. I made the commit 1e6c09e.

Feel free to cherry-pick, make a similar change yourself, or let me know if I can push it to this branch. It's a small nit but with this, you can still have a collision when you don't need that to be the case.

Nice! you can push it to this branch!

@austinabell
Copy link
Contributor

So when making that other change, it wasn't clear to me why the trait is necessary at all. Seems unergonomic to require devs to import that trait to use this. Why not just remove it like in 1cc5c19 ?

@austinabell
Copy link
Contributor

Also, ignore CI failure, it's because of a Rust release. #955 fixes it

@coleFD
Copy link
Contributor Author

coleFD commented Nov 3, 2022

So when making that other change, it wasn't clear to me why the trait is necessary at all. Seems unergonomic to require devs to import that trait to use this. Why not just remove it like in 1cc5c19 ?

initially the plan was to have a StandardEvent trait to standardize the interface for all current and future serialization formats. I agree it doesnt make much sense if we just have json

@austinabell
Copy link
Contributor

For my first iteration, the plan was to have a StandardEvent trait to standardize the interface for all current and future serialization formats. I agree it doesn't make much sense if we just have JSON

I just don't see the benefit in having a trait for this if all it's going to do is add the convenience env::log_str("EVENT_JSON:..."). Can always add the trait back later, but I'd rather keep the API as slim as possible.

I'll push that change to this branch then since it seems like you're on board. Would be nice to have a macro test for the codegen, since I was able to make both changes without any tests failing, which is not ideal. This is not required though, improved tests can come after this PR comes in. Sorry for so much back and forth, this is just an important interface and it would be painful to migrate later.

@frol
Copy link
Collaborator

frol commented Nov 4, 2022

@austinabell @coleFD Thanks for pushing it forward! I was out of the office, and I just had a chance to sync back. I see there was a huge progress! 🙏

Copy link
Contributor

@austinabell austinabell left a comment

Choose a reason for hiding this comment

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

LGTM but would be good to have another approval since I was the last to make a commit on this branch

Copy link
Collaborator

@frol frol left a comment

Choose a reason for hiding this comment

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

Overall, looks good to me. I only left a few nits in the comments

Comment on lines 16 to 17
#[cfg(test)]
mod event_tests;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it actually the right place for the tests? Should we move it to near-sdk/tests?

near-sdk-macros/src/lib.rs Outdated Show resolved Hide resolved
near-sdk-macros/src/core_impl/event/mod.rs Outdated Show resolved Hide resolved
austinabell and others added 3 commits November 7, 2022 19:57
Co-authored-by: Vlad Frolov <frolvlad@gmail.com>
Co-authored-by: Vlad Frolov <frolvlad@gmail.com>
@austinabell austinabell merged commit 557c22c into near:master Nov 8, 2022
@austinabell
Copy link
Contributor

thank you! Sorry for all the back and forth

@coleFD
Copy link
Contributor Author

coleFD commented Nov 8, 2022

No worries! thank you guys for being responsive and taking the time to dig into it!

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.

5 participants