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

Switch log signature to str from bytes #366

Merged
merged 21 commits into from
Jul 15, 2021

Conversation

austinabell
Copy link
Contributor

@austinabell austinabell commented Apr 20, 2021

I've decided to go with the generic AsRef<str> to start as it makes for a cleaner API, but I'm unsure if the code duplication from the generic gets optimized away, so I will try to compare now and will leave this PR in draft state until I explore some more. Alternative being taking &str as the param and just calling .as_ref() in the macro call, which might be best to make sure to minimize the code output size in all potential cases.

I asked about this a while ago in discord, but I'll assume #362 means the breaking change is acceptable. Is there any downstream work connected with the master branch that I should update/make sure this doesn't break?

Closes #362

@austinabell
Copy link
Contributor Author

austinabell commented Apr 20, 2021

Tested the different APIs with a modified greeter to just have the logs as follows:

        log!("Saving greeting '{}' for account '{}'", message, account_id,);
        log!("Some static log");
        log!(message.as_str());

and even in that case that I assumed it would optimize away, it wasn't:

~/dev/git/nea/log/con/tar/was/release $ stat -c '%n %s' greeter.wasm
greeter.wasm 120783
~/dev/git/nea/log/con/tar/was/release $ stat -c '%n %s' greeter.wasm
greeter.wasm 119963

So I decided to switch to the non-generic function signature because the API will be basically the same when using the log! macro, which it seems you are moving to.

Edit: I also switched the single arg log macro to be of expr type, because the tt only allowed a static string, and I don't see why it can't also take a variable/expression if someone wanted.

@austinabell austinabell marked this pull request as ready for review April 20, 2021 00:56
Copy link
Contributor

@evgenykuzyakov evgenykuzyakov left a comment

Choose a reason for hiding this comment

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

This is going to break legacy code. log! serves the purpose.

@austinabell
Copy link
Contributor Author

This is going to break legacy code. log! serves the purpose.

But the env::log is still public so still technically a breaking change, so just wanted to make sure

@matklad
Copy link
Contributor

matklad commented Apr 21, 2021

This is going to break legacy code. log! serves the purpose.

Do we have our backwards compatibility policy for SDK documented anywhere? Taking a bird's eye view, the current public API of SDK feels like it has a lot of rough edges from Rust API design point of view, and it seems like long term smoothing those out would be beneficial. However, it's unclear to me at least what is the best path towards that.

I can see several options for this particular change, and for this class of changes:

  • do nothing and consider the API frozen / append only
  • keep the current major version, but use deprecation to slowly clean-up the API (so, apply #[deprecated] & #[doc(hidden)] attributes to the log function, introduce log_str, re-implement log in terms of log_str)
  • use release trains: release a point release which deprecates log function now, and release a new semver-incompatible version not-to-far in the future, which adds log with the correct signature.
  • prepare for "big-bang" style next major version (don't implement this right now, but add a BreakingChange label and release a new version when we accumulate a bunch of those).
  • re-design the API from the first principles, using the lessons learned, but not the code, from the existing sdk (aka "don't tell Joel Spolsky")

Neither of them is inherently better than the other (even the last one can be beneficial in the exceptional circumstances), but it's unclear which one we use.

@austinabell austinabell mentioned this pull request May 20, 2021
10 tasks
@austinabell austinabell removed the paused label Jun 4, 2021
@austinabell
Copy link
Contributor Author

I've updated the code to keep the existing env::log signature to reduce breakage, and marked the function as deprecated.

This is not completely backwards compatible because the macro is switched to use the new function, but I can't think of a case where this would actually be hit. Everything that worked before should still work, and this will be released under a major, breaking release anyway.

@austinabell austinabell requested a review from matklad June 10, 2021 15:48
@@ -506,10 +506,20 @@ pub fn panic(message: &[u8]) -> ! {
unsafe { sys::panic_utf8(message.len() as _, message.as_ptr() as _) }
unreachable!()
}
/// Logs the string message message. This message is stored on chain.
pub fn log_str(message: &str) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should it be accepting anything that implements ToString trait? WDYT @matklad ?
Btw, is this method going to support no-std?

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 don't see a huge benefit in supporting this because it would increase code size for the monomorphization of the generic and for more general usage, log! macro is used. I originally made it generic based on AsRef<str> but since it added code size (tested and an example given above) the macro calls as_ref and this base call remains as a concrete type. Having it be ToString would force an unnecessary allocation that I'm not sure can be optimized away by the compiler.

As for no_std, yes it is no_std compatible and has the same memory layout as bytes. It's currently used as such in the no_std experimental SDK I've been playing with.

Copy link
Contributor

Choose a reason for hiding this comment

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

No, ToString would force allocation, and won't be enough to make a nice API. For the latter, we need a format-style macro.

Copy link
Contributor

@matklad matklad left a comment

Choose a reason for hiding this comment

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

LGTM!

@mikedotexe mikedotexe merged commit 932ebb5 into near:master Jul 15, 2021
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.

near_sdk::env::log has wrong signature
5 participants