log の Writer を Discard してみる

golang のログ難しい・・・

golang.org

特定のログレベルが指定されたときだけログ出力を有効化できるようになっているといいんじゃないかと思った。 ほんとはもっと自由に設定できるようになって欲しいけど。

とりあえずの実装はこんな感じ。 環境変数 LOG_LEVELdebug が指定されたら出力する、それ以外では出さない。

io.Writer な変数( ioutil.Discard から推論されてるはず) に *os.Fileos.Stdout を代入できるのは (*File) Write があるからだと思う。 プロジェクト固有の実装でこういうのがあったら辛いなぁ。

package main

import (
    "io/ioutil"
    "log"
    "os"
)

var logger *log.Logger

func init() {
    writer := ioutil.Discard
    if os.Getenv("LOG_LEVEL") == "debug" {
        writer = os.Stdout
    }
    logger = log.New(writer, "[main] ", log.LstdFlags)
}

func Log() {
    logger.Println("aaabbbccc")
}

ログ出力が無効な状態で性能落ちてもいやなので、簡単にベンチマーク

package main

import (
    "testing"
)

func BenchmarkLog(b *testing.B) {
    for n := 0; n < b.N; n++ {
        Log()
    }
}

これを環境変数指定して2回実行。

go test -bench=. > discard_bench.txt
LOG_LEVEL=debug go test -bench=. > stdout_bench.txt

そうすると次のような感じになった。 ざっくり 14 倍のオーバーヘッド (5169/361 = 14.3)。 プロジェクトの都合で使ってるロギングライブラリがあるときはダメだけど、そうでなければなんか利用できそう。

実行方法 繰り返し回数 呼び出しあたりの時間
無効化 5,000,000 361 ns/op
有効化 200,000 5169 ns/op

コンテナで実行した jvm からはリソースがどう見えているか

特にCPUコア数がどう見えてるのか気になったので。

環境

コンポーネント バージョン
OS Windows 10 Professional 10.0.17763
仮想環境 Hyper-V
minikube v1.15.0
java OpenJDK 11

こういうノードで試した。

kubectl get node/minikube -o yaml | yq read - status.capacity
cpu: "4"
ephemeral-storage: 44529848Ki
hugepages-2Mi: "0"
memory: 8154628Ki
pods: "110"

単純に jshell で次のコードを実行しただけ。

System.out.println(Runtime.getRuntime().availableProcessors());
System.out.println(Runtime.getRuntime().maxMemory() / 1024 / 1024);

まとめ

limits.cpu を四捨五入した値になるみたい。

limits.cpu availableProcessors()
なし 1
500m 以下 jshell がタイムアウトする
500m 1
1000m 1
1500m 2
2000m 2
2500m 3
3000m リソース不足でコンテナが起動せず

Git for Windows で pacman を使う

背景

Git for Windows には MSYS2bash が同梱されています。

Windows での開発に必要なソフトウェアはほとんど scoop で導入できるのであまり困ることはありません。 しかし、tree のように MSYS2 なら提供されてる けど Git for Windows には同梱されていないちょっとしたツールもあります。 重ねて、MSYS2 の提供するパッケージを導入するための pacman も Git for Windows では省略されています。

ソリューション

  1. Git for Windows の開発環境 Git for Windows SDK を導入する
  2. Git for Windows SDK から pacman に関連するファイルだけを取り出す

1. Git for Windows の開発環境 Git for Windows SDK を導入する

リポジトリを取得してあれこれすれば使えそうな雰囲気です。

2. Git for Windows SDK から pacman に関連するファイルだけを取り出す

わりと無理矢理感はありますが、こんな感じで今のところ使えています。

git clone --depth=1 https://github.com/git-for-windows/git-sdk-64 gfw-sdk

cp gfw-sdk/usr/bin/pacman* /usr/bin/
cp -a gfw-sdk/etc/pacman.* /etc/
mkdir -p /var/lib/
cp -a gfw-sdk/var/lib/pacman /var/lib/
cp -a gfw-sdk/usr/share/makepkg/util* /usr/share/makepkg/

pacman --database --check

curl -L https://raw.githubusercontent.com/git-for-windows/build-extra/master/git-for-windows-keyring/git-for-windows.gpg \
| pacman-key --add - \
&& pacman-key --lsign-key 1A9F3986

pacman -S tree

Git for Windows でシンボリックリンクを使う

本題

はるか4年前からすでに導入されていました。

インストールしただけでは利用できないので、どこかで次の環境変数を設定しましょう。

MSYS=winsymlinks:nativestrict

余談

値の意味を調べてたら Cygwin へたどり着いた。 具体的には 2013 年に導入されていた模様。

Microsoft のリファレンスによると開発者モードを有効化しておく必要があるみたい。

Spring Boot App を Payara Micro へデプロイする

Spring Boot App を Payara Micro にデプロイする方法を確認してみた。

素材として Spring Petclinic を利用する。

結局、spring.io blog の Deploying Spring Boot Applications を参考に Application クラスや pom.xml を編集するだけだった。

executable jar(war) で実行することに対するメリットは思いつかなかった。

Spring Boot App から Eclipse MiroProfileクラスタリングやヘルスチェック、ロードバランシングなどの機能が利用できると便利なんじゃないか、と思ったこともあるけど、そもそもアプリケーションに組み込むべき機能なのかどうか疑問だし、何より Spring と JavaEE(JakartaEE) を混ぜ合わせて使うのは筋悪のような気がします。

動かしてみる手順

Payara のダウンロードページから Payara Micro (jarファイル)を取得して、適当な場所に置いておく。

fork して改変した Spring PetClinic を取得して、ビルドする。

git clone https://github.com/yujiorama/spring-petclinic
cd spring-petclinic
./mvnw clean package
(いろいろなログ出力)
ls -l target/spring-petclinic-2.1.0.BUILD-SNAPSHOT.war
-rw-r--r-- 1 y_okazawa 197609 40995335 6月   1 14:09 target/spring-petclinic-2.1.0.BUILD-SNAPSHOT.war

Payara Micro を実行する。 しばらくするとアプリケーションの初期化が完了して、ブラウザからアクセスできるようになる。

java -Dfile.encoding=UTF-8 \
-jar ~/Downloads/payara-micro-5.192.jar \
--deploy target/spring-petclinic-2.1.0.BUILD-SNAPSHOT.war \
--contextroot spetclinic
2019-06-01 14:10:03.989  INFO 13772 --- [           main] PayaraMicro                              :
{
    "Instance Configuration": {
        "Host": "DEVW1904",
        "Http Port(s)": "8080",
        "Https Port(s)": "",
        "Instance Name": "Kind-Turbot",
        "Instance Group": "MicroShoal",
        "Hazelcast Member UUID": "86c85883-644f-487f-8236-e4b0d0ea3213",
        "Deployed": [
            {
                "Name": "spring-petclinic-2.1.0.BUILD-SNAPSHOT",
                "Type": "war",
                "Context Root": "/spetclinic"
            }
        ]
    }
}
2019-06-01 14:10:04.005  INFO 13772 --- [           main] PayaraMicro                              :
Payara Micro URLs:
http://DEVW1904:8080/spetclinic


2019-06-01 14:10:04.005  INFO 13772 --- [           main] PayaraMicro                              : Payara Micro  5.192 #badassmicrofish (build 115) ready in 44,734 (ms)
2019-06-01 14:10:37.629  INFO 13772 --- [ttp-listener(2)] javax.enterprise.web                     : WebModule[/spetclinic] ServletContext.log():Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-06-01 14:10:37.629  INFO 13772 --- [ttp-listener(2)] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-06-01 14:10:37.644  INFO 13772 --- [ttp-listener(2)] o.s.web.servlet.DispatcherServlet        : Completed initialization in 15 ms

プロジェクトの進捗とプロセスの改善は分けて考えないといけない

参考書籍は Software Development Metrics

もう少し整理したほうがいいんだけどとりあえずメモ。

 

www.manning.com

書籍紹介

著者はウォーターフォールなプロジェクトやアジャイルなプロジェクトのPMやコンサルをやってきた方。

ソフトウェア工学の知識よりも現場での経験が豊富な感じ。

アジャイル(適応型)やウォーターフォール(計画重視)それぞれの手法で、どのようなメトリクスをどのように活用できるのか説明している。

メトリクスを活用する目的として、プロジェクトの状況を予測可能にすること、プロセスを改善することを挙げている。

プロジェクトの状況を予測可能にすることはステークホルダーにとって重要。

プロセスを改善することはチームにとって重要。

目的別にメトリクスの正しい使い方や間違った使い方を紹介している。

書籍で紹介されているメトリクスを計算する Excel シートがサポートサイトで公開されている。

https://www.manning.com/downloads/1565

メトリクスの性質

メトリクス自体には次のような性質がある。基本的には数値化された事実であり、解釈する人によって意味が変わってくる。

  • 情報
    • 善悪・良し悪しと関係ない事実
  • 兆候
    • 問題が発生している(しそうになっている)ことを伝える
  • 動機づけ
    • 人間の行動を変えるきっかけになる

メトリクスの解釈

  • 過去を照らし出す
    • 「計画」と「現在の状態」を比較して得られるメトリクスのこと
    • 「今までの自分たちは間違ってないよね」を大事にする考え方
    • 状況が変化しないことを前提としている
  • 未来に向き合う
    • 「現在の状態」から「達成すべき目標」を比較して得られるメトリクスのこと
    • 「自分たちはどれだけできたのか」を大事にする考え方
    • 常に状況が変化することを前提としている

プロジェクト管理手法vs目的別メトリクス一覧

どのメトリクスも「ビジネス価値を提供できる状態になった」ことを計測しないと意味のある情報にならない。

リリースできない中間成果物(設計書やテスト結果)を計測するのは効果がない。

書籍ではプロジェクト管理手法だけでなく、プロセスモデルや出荷モデルも分類の軸として紹介している。

  • プロセスモデルの分類は次のとおり
    • 線形(最初に固定した要件を段階的に具体化していく)
    • 反復(要件の具体化を繰り返して洗練していく)
    • タイムボックス(反復の期間を固定して、それぞれの期間で出荷できるソフトウェアを開発する)
    • フロー(流れ作業的な)
  • 出荷モデルの分類は次のとおり
    • 開発して提供したら終わり
    • 継続的に保守開発
  計画重視のプロジェクト管理 適応型のプロジェクト管理
プロジェクトの状況を予測可能にする

スコープ達成率

アーンド・バリュー

予算バーンダウン

バッファバーンダウン

ベロシティ

サイクルタイム

バーンアップチャート

バーンダウンチャート

スループット

累積フロー図

スコープ達成率

予算バーンダウン

バッファバーンダウン

テストの完了した機能数

アーンド・ビジネスバリュー

ベロシティ

サイクルタイム

バーンアップチャート

バーンダウンチャート

スループット

累積フロー図

プロセスを改善する

ベロシティ

サイクルタイム

バーンアップチャート

バーンダウンチャート

累積フロー図

プロセスサイクル効率

ソースコードバージョン管理システムの履歴

ソースコードの静的解析の履歴

ニコニコカレンダー

感情振幅図

幸福度

ボール・イン・ボール

健全さと幸福度

パーソナリティチェック

cacerts の中身を精査した

TL;DR

  • Oracle OpenJDK に同梱された cacerts と他のプロバイダの配布物を比較した
  • Zulu 11 は Oracle OpenJDK の cacerts にエントリを追加したように見える
    • fingerprint type が同一
    • エントリ名に [jdk] と付けるルールを揃えてる
  • AdoptOpenJDK および Redhat の OpenJDK は cacerts を作り直しているようだ
    • fingerprint type が異なる

比較結果

配布物 エントリ数 fingerprint type
Oracle OpenJDK 11 93 SHA1
OpenJDK 11 (AdoptOpenJDK) 93 SHA256
OpenJDK 11 (Redhat) 133 SHA256
Zulu 11 158 SHA1

個別の観察

OpenJDK 11 (AdoptOpenJDK)

  • fingerprint type が違う
  • エントリの名前とタイムスタンプは同じ
  • エントリ数は一致

Oracle OpenJDK と同じソースから作り直している、と考えてよさそう。

OpenJDK 11 (Redhat)

  • fingerprint type が違う
  • 同じ名前のエントリでもタイムスタンプが違う
  • Oracle OpenJDK に存在しないエントリが増えてる

完全に作り直している雰囲気。

Zulu 11

  • fingerprint type は同じ
  • Oracle OpenJDK に存在するエントリの名前とタイムスタンプは同じ
  • Oracle OpenJDK に存在しないエントリが増えてる

作り直しているというより、キーストアファイルにエントリを追加しているような雰囲気。

JDK-8191031で削除対象になっている Symantec の証明書が残っていることから、OpenJDK 本体へ追従できてないような気がする。

深入り

cURL の公開している cacerts.pem と比較して存在する(1)存在しない(0)を整理した。

openjdk cacerts