Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Datadog にカスタムメトリクスを追加して Jenkins のジョブ生存期間監視を導入

More than 3 years have passed since last update.

背景

社内の Jenkins サーバで回しているテストが最近不調で、よく途中で止まってしまうので監視の導入を決意。
(もちろんテストが止まってしまう根本原因の解決が優先ですが、少々時間のかかる問題なので)

  • しかし Datadog の Jenkins Integration では「ビルドが完了したジョブ」の duration は取れても「ビルド中のジョブが何分生き残ってるか」は取れなさそうだった
  • テスト自体に時間がかかることもあるのでタイムアウトを設定はできない
  • ビルド開始後一定時間経ってもジョブが終了していなければ確認のための通知を出す

という対処を実施
なお、Jenkins サーバは Datadog インストール済み&インテグレーション設定済み

やったこと

前準備

Datadog のカスタムメトリクスでも作ってジョブの生存時間確認してアラート出せばいいかなーと思ったら、python がデフォの 2.6.6。
pyenv 入れようと思ったら色々足りない。

というわけで時々思い出したかのようにやるセットアップ

$ sudo yum groupinstall "Development Tools"`
$ sudo yum install zlib zlib-devel
$ sudo yum install openssl openssl-devel
$ git clone git://github.com/yyuu/pyenv.git ~/.pyenv

.bash_profile あたりに↓追記して $ source ~/.bash_profile しておく。

export PYENV_ROOT="${HOME}/.pyenv"
if [ -d "${PYENV_ROOT}" ]; then
    export PATH=${PYENV_ROOT}/bin:$PATH
    eval "$(pyenv init -)"
fi

あとは pyenv から python インストールして pip install

$ sudo pyenv install 2.7.12
$ sudo pip install datadog

準備完了

カスタムメトリクスの送信

以下のようなスクリプトを作成

custom_metrics.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from datadog import statsd
import time
import datetime as dt
import jenkins


PRJ_NAME = "Enter Your Project Name on Jenkins"

def get_building_jobs():
    server = jenkins.Jenkins("http://localhost:8080")
    builds = server.get_job_info(PRJ_NAME,depth=1)["builds"]

    return [x for x in builds if x['building'] == True]

def get_lifetime(timestamp=""):
    # return minutes
    now = int(dt.datetime.now().strftime('%s'))
    return (now - (timestamp / 1000)) / 60


while True:
    for job in get_building_jobs():
        statsd.gauge("jenkins.job.lifetime", get_lifetime(timestamp=job["timestamp"]))
    time.sleep(10)

ちょろっと自分の備忘録メモがてら解説

def get_building_jobs():
    server = jenkins.Jenkins("http://localhost:8080")
    builds = server.get_job_info(PRJ_NAME,depth=1)["builds"]

    return [x for x in builds if x['building'] == True]

ここでは get_job_info で得られたジョブの中から "builds"(ビルド履歴)を引いて、 latSuccess やら lastFailure やらを除外した後、ステータス building が True のもののみを取得して返しています。
これで 現在実行中のジョブ を取得できます。

def get_lifetime(timestamp=""):
    # return minutes
    now = int(dt.datetime.now().strftime('%s'))
    return (now - (timestamp / 1000)) / 60

これは単純に、各ジョブの持っている timestamp(ジョブ開始時刻の UNIX タイムスタンプ)を元に、生存期間を分に直して返しています。
Jenkins の timestamp はミリ秒まで入ってて面倒なので雑に timestamp / 1000 とかやってます。
良い子は真似してはいけない感じの雑さですね。

while True:
    for job in get_building_jobs():
        statsd.gauge("jenkins.job.lifetime", get_lifetime(timestamp=job["timestamp"]))
    time.sleep(10)

そして後はひたすら「実行中のジョブの生存期間(分)」を jenkins.job.lifetime という名前で Datadog に送り続けています。

$ python ./custom_metrics.py &

とか雑にバックグラウンド実行して放置です。
ちゃんとやるならデーモンとして起動させるとかプロセスにも監視入れるとかしたほうがいいと思います。

あとはこの jenkins.job.lifetime をモニタリング・アラートを作成すれば「いつの間にか止まっている」という状況を防ぐことができます。

それにしても、Datadog 便利ですねぇ。

nekojarashi
クラウドストレージ、クラウドバックアップサービスを提供しています。
https://www.nekojarashi.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away