-
Notifications
You must be signed in to change notification settings - Fork 5k
Use problem information in build failure message #31374
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
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
0cdd3e3
to
9613256
Compare
* @return nothing, the method throws an exception | ||
* @since 8.12 | ||
*/ | ||
RuntimeException throwing(Throwable exception, Collection<? extends Problem> problems); |
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'm going to do the API cleanup separately.
This comment has been minimized.
This comment has been minimized.
9613256
to
568dfab
Compare
568dfab
to
d15be93
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
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.
Happy to see this shaping up!
Left some comments, PTAL.
* @since 8.10 | ||
*/ | ||
Collection<Problem> getProblems(); | ||
public interface ProblemLookup { |
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.
🤔 Something doesn't click with me with this classname, but I cannot come up with something better either.
Any case, this is internal so if we come up with something better, we can change it anytime.
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.
ProblemLocator?
...rojects/build-events/src/main/java/org/gradle/internal/build/event/types/DefaultFailure.java
Outdated
Show resolved
Hide resolved
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.
🎉 Nice cleanup, happy to see that exception mapping go away (at least from here)
...core/src/integTest/groovy/org/gradle/internal/buildevents/BuildFailureIntegrationTest.groovy
Outdated
Show resolved
Hide resolved
subprojects/core/src/main/java/org/gradle/internal/buildevents/BuildLoggerFactory.java
Outdated
Show resolved
Hide resolved
testing/architecture-test/src/changes/archunit-store/internal-api-nullability.txt
Outdated
Show resolved
Hide resolved
...distributions-integ-tests/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy
Show resolved
Hide resolved
@hegyibalint Thanks for the review, I'll clean up the items. Some of the issues come from cherry-picking changes from another (wip) branch. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
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.
Thanks for the fixes, let's merge this!
...distributions-integ-tests/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy
Show resolved
Hide resolved
The following builds have failed: |
@bot-gradle merge |
WARN: Based on labels, this pull request addresses notable issue but no changes to release note found. |
} | ||
} | ||
} catch (RuntimeException e) { | ||
e.printStackTrace(); |
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 don't think we should use e.printStackTrace()
in our code base. Not sure if you want to do some debug logging here or what is the actual problem we guard against. I'd just throw the runtime exception if we don't have anything in particular to guard against here.
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 agree, the printStackTrace()
call should be deleted. I'd rather not rethrow the exception. We compare exception instances with user-supplied types that can have exotic problems that we don't anticipate. If the comparison fails, I'd not break the control flow but continue with returning null.
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.
How can we find out that the exotic problems (or any problems) happen? Should we print out the problem on the info log?
StackTraceElement[] s1 = t1.getStackTrace(); | ||
StackTraceElement[] s2 = t2.getStackTrace(); | ||
for (int i = 0; i < s1.length && i < s2.length; i++) { | ||
if (!isSackTraceElementEquals(s1[i], s2[i])) { |
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.
isStackTraceElementEquals
instead of isSackTraceElementEquals
?
return null; | ||
} | ||
|
||
private boolean deepEquals(Throwable t1, Throwable t2, List<Throwable> seen) { |
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 really surprised we don't have that already somewhere.
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've spent some time looking around and I haven't found anything in Gradle nor in 3rd party libs (commons-lang, etc.).
|
||
private final Multimap<Throwable, Problem> problemsForThrowables = Multimaps.synchronizedMultimap(HashMultimap.<Throwable, Problem>create()); | ||
|
||
private final Multimap<Throwable, Problem> problemsForThrowables = Multimaps.synchronizedMultimap(MultimapBuilder.linkedHashKeys().linkedHashSetValues().<Throwable, Problem>build()); |
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.
❓ Is it a performance problem to use a synchronized multimap here? Can we use some kind of concurrent maps instead?
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 took a look an I think we cannot really improve the situation by using ConcurrentHashMap
. We need to ensure that updating the list of values are update atomically, which requires synchronisation anyway.
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.
Updating the list doesn't require synchronization if you use ConcurrentHashMap.compute()
. ConcurrentHashMap
should take care of that. Or are you referring to another list?
public Map<Throwable, Collection<Problem>> getProblemsForThrowables() { | ||
return problemsForThrowables.asMap(); | ||
public ProblemLookup getProblemLookup() { | ||
return new DefaultProblemLookup(); |
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.
❓ Why do we recreate this expensive class on each call instead of keeping the last one around?
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.
It raises concurrency issues if we cache the problem lookup. At the same time, we can make the expensive part (ie. initLookup()
lazy).
public Map<Throwable, Collection<Problem>> getProblemsForThrowables() { | ||
return problemContainer.getProblemsForThrowables(); | ||
public ProblemLookup getProblemLookup() { | ||
return problemContainer.getProblemLookup(); |
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.
🤔 That looks somewhat problematic: The problem lookup is only ready at the end, though we allow the lookup from the details object. Why is the problem lookup not a service?
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'll probably need some help with that. FWIW problemlookup needs to be accessible ClientForwardingBuildOperationListener which is created in the context of ToolingBuilderServices
which has no access to build tree scope services.
public Map<Throwable, Collection<Problem>> getProblemsForThrowables() { | ||
return problemContainer.getProblemsForThrowables(); | ||
public ProblemLookup getProblemLookup() { | ||
return problemContainer.getProblemLookup(); |
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.
💅 problemContainer
should probably be called exceptionProblemRegistry
.
public interface CompilationFailedIndicator extends NonGradleCause { | ||
|
||
@Nullable | ||
String getDiagnosticCounts(); |
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 name of this makes me think it is going to return structured data containing the counts. Maybe reportDiagnosticSummary()
or something might be a better name.
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.
Thanks for helping out with the naming!
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.
getDiagnosticSummary or getReportDiagnosticSummary?
String message = t.getMessage(); | ||
result = message == null ? "" : message; | ||
} catch (RuntimeException ignore) { | ||
// ignore exceptions with faulty getMessage() implementation |
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.
❓ Won't this cause issues finding the proper exception if there are multiple instances of an exception with a faulty getMessage()
implementation that are thrown?
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 don't see how. Both faulty exceptions would have still the same key in the lookup.
* @since 8.10 | ||
*/ | ||
Collection<Problem> getProblems(); | ||
public interface ProblemLookup { |
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.
ProblemLocator?
|
||
@Override | ||
public String getDiagnosticCounts() { | ||
return null; |
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.
💅 Shouldn't this method be annotated @Nullable
as well?
Fixes #31376
Reviewing cheatsheet
Before merging the PR, comments starting with