【PHP】Log出力 in GKE

GKEでログ出力をしようとしてはまったのでメモを残しておく。
なお、標準出力ではなく、ログエクスプローラでの閲覧を前提としています。

# 構成
k8s on gke
nginx → php(php7.4.3)

# 実装
## 前段階：Monologで標準出力
*こちらの方法は問題がありましたので前段階とします。

```php
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;

// --- 省略

        $logger = new Logger($name);
        $formatter = new LineFormatter(null, null, true, true);

        $sh = new StreamHandler('php://stdout', Logger::DEBUG);
        $sh->setFormatter($formatter);
        $logger->pushHandler($sh);

        $sh = new StreamHandler('php://stderr', Logger::ERROR);
        $sh->setFormatter($formatter);
        $logger->pushHandler($sh);

        $logger->debug('なんか内容');

// --- 省略

```

こちらの方法では、ログ出力はできたものの、すべてのログが `severity:ERROR` になってしまった。本来infoのログもERRORででるので、もはや訳が分からない状態。

```json
{
textPayload: "なんか内容"
insertId: "省略"
resource: {
type: "k8s_container"
labels: {6}
  # pod名とか入ってる
}
timestamp: "省略"
severity: "ERROR"
labels: {3}
logName: "projects/${PROJECT_id}/logs/stderr"
receiveTimestamp: "省略"
}
```

## 標準ライブラリ使用
上記の方法では適切に表示ができなかったので調べたところ、ログのformatをがっちがちに設定するか、標準ライブラリを使えとのこと。
今回は後者の方法でやってみることとした。

```php
use Google\Cloud\Logging\LoggingClient;
use Google\Cloud\Logging\PsrLogger;

// --- 省略
  $name = 'test';
  $logger = LoggingClient::psrBatchLogger($name);
  
  $logger->info('なんか内容'); 
// --- 省略
```

なんやこれ、くっそかんたんやんけ、と思ったのものの、ロギングに出ない。
ちなみにログエクスプローラ上では以下のクエリで検索をかけていた。

```
resource.type="k8s_container"
resource.labels.namespace_name="namespace_name"
resource.labels.cluster_name="cluster_name"
resource.labels.container_name="container_name"
```

よくよく調べてみたところ、psrBatchLoggerは名前だけ指定すると、`resource.type="global"`
に設定されるようだった。

https://stackoverflow.com/questions/45022651/logging-using-stackdriver-api-on-kubernetes-google-container-engine-gke/45085569#45085569

クラウドコンソール上で以下のコマンドを試すと目的のログがいた。
```sh
gcloud beta logging logs list

--- 省略
projects/${PROJECT_ID}/logs/test
--- 省略
```

`gcloud beta logging read projects/<PROJECT>/logs/<LOG_NAME>` 
こちらで内容を確認すると

```json
insertId: "省略"  
 jsonPayload: {…}  # 内容入ってる
 logName: "projects/${PROJECT_ID}/logs/test"  
 receiveTimestamp: "省略"  
 resource: {
  labels: {
   project_id: ${PROJECT_ID}    
  }
  type: "global"   
 }
 severity: "INFO"  
 timestamp: 省略  
}
```
severity:INFOになっているものの、typeがglobalなのはちょといただけない。

## 設定をきちんとしてみる
```php
use Google\Cloud\Logging\LoggingClient;
use Google\Cloud\Logging\PsrLogger;

// --- 省略
        $logger = LoggingClient::psrBatchLogger(
            $name,
            [
                'resource' => [
                    'type' => 'k8s_container',
                    'labels' => [
                        'project_id' => ${PROJECT_ID},
                        'cluster_name' => ${CLUSTER_NAME},
                        'container_name' => ${CONTAINER_NAME},
                        'namespace_name' => ${NAMESPACE_NAME}
                    ]
                ]
            ]
        );

        $logger->info('なんか内容');
// ---省略
```

こちらの設定方法でログエクスプローラに以下のクエリを指定したところ
```
resource.type="k8s_container"
resource.labels.namespace_name="namespace_name"
resource.labels.cluster_name="cluster_name"
resource.labels.container_name="container_name"
```

以下のログが出力できた。

```json
{
insertId: "省略"
jsonPayload: {
message: "なんか内容"
}
resource: {
type: "k8s_container"
labels: {
namespace_name: "namespace_name"
container_name: "conteainer_name"
project_id: "${PROJECT_ID}"
pod_name: ""
location: ""
cluster_name: "cluster_name"
}
}
timestamp: "省略"
severity: "INFO"
logName: "projects/${PROJECT_ID}/logs/name"
receiveTimestamp: "省略"
}
```

と狙い通りに出力することができた。

*標準出力に出していた際には、pod_nameやlocationなども自動で入力されていたが、今回は不要と判断し、設定していない。
*logNameに `/` をもちいて階層化を狙ったが、そうすると全く出力されなくなってしまった
。 `.` で区切るのが今のところベターと思われる。