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

Support for lazy arguments #14

Closed
wants to merge 5 commits into from

Conversation

NeilRickards
Copy link

@NeilRickards NeilRickards commented Jul 21, 2017

Closes #8

What do you think to something like this? Then, instead of:

    if (logger.isDebugEnabled()) {
        logger.debug("Message {}", SafeArg.of("name", expensiveFunc()));
    }

I could do:

    logger.debug("Message {}", SafeArg.of("name", () -> expensiveFunc()));

Log4j 2 supports something similar, but slf4j are still talking about it.

What do you think to something like this?  Then, instead of:
```
    if (logger.isDebugEnabled()) {
        logger.debug("Message {}", SafeArg.of("name", expensiveFunc()));
    }
```
I could do:
```
    logger.debug("Message {}", SafeArg.of("name", () -> expensiveFunc()));
```
Log4j 2 supports something similar, but slf4j are still talking about it.
@markelliot
Copy link

Might be preferable to do this in the Appender

@NeilRickards
Copy link
Author

How would that work @markelliot? At the point I call org.slf4j.Logger.debug I don't know what the appender is, so don't know if a Supplier will be evaluated. All I can be confident of is it will call toString on the object I pass.

@markelliot
Copy link

markelliot commented Jul 26, 2017 via email

@gracew
Copy link
Contributor

gracew commented Jul 28, 2017

our internal layout actually doesn't call toString on objects by default, preferring to use the json representation if one exists.

so I think we need to make this change to getValue as well.

also, I think this closes #8

@NeilRickards
Copy link
Author

Good point @gracew. Updated -> how about something like this?

Copy link
Contributor

@schlosna schlosna left a comment

Choose a reason for hiding this comment

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

I have some perf concerns around current impl

}

public static <T> SafeArg<T> of(String name, T value) {
return new SafeArg<>(name, value);
return new SafeArg<>(name, () -> value);
Copy link
Contributor

Choose a reason for hiding this comment

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

Would highly recommend adding some JMH benchmarks to compare before and after here as this is going to add more allocations on potentially hot paths. I have a feeling we probably want a lazy and static impl for each safe and unsafe, and you can move most code into an abstract base class


protected Arg(String name, T value) {
private boolean cached;
private T value;
Copy link
Contributor

Choose a reason for hiding this comment

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

See below, but I don't think we want to eat these extra fields for non-lazy args

@carterkozak
Copy link
Contributor

This code is entirely unnecessary if we use a better logging api, as mentioned in the description the following already works as you have described using log4j2 org.apache.logging.log4j.Logger:

log.info("Hello {}", () -> SafeArg.of("whom", "World"));

This approach avoids the allocation of a new SafeArg insteace, only requiring a new supplier, where the proposed solution requires allocation of both.

Copy link
Contributor

@carterkozak carterkozak left a comment

Choose a reason for hiding this comment

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

I don't think it's Args job to solve this.

@iamdanfox iamdanfox closed this Feb 22, 2019
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.

6 participants