Jenkins Pipeline - 如何从并行构建中获取日志

Jenkins Pipeline - how to get logs from parallel builds

是否可能,如果是:如何?分别获取每个并行步骤的日志输出?

即:

def projectBranches = [:]
        for (int i = 0; i < projects.size(); i++) {
            def _i = i
            projectBranches[_i] = {
                someFunction(_i)
            }
        }

        parallel projectBranches

现在是否可以获取每个 projectBranches[_i] 的日志?

您可以使用 Jenkins REST 获取您的节点 API: job/test/1/api/json?depth=2

结果应包含如下内容:

{"_class":"org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode","actions":[{},{},{}],"displayName":"Branch: 0","iconColor":"blue","id":"13","parents":["3"],"running":false,"url":"job/test/1/execution/node/13/"},
{"_class":"org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode","actions":[{},{},{}],"displayName":"Allocate node : Start","iconColor":"blue","id":"23","parents":["13"],"running":false,"url":"job/test/1/execution/node/23/"},
{"_class":"org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode","actions":[{},{}],"displayName":"Allocate node : Body : Start","iconColor":"blue","id":"33","parents":["23"],"running":false,"url":"job/test/1/execution/node/33/"},
{"_class":"org.jenkinsci.plugins.workflow.cps.nodes.StepAtomNode","actions":[{},{}],"displayName":"Print Message","iconColor":"blue","id":"37","parents":["33"],"running":false,"url":"job/test/1/execution/node/37/"}

因此,对于您的情况,您对 child 类型的分支的 StepAtomNode 感兴趣,并给出了名称(本例为 0-9)。从这里您可以通过简单地向地址添加日志来获得控制台输出地址(如:job/test/1/execution/node/37/log)。

现在这里有点难看,您需要解析 html 以从

获取实际日志
<pre class="console-output">log here
</pre>

我找到了实现该目标的方法,但您需要直接访问构建文件夹(例如使用 currentBuild.rawBuild.getLogFile().getParent())。

  • 解析workflow目录中的xml个文件(或单个flowNodeStore.xml文件):
    • 使用 <id><parentIds> 值构建节点层次结构。
    • 如果定义了<branchName>,则将其关联到当前节点,并递归到以该节点为父节点的所有节点。如果一个节点有多个父节点,则不为其分配分支值。
  • log 文件读取为 byte[]
  • 阅读 log-index 的每一行以找到要分配给每个节点的日志范围。行的格式可以是以下之一:
    • offset nodeId -> 新节点范围的开始,前一个节点范围的结束(如果存在)。
    • offset: 当前节点范围结束。
  • 将字节范围转换回 utf8 字符串 (new String(range, "UTF-8"))。
    • 您可能想用 replaceAll("\u001B.*?\u001B\[0m", "")
    • 之类的东西去除所有嵌入代码

我需要从管道代码中访问日志
所以我通过一些调整实现了キキジキ(真的很有帮助)提出的算法(在每行上添加branchName前缀,以便能够获取整个日志并仍然找出每行对应的分支;并支持嵌套分支,这我需要)在 https://github.com/gdemengin/pipeline-logparser :

  • 以编程方式获取日志

    • 获取带有分支前缀的完整日志(类似于 currentBuild.rawBuild.log 在 workflow-job 插件 2.2.5 版本之前返回的内容。但是在 2.26 版本中他们得到了去掉分支信息,我找不到任何具有相同信息的内置函数)
      String logs = logparser.getLogsWithBranchInfo()

      [Pipeline] Start of Pipeline
      [Pipeline] parallel
      [Pipeline] { (Branch: branch1)
      [Pipeline] { (Branch: branch2)
      [Pipeline] }
      [Pipeline] echo
      [branch1] in branch1
      [Pipeline] sleep
      [branch1] Sleeping for 1 sec
      [Pipeline] echo
      [branch2] in branch2
      [Pipeline] sleep
      [branch2] Sleeping for 1 sec

    • 仅从 'branch2' 获取日志
      String logsBranch2 = logparser.getLogsWithBranchInfo(filter: ['branch2'])

      [branch2] in branch2
      [branch2] Sleeping for 1 sec

  • 存档日志(在 $JOB_URL//artifacts 中)以供以后使用 link

    • 归档完整日志(带分支前缀)
      logparser.archiveLogsWithBranchInfo('consoleText.txt')

    • 仅从 branch2 归档日志
      logparser.archiveLogsWithBranchInfo('logsBranch2.txt', [filter: ['branch2']])