-
Notifications
You must be signed in to change notification settings - Fork 842
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
Simplify and remove duplicate logic in AI model observation components #1653
base: main
Are you sure you want to change the base?
Conversation
653ce14
to
070353e
Compare
@@ -62,12 +64,13 @@ public ErrorLoggingObservationHandler(Tracer tracer, | |||
} | |||
|
|||
@Override | |||
public boolean supportsContext(Context context) { | |||
return (context == null) ? false : this.supportedContextTypes.stream().anyMatch(clz -> clz.isInstance(context)); | |||
public boolean supportsContext(@Nullable Context context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Context
is never null as per the Micrometer infrastructure. Is there a reason for making it nullable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am going to remove the @Nullable
annotation so it generates the appropriate warnings in the supported IDEs.
} | ||
|
||
@Override | ||
public void onError(Context context) { | ||
@SuppressWarnings("unused") | ||
public void onError(@Nullable Context context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same thing here, the Context
is never null as per the Micrometer infrastructure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above.
General comment about the added |
070353e
to
29cdc0b
Compare
Well, this and this, contradicts the contract. I would argue that it is never good for any code to throw a NPE, especially in boolean methods that should simply return So, I think the In both cases, I have made changes. |
Thanks for mentioning those two points. I didn't actually notice we were performing a null check there. It might be the only Micrometer API-related implementation where we do that, because all other handlers, predicates, and filters I know of don't do that. I would say those two checks shouldn't be there since the interface is marked with
Totally agree with you. But then we should add a check to verify the compliance with the contract, which is a non-null contract, rather than allowing null. And that check is indeed missing. We could add the following. What do you think?
Micrometer itself ensures that handlers, predicates, and filters are called with a non-null context, but if at some point a null value is passed, then we get an exception thrown since that should never happen and we entered a faulty state of the application. |
|
||
private ChatModelObservationContentProcessor() { | ||
} | ||
public abstract class ChatModelObservationContentProcessor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this to be abstract?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great question!
For extensibility purposes, I often prefer classes marked as abstract
rather than final
with a private
constructor, even if they mostly, or entirely, contain static methods (e.g. utility classes).
This prevents the class from being immediately instantiated (without extra effort) and allows the class to be extended with another abstract (or concrete) class that may be context-specific. Additionally this helps to reduce the responsibility and footprint of the parent class.
For example, FileSystemUtils
to FileUtils
to IOUtils
(extending nothing).
Of course this is debatable and so I am not a huge stickler on this.
I believe one of Spring's primary strengths is its excellent implementation of the Open/Closed principle. This upholds Spring's principle of choice and gives developers options OOTB if the base functionality does not quite meet their needs.
In fact, in this particular case, I'd probably even prefer that the ChatModelObservationContentProcessor
class not contain static
methods, and that instance could even be treated as a proper bean.
Again, I am flexible here.
Agreed. And, I already changed the PR to do exactly what you suggested. |
Hi @tzolov & @ThomasVitale (CC'ing @jonatan-ivanov), I did have a question (or 2) about Spring AI's Observability story. While my questions focus on
For instance, in However, some of the high-cardinality keys do not seem as though they would have an "unbounded range of values"; for example: I even debated about On the other hand, the
This seems logical to me that they nicely align in this way.
|
See title.