🕰️
[Jenkins] 特定の時間に動いていたビルドを探す
今いま問題が起きている場合は
とりあえずトップページから実行中のビルドを探せば良いのですが
過去の時点で実行中だったビルドを探すのは難しい
ユーザーに聞いて回るのは手間ですし不正確
かと言って、ビルドページを一つひとつ開いて確認するなんて非効率過ぎる。。
CIAnalyzerと簡単なスクリプトで解析する
ビルド情報を取得する
Jenkinsのビルド情報をJSON形式で引っこ抜いてきてくれる便利ツールがあるので、これを使いましょう。
git clone https://github.com/Kesin11/CIAnalyzer.git
cd CIAnalyzer
vim ci_analyzer.yaml
baseUrlは自分のJenkinsに合わせて変更してください。
ci_analyzer.yaml
jenkins:
baseUrl: https://localhost:8080
correctAllJobs: # Enable correct all pipeline jobs
filterLastBuildDay: 30 # Filter by last build day. default: 30
isRecursively: true # Also collect jobs under folders. default: false
jobs: []
exporter: &exporter
local:
outDir: output # default: output
format: json # default: json. 'json' and 'json_lines' are supported.
lastRunStore:
backend: local
path: .ci_analyzer/last_run/jenkins.json
いよいよ、ビルド情報を取得します。
export JENKINS_USER=admin
export JENKINS_TOKEN=***
docker run \
--mount type=bind,src=${PWD},dst=/app/ \
-e JENKINS_USER=${JENKINS_USER} \
-e JENKINS_TOKEN=${JENKINS_TOKEN} \
ghcr.io/kesin11/ci_analyzer:v5.1 -c ci_analyzer.yaml
outputフォルダ下にビルド情報が格納されているはずです。
ビルド情報を解析する
Elasticsearch等を使っても良いのですが、データ量がそんなに無いうちはインメモリーのSQLiteでサクッと解析するのが楽です。
analyze.py
import sys, json, sqlite3
########################
# Validation
########################
if len(sys.argv) < 3:
print('Usage: python analyze.py /path/to/json problematicTime')
sys.exit(1)
########################
# Initialization
########################
data_path = sys.argv[1]
data = None
problematicTime = sys.argv[2]
con = sqlite3.connect(':memory:')
cur = con.cursor()
# Create table
cur.execute('''CREATE TABLE jenkins (id text primary key, job text, duration real, startedAt text, completedAt text)''')
########################
# Insert data
########################
with open(data_path) as json_file:
data = json.load(json_file)
for d in data:
workflowRunId = d.get("workflowRunId")
workflowName = d.get("workflowName")
workflowDurationSec = d.get("workflowDurationSec")
workflowStartedAt = d.get("startedAt")
workflowCompletedAt = d.get("completedAt")
if not (workflowRunId and workflowName and workflowDurationSec and workflowStartedAt and workflowCompletedAt):
continue
duration = int(workflowDurationSec)
# Insert a row of data
cur.execute("INSERT INTO jenkins VALUES ('{}', '{}', {}, '{}', '{}')".format(workflowRunId, workflowName, duration, workflowStartedAt, workflowCompletedAt))
# Save (commit) the changes
con.commit()
########################
# Analyze data
########################
print('Job running at {}'.format(problematicTime))
for row in cur.execute("SELECT id, startedAt, completedAt FROM jenkins WHERE startedAt < '{}' AND completedAt > '{}'".format(problematicTime, problematicTime)):
print('Build: "{0[0]}" - started at {0[1]} completed at {0[2]}'.format(row))
# We can also close the connection if we are done with it.
# Just be sure any changes have been committed or they will be lost.
con.close()
SQLiteは賢いのでWHERE句の大小比較で時間を絞り込めます。
python analyze.py output/20220927-1021-workflow-jenkins.json '2022-09-27T09:00'
Job running at 2022-09-27T09:00
Build: "jenkins-JOB_NAME-1" - started at 2022-09-27T08:56:28.014Z completed at 2022-09-27T09:05:50.208Z
jenkinsは接頭語ですので、その後ろのJOB_NAMEが疑わしいジョブ名、そしてその後ろの数字がビルド番号です。
ビルドの実行者もしくはジョブの設定者に突撃する
問題があるジョブは、そっとDisableにすることをお勧めします。
Discussion