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 an annotation-based logging framework for Java programs #6584

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

SamCarlberg
Copy link
Member

@SamCarlberg SamCarlberg commented May 4, 2024

An annotation processor will generate data loggers at compile time based on the contents of the annotated classes.

Logging is opt-out by default; placing an @Logged annotation on a class will attempt to log everything in that class. This can be configured by setting the strategy on the class and by configuring the importance levels on the logged elements, or by placing a @NotLogged annotation on fields and methods that should always be excluded

Explicitly tagging a non-loggable element will result in a compile-time error

Data is logged to NetworkTables by default, but can be configured to use any backend (just implement the DataLogger interface)

This relies on features added between Java 11 and 17, including text blocks and pattern matching, and I've included a small commit that bumps our source compatibility. We already build with and ship JDK 17 to teams, so this is just giving us access to those language features. Added separately in #6585

@SamCarlberg SamCarlberg requested review from a team as code owners May 4, 2024 17:23
@SamCarlberg
Copy link
Member Author

/format

@Oblarg
Copy link
Contributor

Oblarg commented May 4, 2024

This looks really good! Two thoughts:

  1. OPT_IN seems like a safer default behavior than OPT_OUT
  2. It might be better to not to overload @Epilogue for opting-in class members? I'm up in the air about this one: On the one hand, it's definitely simpler to only have to remember one annotation name; on the other, though, splitting them makes it easier to understand the compile-time error behavior of opting-in an untagged class (otherwise, "why do I need to repeat the annotation in two places?").

}
out.println();

// public class FooLogger implements ClassSpecificLogger<Foo> {
Copy link
Contributor

Choose a reason for hiding this comment

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

whoops

Copy link
Member Author

Choose a reason for hiding this comment

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

Hah. I originally had this printing out elements individually, so comments were helpful for showing examples of what the code was generating. I later refactored it to use string concats and this got left over

@SamCarlberg
Copy link
Member Author

SamCarlberg commented May 5, 2024

OPT_IN seems like a safer default behavior than OPT_OUT

The idea is to make the lowest-friction way of using the library to also be what provides the most information. Therefore, tagging a class with @Epilogue should be all that's needed to log everything in that class.

It might be better to not to overload @Epilogue for opting-in class members? I'm up in the air about this one: On the one hand, it's definitely simpler to only have to remember one annotation name; on the other, though, splitting them makes it easier to understand the compile-time error behavior of opting-in an untagged class (otherwise, "why do I need to repeat the annotation in two places?").

There was a lot of back and forth on that. But getting back to simplicity, this means only a single annotation needs to get used (and a separate @NotLogged annotation for opting out, rather than an ImportanceLevel.NONE or skip = true attribute that I'd experimented with. That was too much overloading). The only other annotation is @CustomLoggerFor to allow user-defined loggers for third-party types (eg vendor motor controllers and sensors) to be detected and pulled in at compile time

@Oblarg
Copy link
Contributor

Oblarg commented May 5, 2024

I worry that "most information" might not be the default behavior that's most-useful in practice beyond initial prototyping phases. I might be biased towards complex codebases with a high base-level of internal complexity, though.

I agree that skip = true is too far; I feel that the overloading now is convenient but that @Epilogue (as opposed to @Log or @Logged) reads a tiny bit less cleanly when applied to members (as opposed to classes). Feels less imperative-y than the explicit verbs.

@Starlight220
Copy link
Member

I've included a small commit that bumps our source compatibility.

For sake of tracking history, that should be a separate PR.

@SamCarlberg
Copy link
Member Author

I worry that "most information" might not be the default behavior that's most-useful in practice beyond initial prototyping phases. I might be biased towards complex codebases with a high base-level of internal complexity, though.

Higher complexity codebases can surely add a bit more complexity and use explicit logging configurations. My concern is that forcing users to tag everything they want (and have to decide what they want) is too much overhead; people generally want something that does what they want with the least time and effort possible.

I agree that skip = true is too far; I feel that the overloading now is convenient but that @Epilogue (as opposed to @Log or @Logged) reads a tiny bit less cleanly when applied to members (as opposed to classes). Feels less imperative-y than the explicit verbs.

Yep, having the annotation name a verb makes sense. I considered changing it to @AutoLogged but I think akit already uses that name? And I don't want to introduce confusion between what's in wpilib and what's in third party libraries. Just @Logged could work, and it mirrors the existing @NotLogged annotation

I've included a small commit that bumps our source compatibility.
For sake of tracking history, that should be a separate PR

I agree; the squash merge would hide the upgrade. Looks like @spacey-sooty is top of things and already opened a PR 🙂

@Oblarg
Copy link
Contributor

Oblarg commented May 5, 2024

I think @Logged is probably the best bet for consistency and clarity. I have a personal bias for @Log since it's really short, but it really doesn't matter and not overlapping with third-party identifiers is a good thing.

SamCarlberg and others added 7 commits May 5, 2024 11:03
An annotation processor will generate loggers at compile time

Logging is opt-out by default; placing an `@Epilogue` annotation on a class will attempt to log *everything* in that class. This can be configured by setting the strategy on the class and by configuring the importance levels on the logged elements

Explicitly tagging a non-loggable element will result in a compile-time error

Data is logged to NetworkTables by default
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.

None yet

4 participants