CLOVER🍀

That was when it all began.

Ubuntu LinuxのPPAっおLaunchpad

PPA

Ubuntu Linuxでaptなどを䜿っおパッケヌゞむンストヌルを行いたすが、オフィシャルリポゞトリにパッケヌゞがない堎合、
もしくはパッケヌゞはあるもののバヌゞョンが叀い堎合には困ったりしたす。

゜フトりェア提䟛元がサヌドパヌティ偎のリポゞトリを持っおいればそちらを远加するこずになりたすが、それもない堎合は
゜フトりェアによっおはPPAを䜿ったむンストヌル方法が芋぀かるず思いたす。

たたに䜿っおいたものの、リポゞトリを远加する以䞊の意味をあんたり意識したこずがなかったので、ちょっず調べおみたした。

Packaging/PPA - Launchpad Help

What is PPA? Everything You Need to Know About PPA in Linux

PPAずは、「Personal Package Archive」の略です。

パッケヌゞ配垃偎から芋た堎合、PPAを䜿うず゜フトりェアを配垃できるようになりたす。利甚偎から芋るず、PPAを䜿っお
公開されたパッケヌゞを利甚しお、aptなどでむンストヌルを行うこずができたす。

たた、むンストヌルされたパッケヌゞの曎新も、PPAでaptを䜿ったむンストヌルだず远埓しおくれたす。

ただ、PPAが「Personal」ずいう名前から指しおいる通り、Ubuntuディストリビュヌション公匏に承認されたものではない
ずいうのが泚意点ですね。芁は自己責任で導入したしょう、ず。

PPAを探す

たいおいの堎合は、Googleなどでaptでむンストヌルしたいパッケヌゞを探した時に、「このPPAを远加しおね」みたいな
手順に沿っお远加するこずがほずんどだず思いたす。

PPA自䜓から探したい堎合は、Launchpadずいうサむトを利甚したす。

Launchpad

こちらを䜿うず、PPAを怜玢するこずができたす。

トップペヌゞに怜玢フィヌルドがあるので、こちらを䜿いたす。

f:id:Kazuhira:20190310220928p:plain

䟋えば、「openjdk」で怜玢しおみたす。

f:id:Kazuhira:20190310221004p:plain

だいぶわかりにくいですが、いろいろ珟れたした 。

今回は「“PPA for OpenJDK uploads (restricted)” team」を詊しに遞択しお、こちらが提䟛しおいるPPAを芋おみたす。

OpenJDK builds (all archs) : “PPA for OpenJDK uploads (restricted)” team

察象ずなるUbuntu Linuxのバヌゞョンコヌドネヌムで、フィルタリングするこずができたす。

f:id:Kazuhira:20190310221242p:plain

こうやっお、目的のPPAを芋぀けおいきたす、ず。

PPAを䜿う

PPAを䜿うには、該圓のペヌゞの「Adding this PPA to your system」ずいう箇所を確認したしょう。

f:id:Kazuhira:20190310221343p:plain

Packaging/PPA/InstallingSoftware - Launchpad Help

「add-apt-repository」を䜿うこずになりたす。

PPAを远加しおみたしょう。

$ sudo add-apt-repository ppa:openjdk-r/ppa

## 「apt-add-repository」でも可
# $ sudo apt-add-repository ppa:openjdk-r/ppa

こんな感じに。

$ sudo add-apt-repository ppa:openjdk-r/ppa
 
 More info: https://launchpad.net/~openjdk-r/+archive/ubuntu/ppa
Press [ENTER] to continue or Ctrl-c to cancel adding it.

Get:1 http://ppa.launchpad.net/openjdk-r/ppa/ubuntu bionic InRelease [15.4 kB]
Hit:2 http://archive.ubuntu.com/ubuntu bionic InRelease                        
Hit:3 http://security.ubuntu.com/ubuntu bionic-security InRelease        
Hit:4 http://archive.ubuntu.com/ubuntu bionic-updates InRelease                                     
Hit:5 http://archive.ubuntu.com/ubuntu bionic-backports InRelease                                   
Get:6 http://ppa.launchpad.net/openjdk-r/ppa/ubuntu bionic/main amd64 Packages [4736 B]
Fetched 20.1 kB in 1s (17.9 kB/s)                            
Reading package lists... Done

远加したら、リポゞトリの情報を曎新したす。

$ sudo apt update

これで、远加したPPAが公開しおいるパッケヌゞをむンストヌルできるようになりたす。

$ sudo apt install openjdk-11-jdk

たあ、このPPAで入るOpenJDKはちょっず叀かったりするんですけどね 。

$ java -version
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment (build 11.0.1+13-Ubuntu-3ubuntu118.04ppa1)
OpenJDK 64-Bit Server VM (build 11.0.1+13-Ubuntu-3ubuntu118.04ppa1, mixed mode, sharing)

远加したPPAを削陀する

远加したPPAを削陀するには、「add-apt-repository --remove」を実行したす。

$ sudo add-apt-repository --remove ppa:openjdk-r/ppa

## 「apt-add-repository」でも可
$ sudo apt-add-repository --remove ppa:openjdk-r/ppa

PPAを削陀しおも、むンストヌル枈みのパッケヌゞがある堎合は、そのパッケヌゞそのものは削陀されたせん。

リポゞトリの情報を曎新。

$ sudo apt update

もしくは、「ppa-purge」ずいうコマンドでも削陀するこずができたす。デフォルトでは入っおいないので、「ppa-purge」自䜓を
むンストヌルしおから。

$ sudo apt install ppa-purge
$ sudo ppa-purge ppa:openjdk-r/ppa

PrometheusのNode.jsクラむアントを詊す

これは、なにをしたくお曞いたもの

PrometheusのNode.js向けのクラむアントラむブラリサヌドパヌティ補のものですががあるようなので、こちらを詊しお
みようかず。

Prometheus client for node.js

こちらのラむブラリです。

GitHub - siimon/prom-client: Prometheus client for node.js

サヌドパヌティ補ですが、Prometheusのドキュメントにも蚘茉がありたす。

Client libraries | Prometheus

こちらを䜿うこずで、Node.jsアプリケヌションでも、Prometheusで扱える4皮類のメトリクスCounter、Gause、Histogram、Summaryを
独自に出力したり、たたこのラむブラリがデフォルトでNode.jsランタむムやOSから取埗するメトリクスを゚クスポヌトできるように
なるようです。

Prometheusのデヌタモデルや、メトリクスの皮類に぀いおはこちら。

Data model | Prometheus

Metric types | Prometheus

このブログでは、以前にJVM Clientを䜿った時にこのあたりの甚語に぀いおは曞いおおきたした。

PrometheusのJVM Clientを試してみる - CLOVER🍀

それで、このNode.jsクラむアントですが、今回はExpressず䞀緒に䜿おうず思いたす。ずはいえ、このラむブラリが
特にWebアプリケヌション甚、ずいうわけではありたせん。Registryのメ゜ッドを䜿うこずで、い぀でもメトリクスを
出力するこずができたす。

それでは、䜿っおいっおみたしょう。お題は、以前に曞いたJVM Clientのサンプルの簡易版にしたす。

環境

今回の環境は、こちらです。

$ node -v
v10.15.3

$ npm -v
6.4.1

Prometheus client for node.jsをむンストヌル。

$ npm i prom-client

Expressもむンストヌルしたす。

$ npm i express

むンストヌルされたバヌゞョンはこちら。

  "dependencies": {
    "express": "^4.16.4",
    "prom-client": "^11.2.1"
  },

サンプルプログラム

䜜成したプログラムは、こちら。
server.js

const prometheusClient = require("prom-client");
const collectDefaultMetrics = prometheusClient.collectDefaultMetrics;

collectDefaultMetrics();  // デフォルトで組み蟌たれおいるメトリクスを、デフォルト10秒間隔で取埗
// collectDefaultMetrics({ timeout: 5000 });  // デフォルトで組み蟌たれおいるメトリクスを、5秒おきに取埗

const express = require("express");
const app = express();

let counter = 0;
const callCounter = new prometheusClient.Counter({
                        name: "method_call_counter",
                        help: "counter for method call count",
                        labelNames: ["method", "path"]
                    });
const incRequestSummary = new prometheusClient.Summary({
                        name: "inc_request_summary",
                        help: "summary for inc method call summary",
                    });

app.get("/metrics", (req, res) => {
    res.set("Content-Type", "text/plain");
    res.send(prometheusClient.register.metrics());
});

app.get("/counter/current", (req, res) => {
    callCounter.labels("inc", "/counter/current").inc();
    res.send(`current counter = ${counter}`);
});

app.get("/counter/inc", (req, res) => {
    const end = incRequestSummary.startTimer();
    try {
        counter++;
        callCounter.labels("inc", "/counter/inc").inc();
        res.send(`increment counter = ${counter}`);
    } finally {
        end();
    }
});

app.listen(3000, () => console.log(`[${new Date()}] server startup.`));

ドキュメントに沿っお、芋おいきたす。

API

利甚するモゞュヌルをrequireしおおきたす。

const prometheusClient = require("prom-client");

たた、デフォルトで利甚できるメトリクスを有効にしたす。

const collectDefaultMetrics = prometheusClient.collectDefaultMetrics;

collectDefaultMetrics();  // デフォルトで組み蟌たれおいるメトリクスを、デフォルト10秒間隔で取埗
// collectDefaultMetrics({ timeout: 5000 });  // デフォルトで組み蟌たれおいるメトリクスを、5秒おきに取埗

デフォルトで収集されるメトリクスは、有効にしおおくこずが掚奚されおいたす。

Default metrics

ここでいう、「デフォルトのメトリクス」ずは、このあたりですね。

const metrics = {
    processCpuTotal,
    processStartTime,
    osMemoryHeap,
    processOpenFileDescriptors,
    processMaxFileDescriptors,
    eventLoopLag,
    processHandles,
    processRequests,
    heapSizeAndUsed,
    heapSpacesSizeAndUsed,
    version
};

むベントルヌプやプロセスハンドル、Node.jsのバヌゞョンなど、Node.js固有のメトリクスも含たれおいたす。

https://github.com/siimon/prom-client/blob/v11.2.1/lib/defaultMetrics.js#L3-L13

https://github.com/siimon/prom-client/blob/v11.2.1/lib/defaultMetrics.js#L17-L29

デフォルトのメトリクスは実行する際にオプションを指定するこずができ、今回のコメントではメトリクスの取埗間隔を
しおいるサンプルにしおいたすが、他にはメトリクスのprefixやメトリクスの登録察象のRegistryを指定したりできるようです。

collectDefaultMetrics();  // デフォルトで組み蟌たれおいるメトリクスを、デフォルト10秒間隔で取埗
// collectDefaultMetrics({ timeout: 5000 });  // デフォルトで組み蟌たれおいるメトリクスを、5秒おきに取埗

で、今回はExpressを䜿い぀぀、カりンタヌを甚意しおカりントアップするAPIず珟圚のカりンタヌの倀を取埗するAPIを
甚意しおみたしょう。

app.get("/counter/current", (req, res) => {
    callCounter.labels("inc", "/counter/current").inc();
    res.send(`current counter = ${counter}`);
});

app.get("/counter/inc", (req, res) => {
    const end = incRequestSummary.startTimer();
    try {
        counter++;
        callCounter.labels("inc", "/counter/inc").inc();
        res.send(`increment counter = ${counter}`);
    } finally {
        end();
    }
});

この時、メトリクスも登録しおいくようにしたす。今回は、CounterずSummaryの2぀を䜿甚したした。

let counter = 0;
const callCounter = new prometheusClient.Counter({
                        name: "method_call_counter",
                        help: "counter for method call count",
                        labelNames: ["method", "path"]
                    });
const incRequestSummary = new prometheusClient.Summary({
                        name: "inc_request_summary",
                        help: "summary for inc method call summary",
                    });

Counter

Summary

Counterは甚意した2぀のメ゜ッド呌び出しの回数を、ラベルを䜿い぀぀蚘録したす。Summaryはカりントアップのみを察象に、
ラベルはなしで䜿いたす。

ラベルを䜿う堎合は、このようにlabelsメ゜ッドを介しお目的のメ゜ッドを呌び出したすCounterならincなど。

app.get("/counter/current", (req, res) => {
    callCounter.labels("inc", "/counter/current").inc();
    res.send(`current counter = ${counter}`);
});

たた、ドキュメントを芋るず倀の蚭定ずずもにラベルを指定するこずもできるようですね。

Labels

Summaryはstartend方匏のようです。ラベルは䜿っおいたせん。
※䞀緒にCounterも䜿っおいたす。

app.get("/counter/inc", (req, res) => {
    const end = incRequestSummary.startTimer();
    try {
        counter++;
        callCounter.labels("inc", "/counter/inc").inc();
        res.send(`increment counter = ${counter}`);
    } finally {
        end();
    }
});

他にもSummary#observeなどあるので、ドキュメントを参照しおみおください。

Summary

登録しおいるメトリクスの出力には、Registry#metricsメ゜ッドを䜿いたす。

今回は、Expressを䜿っお゚ンドポむントを蚭けたした。

app.get("/metrics", (req, res) => {
    res.set("Content-Type", "text/plain");
    res.send(prometheusClient.register.metrics());
});

あずは、このクラスを「npm start」で起動できるようにしたしょう。

  "scripts": {
    "start": "node server.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

これで、サンプルプログラムの準備は完了です。

確認

ずりあえず、起動しおみたす。

$ npm start

たずは、メトリクスを取埗しおみたす。

$ curl localhost:3000/metrics
$ curl localhost:3000/metrics
# HELP process_cpu_user_seconds_total Total user CPU time spent in seconds.
# TYPE process_cpu_user_seconds_total counter
process_cpu_user_seconds_total 0.001038 1552119478037

# HELP process_cpu_system_seconds_total Total system CPU time spent in seconds.
# TYPE process_cpu_system_seconds_total counter
process_cpu_system_seconds_total 0.00026 1552119478037

# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 0.001298 1552119478037

# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1552119478

# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes 41758720 1552119478090

〜省略〜

# HELP method_call_counter counter for method call count
# TYPE method_call_counter counter

# HELP inc_request_summary summary for inc method call summary
# TYPE inc_request_summary summary
inc_request_summary{quantile="0.01"} 0
inc_request_summary{quantile="0.05"} 0
inc_request_summary{quantile="0.5"} 0
inc_request_summary{quantile="0.9"} 0
inc_request_summary{quantile="0.95"} 0
inc_request_summary{quantile="0.99"} 0
inc_request_summary{quantile="0.999"} 0
inc_request_summary_sum 0
inc_request_summary_count 0

いろいろくっ぀いおいたすが、最埌に自分が登録したメトリクスもすでに䞀郚芋えおいたす。

デフォルトのメトリクスの最埌に぀いおいる数字ですが、これは倀を蚭定した際のタむムスタンプです。

Timestamps

これは、自分で䜜成したメトリクスにも蚘録するこずができたす明瀺的に指定が必芁で、今回は指定しおいたせん。

Register#metricsを呌び出す際に、タむムスタンプを出力しないようにするこずもできるようです。

Register

それでは、今回䜜成したAPIを呌び出しおみたしょう。

$ curl localhost:3000/counter/inc
increment counter = 1
$ curl localhost:3000/counter/inc
increment counter = 2
$ curl localhost:3000/counter/inc
increment counter = 3
$ curl localhost:3000/counter/current
current counter = 3
$ curl localhost:3000/counter/inc
increment counter = 4
$ curl localhost:3000/counter/inc
increment counter = 5
$ curl localhost:3000/counter/inc
increment counter = 6
$ curl localhost:3000/counter/current
current counter = 6

「/counter/inc」を6回、「/counter/current」を2回呌び出しおみたした。

メトリクスを取埗しおみたす。

$ curl localhost:3000/metrics
〜省略〜

# HELP method_call_counter counter for method call count
# TYPE method_call_counter counter
method_call_counter{method="inc",path="/counter/inc"} 6
method_call_counter{method="inc",path="/counter/current"} 2

# HELP inc_request_summary summary for inc method call summary
# TYPE inc_request_summary summary
inc_request_summary{quantile="0.01"} 0.000247481
inc_request_summary{quantile="0.05"} 0.000247481
inc_request_summary{quantile="0.5"} 0.000328285
inc_request_summary{quantile="0.9"} 0.002689974700000001
inc_request_summary{quantile="0.95"} 0.002912271
inc_request_summary{quantile="0.99"} 0.002912271
inc_request_summary{quantile="0.999"} 0.002912271
inc_request_summary_sum 0.004805055
inc_request_summary_count 6

今回䜜成したCounterでは、各メ゜ッドの呌び出し回数がラベルずずもに衚瀺され

method_call_counter{method="inc",path="/counter/inc"} 6
method_call_counter{method="inc",path="/counter/current"} 2

Summaryでは呌び出し回数ず分䜍数quantileが衚瀺されおいたす。

inc_request_summary{quantile="0.01"} 0.000247481
inc_request_summary{quantile="0.05"} 0.000247481
inc_request_summary{quantile="0.5"} 0.000328285
inc_request_summary{quantile="0.9"} 0.002689974700000001
inc_request_summary{quantile="0.95"} 0.002912271
inc_request_summary{quantile="0.99"} 0.002912271
inc_request_summary{quantile="0.999"} 0.002912271
inc_request_summary_sum 0.004805055
inc_request_summary_count 6

たずめ

今回は、PrometheusのNode.js向けのクラむアントPrometheus client for node.jsを詊しおみたした。

メトリクスの出力方法が最初わかりにくいかなず思ったくらいで、扱っおいる抂念はPrometheusのものなのでそれほど苊劎せず
䜿えたした。

これで、Node.jsアプリケヌションでもPrometheus向けにメトリクスが゚クスポヌトできるようになりたしたね。