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

JSON #62

Closed
Raniz85 opened this issue Jun 4, 2020 · 6 comments
Closed

JSON #62

Raniz85 opened this issue Jun 4, 2020 · 6 comments
Labels

Comments

@Raniz85
Copy link

Raniz85 commented Jun 4, 2020

I'm trying to implement JSON logging using fern, but I'm having issues with messages containing newlines.

See this example program:

fn main() {
    let mut dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{{ \"message\": \"{}\" }}",
                message
            ))
        })
        .chain(std::io::stdout())
        .apply().unwrap();
    log::info!("This is a single line and works fine");
    log::info!("This is mulitple lines\n and doesn't produce valid JSON");
}

And the output:

{ "message": "This is a single line and works fine" }
{ "message": "This is mulitple lines
 and doesn't produce valid JSON" }

Is there any good way of escaping the newline(s) in the message?

@daboross
Copy link
Owner

daboross commented Jun 4, 2020

If you're OK with it, how about using an existing json crate? It'll have robust handling of this kind of issue.

For instance, using serde_json, I think something like the following should work:

fn main() {
    let mut dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}",
                serde_json::to_string(&serde_json::json!(
                    {
                        "message": message,
                    }
                )).expect("formatting `serde_json::Value` with string keys never fails")
            ))
        })
        .chain(std::io::stdout())
        .apply().unwrap();
    log::info!("This is a single line and works fine");
    log::info!("This is mulitple lines\n and doesn't produce valid JSON");
}

This has the disadvantage of making multiple allocations per message, but it'll be quite robust.

If serde_json is too heavy weight, then tinyjson might be better? It has a much lower compile-time cost, and the runtime will probably be slightly faster as well.

fn main() {
    let mut dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{{\"message\":{}}}",
                tinyjson::JsonValue::String(message.to_string()).stringify()
                .expect("no inf floats in a string")
            ))
        })
        .chain(std::io::stdout())
        .apply().unwrap();
    log::info!("This is a single line and works fine");
    log::info!("This is mulitple lines\n and doesn't produce valid JSON");
}

Let me know what your constraints are, and we might be able to find a better solution?

@Raniz85
Copy link
Author

Raniz85 commented Jun 4, 2020

Using serde_json hadn't occured to me, but that works really well.

Thanks!

Maybe mention this in the docs? :)

@Raniz85 Raniz85 closed this as completed Jun 4, 2020
@daboross
Copy link
Owner

daboross commented Jun 5, 2020

I'd originally thought that structured logging would be coming to log a lot sooner and we'd be able to add builtin json/other serde logging based on that. But I think you might be right - adding documentation for doing this with regular logging would be a good idea.

@Raniz85
Copy link
Author

Raniz85 commented Jun 5, 2020

Key/Value logging seems to have arrived in the log crate now.

https://docs.rs/log/0.4.8/log/struct.Record.html#method.key_values

@daboross
Copy link
Owner

daboross commented Jun 5, 2020

Oh! I must have not been watching the right issues/etc. I'll have to go back and look at when that happened, and see if there's anything we want to change in fern based on that.

Thanks!

@daboross
Copy link
Owner

daboross commented Jun 5, 2020

Looks like it's still unstable right now, but other logging crates have already started integrating into it.

I've opened #63 to do some initial brainstorming for how fern should support this. I probably won't have time to actually do the planning nor implementation soon, but this will track it for the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants