捕获詹金斯中每个管道阶段所花费的时间

时间:2018-09-13 21:52:14

标签: jenkins

我在jenkins中使用了多分支管道,并且想记录每个管道阶段花费的时间并将其存储在DB中。关于如何获得每个构建阶段的持续时间的任何想法?我只是想了解每个阶段的持续时间

4 个答案:

答案 0 :(得分:1)

这已经开放了一段时间,这是一个基于@adir-d's excellent answer

的可能答案
import io.jenkins.blueocean.rest.impl.pipeline.*

def jobName = "folder/project/master"
def run = Jenkins.instance.getItemByFullName(jobName).getBuildByNumber(42)

PipelineNodeGraphVisitor visitor = new PipelineNodeGraphVisitor(run)
def stageNodes = visitor.getPipelineNodes().findAll { it.getType() == FlowNodeWrapper.NodeType.STAGE }

    for (def node: stageNodes) {
        String stageName = node.getDisplayName()
        println "Result of stage ${node.getDisplayName()} is ${node.status.result} (${node.status.state})"
        println " timings: start=${node.timingInfo.startTimeMillis}ms; durationMillis=${node.timingInfo.totalDurationMillis}ms; paused=${node.timingInfo.pauseDurationMillis}ms"
        println "----------------------------------------------------------------"
    }

答案 1 :(得分:0)

仅作记录,因为这已经有相当长的时间没有得到回答,因此afaik还没有内置的方法来实现此目的(也许有一些插件?),但是jenkins管道脚本功能提供了自己添加此内容的灵活性,即在staget的开头添加一个记录时间戳的命令,在stage的末尾添加另一个命令。

即请查看this有关获取时间戳记值的信息,您可以自由地使用此值进行计算并将其存储到某些数据库或其他使用者。

答案 2 :(得分:0)

一个人也可以使用Jenkins工作流API来获取每个阶段的数据-

https://Jenkins_URL/job/${jobName}/wfapi/runs

这将返回一个JSON对象数组(默认情况下最后10个运行)

然后可以将这些数据存储在InfluxDB之类的时间序列数据库中。

答案 3 :(得分:0)

answer of Patrice M.乍看起来似乎是最优雅的,但是嵌套阶段和分支存在问题。嵌套节点的持续时间将不被考虑,而是仅报告节点自身的持续时间。

幸运的是,我们可以访问由FlowNodeWrapper包裹的基础TimingActionFlowNode来计算总持续时间,包括嵌套节点。

解决方案

  1. 找到代表分支或阶段开始的FlowNode。通过查询其节点TimingAction来获取该节点的开始时间。
  2. 找到代表分支或阶段结束的FlowNode。通过查询其节点TimingAction来获取该节点的开始时间。
  3. 计算这两个时间点之间的时差。

使用Blue Ocean插件API的PipelineNodeGraphVisitor可以很容易地找到分支和阶段的节点,正如我在先前的答案(for branchesfor stages)中所展示的那样。

要获取节点的开始时间,有一个方便的静态方法TimingAction.getStartTime(node)可以返回时间(以毫秒为单位)。

示例

import io.jenkins.blueocean.rest.impl.pipeline.PipelineNodeGraphVisitor
import io.jenkins.blueocean.rest.impl.pipeline.FlowNodeWrapper
import org.jenkinsci.plugins.workflow.actions.TimingAction

pipeline {
    agent any
    
    stages {
        stage('A') {
            stages {
                stage('A1') {
                    steps {
                        sleep 1
                    }
                }
                stage('A2') {
                    steps {
                        sleep 1
                    }
                }
            }
        }
    }
    post {
        always {
            printFinishedStageDurations()
        }
    }
}

void printFinishedStageDurations() {

    def visitor = new PipelineNodeGraphVisitor( currentBuild.rawBuild )

    // To find branches instead, replace NodeType.STAGE by NodeType.PARALLEL
    def stages = visitor.pipelineNodes.findAll{ it.type == FlowNodeWrapper.NodeType.STAGE }
    
    for( stage in stages ) {
        if( stage.node.endNode ) {   // only finished stages have endNode
            def startTime  = TimingAction.getStartTime( stage.node )
            def endTime    = TimingAction.getStartTime( stage.node.endNode )
            def duration   = endTime - startTime
        
            echo "Stage $stage.displayName duration: $duration ms" 
        }
    } 
}

输出

Pipeline Blue Ocean view

注意

在沙箱中运行上述示例代码时,由于使用“不安全的” Jenkins API,您将获得错误。按预期将printStageDurations()移到受信任的共享库中时不会发生这种情况。