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']])
是否可能,如果是:如何?分别获取每个并行步骤的日志输出?
即:
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']])