java.util.loggingの出力の扱いをどうするか

java.util.loggingのログが出力されてStackdriver上でERRORログ扱いになってしまう(結果、ERRORレベルのログの中で重要度の高いログが埋もれてしまう)ことに対処したいと思っている。 今回のケースだと下記のライブラリが該当する。

GitHub - GoogleCloudPlatform/cloud-sql-jdbc-socket-factory

接続するだけで、

INFO: Connecting to Cloud SQL instance [xxxxxx:asia-northeast1:xxxxx] on IP [35.190.xxx.xx].

というようなログをERRORレベルで吐いてしまう。

LogManager.getLogManager.reset()

とすれば出なくなる。しかし全く出ないのもまずので、試行錯誤している。

下記のように実装してみた。

  val globalLogger = Logger.getLogger("com.google.cloud.sql.mysql.SocketFactory")
  globalLogger.setUseParentHandlers(false)
  globalLogger.getHandlers.foreach(h => {
    globalLogger.removeHandler(h)
    h.close()
  })
  globalLogger.addHandler(new StreamHandler(System.out, new CustomFormatter))

これを入れればでなくなるが、これを実行するタイミングが難しい。

CustomFormatterは下記のように実装している。

class CustomFormatter extends Formatter {
    override def format(record: LogRecord): String =
      s"""{
         |  "severity": "${record.getLevel}",
         |  "messsage": "(${record.getLoggerName}) ${formatMessage(record)}"
         |}
         |""".stripMargin.replace("\n", "") + CoreConstants.LINE_SEPARATOR
  }

試行錯誤続く。

次はこのあたりを試してみる。

アプリへのslf4j + logback 導入時の java.util.logging 向け対処 - Qiita

ExecutionContextを自分で作る場合

stackoverflow.com

とりあえず雑に

 val es: ExecutorService = Executors.newFixedThreadPool(1000)
 implicit val executionContext: ExecutionContext = ExecutionContext.fromExecutorService(es)

とやってみたが、どれだけスレッド数使うのか計測しないと分からない。

 val es: ExecutorService =  Executors.newCachedThreadPool()
 implicit val executionContext: ExecutionContext = ExecutionContext.fromExecutorService(es)

とりあえずこれでスレッドをどう使ってるか見てみる。

"Class JavaLaunchHelper is implemented in both..."の警告メッセージは1.8.0_152で修正された

MacIntellijJavaを実行すると出てきてた警告メッセージ。

f:id:road288:20171116220525p:plain

  objc[8427]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_141.jdk/Contents/Home/bin/java (0x109de34c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_141.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10a7264e0). One of the two will be used. Which one is undefined.

問題ないメッセージなのだけど、赤い字をなるべく出したくないのでできれば消したかった。 バグらしく、これまで副作用なくこのメッセージを出さなくする方法がわからなかったのだけど、Java1.8.0_152のバージョンでこのバグが修正された。

bugs.java.com

stackoverflow.com

f:id:road288:20171116220805p:plain

めでたく出なくなってスッキリ。

「網羅的テストが可能な擬似コード」?

codezine.jp

読んでもよくわからない。ただ、いまの自分の課題感に近い話題だということは分かる。テストコードを書いても、テストできている部分がごく一部である実感だから、テストを書いても安心できない。

後でもう一度読むとともに、関連することを調べてみる。

Djangoでシンプルなヘルスチェックをつける

ロードバランサの疎通をさせるために、ヘルスチェックのURLパスを作ってそこで200を返す必要があるとき。

www.reddit.com

すごくシンプルな方法があった。

  • urls.py
urlpatterns = [
    url(r"^", lambda r: HttpResponse()),
    (略)
]

ビューはコールバック関数。 これで/へのアクセスに対して200を返してくれる。

cloud_sql_proxyのsidecar containerを立てる

GCPのCloud SQLへのつなぎ方にはいくつか方法があるが、Kubernetes内にあるpodから接続するにはアプリのコンテナと同一pod内にcloud_sql_proxyのコンテナを立ててつなぐ方法で設定した。

github.com

基本的にはここにあるテンプレートどおりやっていけば問題ないが、GCP上で実行する前提だと、いくつかの設定は不要。

      containers:
      (アプリのコンテナの設定)
      - name: cloudsql-proxy
        image: gcr.io/cloudsql-docker/gce-proxy:1.09
        imagePullPolicy: Always
        ports:
        - containerPort: 3306
        command:
        - /cloud_sql_proxy
        - -dir=/cloudsql
        - -instances=foo:asia-northeast1:bar=tcp:0.0.0.0:3306
        volumeMounts:
        - mountPath: /cloudsql
          name: cloudsql
      volumes:
      - name: cloudsql
        emptyDir:

これでいける。インスタンスを設定する部分の foo:asia-northeast1:bar の部分は、

gcloud sql instances describe [インスタンスID]

で取得できる。 あとはアプリ側からは、127.0.0.1:3306向けに接続するだけでOK。

getClass.getCanonicalNameはNullになることもある

@ trait FooFilter { val filterName: String }
defined trait FooFilter

@ val a = new FooFilter{ override val filterName = this.getClass.getCanonicalName }
a: AnyRef with FooFilter = ammonite.$sess.cmd1$$anon$1@3d904e9c

@ a.filterName
res2: String = null

よく考えると当たり前だけど、traitをnewしたものに対してはnullになっちゃう。

@ class BarFilter extends FooFilter { override val filterName = this.getClass.getCanonicalName }
defined class BarFilter

@ new BarFilter().filterName
res4: String = "ammonite.$sess.cmd3.BarFilter"

これならもちろん値ある。