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

Add support for WebAssembly #642

Open
kellytk opened this issue Mar 22, 2020 · 19 comments
Open

Add support for WebAssembly #642

kellytk opened this issue Mar 22, 2020 · 19 comments
Labels
area/wasm Related to improving support for WebAssembly. crate/subscriber Related to the `tracing-subscriber` crate crate/tracing Related to the `tracing` crate help wanted Extra attention is needed kind/feature New feature or request

Comments

@kellytk
Copy link
Contributor

kellytk commented Mar 22, 2020

Feature Request

Crates

tracing = "0.1.13"
tracing-subscriber = "0.2.3"

Motivation

To use Tracing in web frontend in addition to web backend.

Proposal

Support the build targets wasm32-unknown-unknown and wasm32-wasi.

Alternatives

Using a different tracing package for the frontend would introduce unnecessary complexity.

@hawkw hawkw added crate/subscriber Related to the `tracing-subscriber` crate crate/tracing Related to the `tracing` crate help wanted Extra attention is needed kind/feature New feature or request labels Mar 22, 2020
@hawkw
Copy link
Member

hawkw commented Mar 22, 2020

I believe tracing and tracing-core should compile on these platforms with the std feature disabled (e.g. default-features = false in Cargo.toml). I believe the stdlib's thread_local macro, which is used when the std feature is enabled, is the only feature that tracing and tracing-core use that doesn't exist on wasm targets?

tracing-subscriber is likely going to be a bit more difficult to compile for wasm targets, since it contains machinery for actually logging to stdout. However, it should be possible to use the tracing instrumentation API with an alternative subscriber implementation designed for logging in the browser. Then, the same facade can be used everywhere, and the frontend and backend executables can configure different subscribers. At the very least, this should work as a temporary solution until we can make tracing-subscriber wasm-compatible.

Finally, if we want to officially support these targets, we'd need a CI job that ensures tracing can be cross-compiled for wasm32-unknown-unknown and wasm32-wasi.

@hawkw
Copy link
Member

hawkw commented Mar 22, 2020

If someone who's more familiar with wasm than I am is interested in helping out with this, please let me know — I'm happy to provide guidance on the tracing side!

@silvanshade
Copy link
Contributor

I believe the stdlib's thread_local macro, which is used when the std feature is enabled, is the only feature that tracing and tracing-core use that doesn't exist on wasm targets?

I don't know about other features that might be an issue but thread_local! is supported for wasm targets. Here's an example that uses it from the electron-sys crate.

If someone who's more familiar with wasm than I am is interested in helping out with this, please let me know — I'm happy to provide guidance on the tracing side!

This is something I would be interested in helping with but realistically it might be awhile (couple weeks or so) before I could do much.

@hawkw
Copy link
Member

hawkw commented Mar 23, 2020

I believe the stdlib's thread_local macro, which is used when the std feature is enabled, is the only feature that tracing and tracing-core use that doesn't exist on wasm targets?

I don't know about other features that might be an issue but thread_local! is supported for wasm targets. Here's an example that uses it from the electron-sys crate.

Oh, cool — I didn't know that! In that case, I think that tracing and tracing-core should probably work out of the box, even with the std feature set. To officially support wasm targets for those crates, all we'd need to do is start cross-compiling on CI.

@hawkw
Copy link
Member

hawkw commented Jul 10, 2020

I did a quick test, and it looks like every crate in the repo builds fine for wasm32-wasi and wasm32-unknown-unknown, which was kind of a pleasant surprise.

We should probably be checking this on CI before we say that wasm targets are officially supported, though.

@Mythra
Copy link
Contributor

Mythra commented Jul 16, 2020

Hey @hawkw ,

I'd be happy to take a look at adding this to CI if that's the next step? I assume that's just modifying the github actions file to also start targeting' wasm32-unknown-unkwnown, and wasm32-wasi, and running the same steps, is that correct?

@hawkw
Copy link
Member

hawkw commented Jul 16, 2020

@securityinsanity Thanks, that would be great! I think just adding the targets to GitHub Actions is a good first step, but there might be more to it than that?

I'm not sure what the Rust testing story for wasm targets is like. My guess (though I'm not too familiar with the wasm ecosystem) is that we can probably build the test executables for wasm targets, but we might need some wasm runtime in order to actually run the tests --- does anyone know if this is the case?

I also suspect that at least some of the tests may not pass on wasm, since they rely on things like thread::spawn. We might need to add conditional compilation attributes to disable some tests that use functionality not relevant to wasm...

@Mythra
Copy link
Contributor

Mythra commented Jul 16, 2020

Looking at it for another crate, that seems to be the case yeah. Building is easy, executing the tests is currently not the best story: rustwasm/team#173 (seems to be wasm-bindgen-test-runner is the accepted solution?) I'll take a look into this! See if we can get some tests passing.

@hawkw
Copy link
Member

hawkw commented Jul 16, 2020

Great, thank you! Do let me know if you have any questions about stuff on the tracing side --- I'm happy to help out, and excited to get wasm supported officially!

@Mythra
Copy link
Contributor

Mythra commented Jul 17, 2020

So I've started working on this, and most things truly "just work" with wasm-bindgen-test 🎉 ! The two things that don't work that I've noticed in the crates I've ported locally are:

Unfortunately there is one snag, I'm particularly not too fond of, and would like an idea of what would be the easiest for the project long term. So testing currently requires tagging tests with: #[wasm_bindgen_test].

So for example:

#[test]
fn default_name_test() {
    let (subscriber, handle) = subscriber::mock()
        .new_span(span::mock().named("default_name"))
        .enter(span::mock().named("default_name"))
        .exit(span::mock().named("default_name"))
        .done()
        .run_with_handle();

    with_default(subscriber, || {
        default_name();
    });

    handle.assert_finished();
}

Becomes:

#[test]
#[wasm_bindgen_test]
fn default_name_test() {
    let (subscriber, handle) = subscriber::mock()
        .new_span(span::mock().named("default_name"))
        .enter(span::mock().named("default_name"))
        .exit(span::mock().named("default_name"))
        .done()
        .run_with_handle();

    with_default(subscriber, || {
        default_name();
    });

    handle.assert_finished();
}

In this case testing for wasm is "opt in". There is currently no way to just have: #[test] macro work. AFAICT anything we do here will result in a giant PR that most people will need to rebase against to start adding: #[wasm_bindgen_test] to tests as well except in the very few cases where that test isn't compatible with wasm. Not to mention tests going forward have to be tagged like this which adds overhead for contributors.

TBH I can't think of a solution that looks really good here, adding a custom test macro that by default runs test && wasm-bindgen-test, and force everyone to rebase? Introduce a linter where new tests added that are tagged test, without wasm_bindgen_test have warnings thrown, and I do it in a wave of PRs that minimize rebases? Just introduce wasm_bindgen_test for the "most important" crates to start out, and do them bit by bit, so hopefully it minimizes pain? Something else?

I'd appreciate some insight as what to would be easier for y'all, I'd be happy to really take any solution, just wanna make sure it's the easiest for everyone involved. Thanks!

@hawkw
Copy link
Member

hawkw commented Jul 17, 2020

Hmm...in order to include the wasm_bindgen_test attribute, is there also an external dependency that's required?

I think just making the change crate-by-crate is probably the best approach, but I'm not sure. It would be good to get input from other contributors on that.

Why don't we start with a PR that just builds the crates for wasm targets on CI< and then add support for actually testing them in a follow-up?

@Mythra
Copy link
Contributor

Mythra commented Jul 17, 2020

Hmm...in order to include the wasm_bindgen_test attribute, is there also an external dependency that's required?

Yeah, there's a dev-dependency on wasm-bindgen-test crate. This includes both the underlying runner, and the test glue.

Why don't we start with a PR that just builds the crates for wasm targets on CI< and then add support for actually testing them in a follow-up?

Yeah, we can do that. I'll give it a bit to give others a chance to chime in, but will prepare it on my side 😄 .

@hawkw
Copy link
Member

hawkw commented Jul 17, 2020

Hmm...in order to include the wasm_bindgen_test attribute, is there also an external dependency that's required?

Yeah, there's a dev-dependency on wasm-bindgen-test crate. This includes both the underlying runner, and the test glue.

Okay, that sounds fine. Let's make sure that this dependency is in

[target.'cfg(target_arch = "wasm32)'.dev-dependencies]

and similar, so that it doesn't need to be downloaded when running the test for other targets?

Thanks for working on this!

@Mythra
Copy link
Contributor

Mythra commented Jul 17, 2020

Yep, I've got that locally to ensure it's good!

@hawkw
Copy link
Member

hawkw commented Aug 19, 2020

👋 Hi @securityinsanity, any updates on this? I've noticed that a handful of subscriber implementations for emitting diagnostics from tracing to various browser APIs are starting to show up, like tracing-wasm and wgpu-subscriber, so it would be nice to be actually building and testing tracing for wasm targets on CI.

Let me know if there are any blockers?

@Mythra
Copy link
Contributor

Mythra commented Aug 19, 2020

Ah sorry I just forgot to come back to this! I can push up the building Pr later today as I assume most people have had a chance to respond back by now. 😄

@hawkw
Copy link
Member

hawkw commented Aug 19, 2020

Great! No real rush, I just wanted to see where you were at and if you were stuck on anything. Thanks again!

Mythra added a commit to Mythra/tracing that referenced this issue Aug 20, 2020
refs tokio-rs#642

start building all crates, except `tracing-futures` in
wasm32-unknown-unknown. this will validate going forward we don't
break wasm32 build support.

in the future we can start running tests crate by crate, and actually
run those tests. the reason we're doing this is every single test
has to be marked with another special attribute, and add a dev-only
dependency. we don't wanna create a huge pr that has to have conflicts
fixed all the time.

in the future we can also look at adding in support for
tracing-futures.
hawkw pushed a commit that referenced this issue Aug 21, 2020
refs #642

## Motivation

More, and more code is targeting wasm architectures. This is useful for
not only browsers, but also useful for environments that want
extensibility where the host environment is protected, but still allows
extensibility in a variety of languages. Tracing can help these
architectures just as it can any other architecture.

## Solution

start building all crates, except `tracing-futures` in
wasm32-unknown-unknown architecture. this will validate going forward we
don't break wasm32 build support.

in the future we can start running tests crate by crate, and actually
run those tests. the reason we're doing this is every single test has to
be marked with another special attribute, and add a dev-only dependency.
we don't wanna create a huge pr that has to have conflicts fixed all the
time. in the future we can also look at adding in support for
tracing-futures.
hawkw pushed a commit that referenced this issue Aug 27, 2020
## Motivation

refs #642 

Start Testing the core crate in a wasm environment. This requires a
special runner, and an extra dev-dependency.

All tests have been ported over except for
`span::spans_always_go_to_the_subscriber_that_tagged_them_even_across_threads`
because that spins up a thread, and wasm has no concept of threads being
spun up.

## Solution

Add a wasm-pack tester, and properly tag all tests.
@hawkw hawkw added the area/wasm Related to improving support for WebAssembly. label Sep 29, 2020
@teohhanhui
Copy link

Just a note that:

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]

is not enough, since wasm_bindgen_test does not support WASI.

For WASI (wasm32-wasi target), there's no need for an additional attribute. Just the normal test.

So it should be:

#[cfg_attr(all(target_arch = "wasm32", not(target_os = "wasi")), wasm_bindgen_test::wasm_bindgen_test)]

@daxpedda
Copy link
Contributor

I don't know if this is still a desired feature, but to make tracing-subscriber at least work in the browser with external subscribers (events work, spans don't), e.g. tracing-web, I made #2758.

Though I'm happy to go further and actually add compatibility to tracing_subscriber::fmt::Layer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/wasm Related to improving support for WebAssembly. crate/subscriber Related to the `tracing-subscriber` crate crate/tracing Related to the `tracing` crate help wanted Extra attention is needed kind/feature New feature or request
Projects
None yet
Development

No branches or pull requests

6 participants