withContext() in Jenkins pipeline script is hiding console output

旧巷老猫 提交于 2020-06-26 09:44:30

问题


I have this jenkins pipeline script (you should be able to just paste it directly into a blank pipeline build)

import hudson.console.LineTransformationOutputStream
import hudson.console.ConsoleLogFilter
import java.nio.charset.Charset
import java.nio.charset.StandardCharsets

class MyConsoleLogFilter extends ConsoleLogFilter {

    OutputStream decorateLogger(AbstractBuild build, OutputStream logger)
            throws IOException, InterruptedException {
        return new MyOutputStream(logger, StandardCharsets.UTF_8)
    }
}

class MyOutputStream extends LineTransformationOutputStream {
    def logger
    def charset

    MyOutputStream(OutputStream logger, Charset charset) {
        this.logger = logger
        this.charset = charset
    }

    void close() throws IOException {
        super.close();
        logger.close();
    }

    void eol(byte[] bytes, int len) throws IOException {
        String line = charset.decode(ByteBuffer.wrap(bytes, 0, len)).toString();
        logger.write("xxx ".getBytes(charset))
        logger.write(line.getBytes(charset));
    }
}

node {
    withContext(new MyConsoleLogFilter()) {
        echo 'Hello World'
    }
    echo 'Hello World'
}

I expect to see the first Hello World prefixed by xxx, because of the wrapping by MyConsoleLogFilter.

But all I see is greyed out console output as follows:

Started by user Admin
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/mike-learning
[Pipeline] {
[Pipeline] withContext
[Pipeline] {
[Pipeline] echo
[Pipeline] }
[Pipeline] // withContext
[Pipeline] echo
Hello World
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

Why is the console output from within the withContext() block being hidden?


回答1:


A colleague (Hibri Marzook) solved this for me. He pointed me towards https://issues.jenkins-ci.org/browse/JENKINS-53151 , which prompted me to do this:

import hudson.console.LineTransformationOutputStream
import hudson.console.ConsoleLogFilter
import java.nio.charset.Charset
import java.nio.charset.StandardCharsets

class MyConsoleLogFilter extends ConsoleLogFilter {
    @NonCPS
    OutputStream decorateLogger(AbstractBuild build, OutputStream logger)
            throws IOException, InterruptedException {
        return new MyOutputStream(logger, StandardCharsets.UTF_8)
    }
}

class MyOutputStream extends LineTransformationOutputStream {
    def logger
    def charset

    MyOutputStream(OutputStream logger, Charset charset) {
        this.logger = logger
        this.charset = charset
    }

    @NonCPS
    void close() throws IOException {
        super.close();
        logger.close();
    }

    @NonCPS
    void eol(byte[] bytes, int len) throws IOException {
        def line = charset.decode(java.nio.ByteBuffer.wrap(bytes, 0, len)).toString();
        logger.write("xxx ".getBytes(charset))
        logger.write(line.getBytes(charset));
    }
}

node {
    withContext(new MyConsoleLogFilter()) {
        echo 'Hello World'
    }
    echo 'Hello World'
}

and now it works.




回答2:


An alternative is to implement this with a Java plugin, you don't need the NonCPS annotation but to implement the Serializable interface:

@Extension
public class MyConsoleLogFilter extends ConsoleLogFilter implements Serializable {
    private static final long serialVersionUID = 1;

    @Override
    public OutputStream decorateLogger(Run build, final OutputStream logger) {
        return new MyOutputStream(logger, StandardCharsets.UTF_8);
    }

    private class MyOutputStream extends LineTransformationOutputStream {
        private OutputStream logger;
        private Charset charset;

        MyOutputStream(OutputStream logger, Charset charset) {
            this.logger = logger;
            this.charset = charset;
        }

        public void close() throws IOException {
            super.close();
            logger.close();
        }

        public void eol(byte[] bytes, int len) throws IOException {
            String line = charset.decode(java.nio.ByteBuffer.wrap(bytes, 0, len)).toString();
            logger.write("xxx ".getBytes(charset));
            logger.write(line.getBytes(charset));
        }
    }

}


来源:https://stackoverflow.com/questions/53262813/withcontext-in-jenkins-pipeline-script-is-hiding-console-output

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!