-
Notifications
You must be signed in to change notification settings - Fork 124
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
[JEP-210] Log handling rewrite #27
Conversation
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.
Looks good so far
if (executor != null) { | ||
AsynchronousExecution asynchronousExecution = executor.getAsynchronousExecution(); | ||
if (asynchronousExecution != null) { | ||
asynchronousExecution.completed(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.
Why would we need it?
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.
Uses to be part of copyLogsTask
(line 278); that is now gone, so we need to somehow release the flyweight executor slot. This seems like the appropriate place to do it.
pom.xml
Outdated
</pluginRepository> | ||
</pluginRepositories> | ||
<properties> | ||
<jenkins.version>1.642.3</jenkins.version> | ||
<hpi-plugin.version>1.120</hpi-plugin.version> |
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.
Ideally should be updated in the Parent POM
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.
Please review jenkinsci/plugin-pom#35. :-)
@@ -200,8 +181,10 @@ public WorkflowRun(WorkflowJob job, File dir) throws IOException { | |||
} | |||
try { | |||
onStartBuilding(); | |||
// TODO introduce API to wrap out log location |
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.
Implementation from the prototype: https://github.com/oleg-nenashev/workflow-job-plugin/tree/jw-hackaton-external-logging
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.
Saw that, but it is not going to work.
@@ -825,6 +646,10 @@ private String key() { | |||
return TaskListener.NULL; | |||
} | |||
} | |||
@Override public InputStream getLog() throws IOException { |
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.
Maybe Stream is not a perfect solution for Logging. I would rather go after an event-based model similar to JUL, but it will require more changes (it's in my design btw)
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.
Tons of Jenkins APIs expect a TaskListener
or OutputStream
for output, and expect an AnnotatedLargeText
or InputStream
for input, so streams are mandated at some level I think. Of course a logging implementation might internally work with lines.
*/ | ||
public class WorkflowRunConsoleNote extends ConsoleNote<Run<?, ?>> { | ||
|
||
/** | ||
* Prefix used in metadata lines. | ||
*/ | ||
public static final String CONSOLE_NOTE_PREFIX = "[Pipeline] "; | ||
private static final String CONSOLE_NOTE_PREFIX = "[Pipeline] "; |
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.
🐜 binary compat change without a real need
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.
Just minimizing access of things which were never really supposed to be public
.
…e for getLogFile().
…y encompassing all of the functionality of jenkinsci#21.
// TODO log-related overrides pending JEP-207: | ||
|
||
@Override public InputStream getLogInputStream() throws IOException { | ||
// Inefficient but probably rarely used 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.
And comments like this make me realize that the log-handling rewrite that was supposed to deliver some great performance improvements may fall well short of that mark.
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.
My interest is in writes, not reads.
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.
Not much point of a log that nobody reads though, is there? Anyway, we can see if it comes up as an issue.
Also, please do not mark this one "resolved" unless the code has been changed due to feedback -- it'll make it easier to address this if it comes up as a problem in the future.
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.
This particular method is rarely called AFAIK.
|
||
@Override public List<String> getLog(int maxLines) throws IOException { | ||
int lineCount = 0; | ||
List<String> logLines = new LinkedList<>(); |
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 you should never use a LinkedList. TL;DR: Locality-of-reference matters, allocate a darned ArrayList
.
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.
This is just copied from core.
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.
Note that the core implementation of this method has since been rewritten. As I pointed out in jenkinsci/jenkins#2607 (comment) that is irrelevant, since this method is not used in production workflows. Anyway the rewrite is impossible to apply here since it relies on RandomAccessFile
.
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.
Copy and pasted code? Still...
I'm going to keep pointing out that LinkedList is a bad idea until people stop (ab)using it.
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.
This method is not used in production. The performance does not matter.
@@ -1291,6 +1124,15 @@ public void save() throws IOException { | |||
synchronized (this) { | |||
PipelineIOUtils.writeByXStream(this, loc, XSTREAM2, isAtomic); | |||
SaveableListener.fireOnChange(this, file); | |||
if (Boolean.TRUE.equals(completed)) { |
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.
@jglick No! 🐛 🐛 🐛 and a whole nest of 🐛s. This is not the right place to be terminating the AsynchronousExecution - if an IOException never occurs, the build never finishes.
You're welcome to do an extra on-save check somewhere logical -- because we have had hard-to-trace issues with the build not getting killed before, but this makes undead Pipelines more likely.
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.
There is explanation elsewhere of why we have to do the termination here. I can think about whether it is possible to do so more forcefully, such as in a finally
block.
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.
if an IOException never occurs
I suppose you mean if an IOException
does occur.
the build never finishes
As noted in a separate thread, even if no subsequent call to save
is ever made, it is misleading to say that the build is “not finished”. Rather, there would be a stale AsynchronousExecution
, which likely has little or no visible impact.
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.
(see #27 (comment) for fuller discussion)
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.
A stale AsynchronousExecution translates to essentially a "zombie" job that proves highly irritating to users -- it seems like it never completes even if the build is marked as done. Also it holds onto the OneShotExecutor indefinitely.
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.
Again the AsynchronousExecution
normally has no visible effect on anything—it only appears while we are actively running Groovy code, which of course we are not if the build is completed
.
And again if some problem in existing code (whether in workflow-job
or workflow-cps
) results in a condition whereby <completed>true</completed>
never gets written to build.xml
, the AsynchronousExecution
is the least of your concerns, since after the next restart onLoad
will be confused. Possibly #93 will defend against that case—figure out that completed
is wrong and save the correction—but at that point any old Executor
s are no longer an issue anyway (and there should be no new AfterRestartTask
).
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 think the after-restart case should have been fixed by #104.
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.
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 done my best to give this at least a decent readthrough (though I don't imagine every bug has been caught). There are a couple bugs that need fixing but in general the implementation is pretty sane.
Or as sane as Pipeline internals are going to be anyway, given some of the Lovecraftian back-compatibility horrors they're dragging along with them... (ia ia FlowGraph f'htagn!) 🐙
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 handling of AsynchronousExecution
s here is wrong and will probably break in the face of some fairly common cases (IOExceptions, etc). But that's not going to cause Critical/Blocker issues for users, just annoying ones. So, I'm removing my "changes requested" and this can go forward without my approval (I don't feel right "approving" something which I see actual bugs in).
The more critical risks here are the problems we can't anticipate, anyway.
…Also reduce scope of lock.
src/main/java/org/jenkinsci/plugins/workflow/job/console/NewNodeConsoleNote.java
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.
This still does not feel like the correct place to mark the AsynchronousExecution
completed, but it seems to work as far as I can tell from cross-testing, whereas for reasons I'm still at a loss to explain, the correct place to mark it generates test flakes (primarily in CI) -- see #108 -- so I say we roll with this and release it -- with appropriate cautions that the log handling rewrite is a more-than-normal risk for people updating.
Also unclear to me why. I note that the last build of this PR not only passed, but acc. to the log had no flakes. Anyway, this is something that could be sorted out later—there is no API or settings impact. |
Downstream of jenkinsci/workflow-api-plugin#17 and jenkinsci/workflow-support-plugin#15. Cf. #21.
JEP-210
ConsoleNote
on every lineoptimizePipelineLargeText.<init>
optimizeWorkflowRun.getLogInputStream
Nice-to-have things I am deferring:
parallel
branch by default