Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-53151

withContext not working as expected in combination with consoleLogFilter

    Details

    • Similar Issues:

      Description

      I'm trying to make a custom ConsoleLogFilter in my pipeline script, however for some reason it breaks the echo functionality.

       

      Here's my code:

      final class TestStream extends OutputStream {  
        private final OutputStream delegate;  
        TestStream(OutputStream delegate) {
          this.delegate = delegate
        }  
        public void write(int b) throws IOException {
          delegate.write(b);
        }  
        public void write(byte[] b) throws IOException {
          delegate.write(b);
        }  
        public void write(byte[] b, int off, int len) throws IOException {
          delegate.write(b, off, len);
        }  
        public void flush() throws IOException {
          delegate.flush();
        }  
         public void close() throws IOException {
          delegate.close();
        }
      }
      class TestFilter extends ConsoleLogFilter  {     
          @Override
          public OutputStream decorateLogger(AbstractBuild build, OutputStream logger)
                  throws IOException, InterruptedException {
              if (logger == null) {
                  return null;
              }
           
              return new TestStream(logger)
          }
      }
      ConsoleLogFilter subsequent = new TestFilter();
      ConsoleLogFilter original = getContext(ConsoleLogFilter.class);
      println original //prints null
      timestamps {
          original = getContext(ConsoleLogFilter.class);
          println original //prints  TimestampNotesConsoleLogFilter object
          echo "Out of Context" //Visible
          withContext(BodyInvoker.mergeConsoleLogFilters(original, subsequent)) {
              echo "In context " //Not visible
          }
          withContext(new TestFilter()) {
              echo "In context " //Not visible
          }
      }
      

      Here is the output:

      Started by user jenkins
      Running in Durability level: PERFORMANCE_OPTIMIZED
      [Pipeline] getContext
      [Pipeline] echo
      null
      [Pipeline] timestamps
      [Pipeline] {
      [Pipeline] getContext
      [Pipeline] echo
      07:22:58 hudson.plugins.timestamper.pipeline.TimestamperStep$TimestampNotesConsoleLogFilter@1d678d7a
      [Pipeline] echo
      07:22:58 Out of Context
      [Pipeline] withContext
      [Pipeline] {
      [Pipeline] echo
      [Pipeline] }
      [Pipeline] // withContext
      [Pipeline] withContext
      [Pipeline] {
      [Pipeline] echo
      [Pipeline] }
      [Pipeline] // withContext
      [Pipeline] }
      [Pipeline] // timestamps
      [Pipeline] End of Pipeline
      Finished: SUCCESS
      

       

      The 'in context' print is never written to the outputstream

        Attachments

          Activity

          roel0 roel postelmans created issue -
          roel0 roel postelmans made changes -
          Field Original Value New Value
          Description I'm trying to make a custom ConsoleLogFilter in my pipeline script, however for some reason it breaks the echo functionality.

           

          Here's my code:
          {code:java}

          final class TestStream extends OutputStream { private final OutputStream delegate; TestStream(OutputStream delegate) {
              this.delegate = delegate
            } public void write(int b) throws IOException {
              delegate.write(b);
            } public void write(byte[] b) throws IOException {
              delegate.write(b);
            }
            
            public void write(byte[] b, int off, int len) throws IOException {
              delegate.write(b, off, len);
            } public void flush() throws IOException {
              delegate.flush();
            } public void close() throws IOException {
              delegate.close();
            }
          }
          class TestFilter extends ConsoleLogFilter { @Override
              public OutputStream decorateLogger(AbstractBuild build, OutputStream logger)
                      throws IOException, InterruptedException {
                  if (logger == null) {
                      return null;
                  }
               
                  return new TestStream(logger)
              }
          }ConsoleLogFilter subsequent = new TestFilter();
          ConsoleLogFilter original = getContext(ConsoleLogFilter.class);
          println original //prints null
          timestamps {
              original = getContext(ConsoleLogFilter.class);
              println original //prints TimestampNotesConsoleLogFilter object
              echo "Out of Context" //Visible
              withContext(BodyInvoker.mergeConsoleLogFilters(original, subsequent)) {
                  echo "In context " //Not visible
              }
              withContext(new TestFilter()) {
                  echo "In context " //Not visible
              }
          }
          {code}
          Here is the output:
          {code:java}
          Started by user jenkins
          Running in Durability level: PERFORMANCE_OPTIMIZED
          [Pipeline] getContext
          [Pipeline] echo
          null
          [Pipeline] timestamps
          [Pipeline] {
          [Pipeline] getContext
          [Pipeline] echo
          07:22:58 hudson.plugins.timestamper.pipeline.TimestamperStep$TimestampNotesConsoleLogFilter@1d678d7a
          [Pipeline] echo
          07:22:58 Out of Context
          [Pipeline] withContext
          [Pipeline] {
          [Pipeline] echo
          [Pipeline] }
          [Pipeline] // withContext
          [Pipeline] withContext
          [Pipeline] {
          [Pipeline] echo
          [Pipeline] }
          [Pipeline] // withContext
          [Pipeline] }
          [Pipeline] // timestamps
          [Pipeline] End of Pipeline
          Finished: SUCCESS
          {code}
           

          The 'in context' print is never written to the outputstream
          I'm trying to make a custom ConsoleLogFilter in my pipeline script, however for some reason it breaks the echo functionality.

           

          Here's my code:
          {code:java}
          final class TestStream extends OutputStream {
            private final OutputStream delegate;
            TestStream(OutputStream delegate) {
              this.delegate = delegate
            }
            public void write(int b) throws IOException {
              delegate.write(b);
            }
            public void write(byte[] b) throws IOException {
              delegate.write(b);
            }
            public void write(byte[] b, int off, int len) throws IOException {
              delegate.write(b, off, len);
            }
            public void flush() throws IOException {
              delegate.flush();
            }
             public void close() throws IOException {
              delegate.close();
            }
          }
          class TestFilter extends ConsoleLogFilter {
              @Override
              public OutputStream decorateLogger(AbstractBuild build, OutputStream logger)
                      throws IOException, InterruptedException {
                  if (logger == null) {
                      return null;
                  }
               
                  return new TestStream(logger)
              }
          }
          ConsoleLogFilter subsequent = new TestFilter();
          ConsoleLogFilter original = getContext(ConsoleLogFilter.class);
          println original //prints null
          timestamps {
              original = getContext(ConsoleLogFilter.class);
              println original //prints TimestampNotesConsoleLogFilter object
              echo "Out of Context" //Visible
              withContext(BodyInvoker.mergeConsoleLogFilters(original, subsequent)) {
                  echo "In context " //Not visible
              }
              withContext(new TestFilter()) {
                  echo "In context " //Not visible
              }
          }
          {code}
          Here is the output:
          {code:java}
          Started by user jenkins
          Running in Durability level: PERFORMANCE_OPTIMIZED
          [Pipeline] getContext
          [Pipeline] echo
          null
          [Pipeline] timestamps
          [Pipeline] {
          [Pipeline] getContext
          [Pipeline] echo
          07:22:58 hudson.plugins.timestamper.pipeline.TimestamperStep$TimestampNotesConsoleLogFilter@1d678d7a
          [Pipeline] echo
          07:22:58 Out of Context
          [Pipeline] withContext
          [Pipeline] {
          [Pipeline] echo
          [Pipeline] }
          [Pipeline] // withContext
          [Pipeline] withContext
          [Pipeline] {
          [Pipeline] echo
          [Pipeline] }
          [Pipeline] // withContext
          [Pipeline] }
          [Pipeline] // timestamps
          [Pipeline] End of Pipeline
          Finished: SUCCESS
          {code}
           

          The 'in context' print is never written to the outputstream
          Hide
          jsmith45 Joe Smith added a comment -

          I was able to get this to work, by way of adding "NonCPS" annotations to each method in both classes. 

          The exact I tested:

           

          import hudson.console.ConsoleLogFilterclass TestStream extends OutputStream {  
            private final OutputStream delegate;  
            TestStream(OutputStream delegate) {
              this.delegate = delegate
            }  
            @NonCPS
            public void write(int b) throws IOException {
              delegate.write(b);
            }  
            @NonCPS
            public void write(byte[] b) throws IOException {
              delegate.write(b);
            }  
            @NonCPS
            public void write(byte[] b, int off, int len) throws IOException {
              delegate.write(b, off, len);
            }  
            @NonCPS
            public void flush() throws IOException {
              delegate.flush();
            }  
            @NonCPS
             public void close() throws IOException {
              delegate.close();
            }
          }
          class TestFilter extends ConsoleLogFilter  {     
              @Override @NonCPS
              public OutputStream decorateLogger(AbstractBuild build, OutputStream logger)
                      throws IOException, InterruptedException {
                  if (logger == null) {
                      return null;
                  }
               
                  return new TestStream(logger)
              }
          }
          node {
              withContext(new TestFilter()){
                  echo "test"
                  bat 'echo 123'
                  echo "test2"
              }
          }

          So it seems like the issue is that the CPS transformation is breaking these classes. This might actually be by design? I'm not familar enough with the transformation to say for sure, but it does seem odd that it breaks this.

           

          Show
          jsmith45 Joe Smith added a comment - I was able to get this to work, by way of adding "NonCPS" annotations to each method in both classes.  The exact I tested:   import hudson.console.ConsoleLogFilterclass TestStream extends OutputStream { private final OutputStream delegate; TestStream(OutputStream delegate) { this .delegate = delegate } @NonCPS public void write( int b) throws IOException { delegate.write(b); } @NonCPS public void write( byte [] b) throws IOException { delegate.write(b); } @NonCPS public void write( byte [] b, int off, int len) throws IOException { delegate.write(b, off, len); } @NonCPS public void flush() throws IOException { delegate.flush(); } @NonCPS public void close() throws IOException { delegate.close(); } } class TestFilter extends ConsoleLogFilter { @Override @NonCPS public OutputStream decorateLogger(AbstractBuild build, OutputStream logger) throws IOException, InterruptedException { if (logger == null ) { return null ; } return new TestStream(logger) } } node { withContext( new TestFilter()){ echo "test" bat 'echo 123' echo "test2" } } So it seems like the issue is that the CPS transformation is breaking these classes. This might actually be by design? I'm not familar enough with the transformation to say for sure, but it does seem odd that it breaks this.  
          abayer Andrew Bayer made changes -
          Component/s workflow-basic-steps-plugin [ 21712 ]
          Component/s pipeline [ 21692 ]
          Component/s pipeline-model-definition-plugin [ 21706 ]
          Assignee Andrew Bayer [ abayer ]
          vivek Vivek Pandey made changes -
          Labels console consoleoutput jenkins pipeline complex-cps-code console consoleoutput jenkins pipeline triaged-2018-11

            People

            • Assignee:
              Unassigned
              Reporter:
              roel0 roel postelmans
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated: