Couchbase Server Java SDK解説：分散トランザクション〜ログとトレース

##  はじめに

Couchbase Serverの分散トランザクションライブラリーにおける、ログとトレースについて、解説します。

## ログ

トラブルシューティングを支援するために、各トランザクションはログエントリのリストを維持します。そして、次のようにエラー発生時にログに記録できます。

同期APIの場合：

```JAVA
} catch (TransactionCommitAmbiguous e) {
    // The application will of course want to use its own logging rather
    // than System.err
    System.err.println("Transaction possibly committed");

    for (LogDefer err : e.result().log().logs()) {
        System.err.println(err.toString());
    }
} catch (TransactionFailed e) {
    System.err.println("Transaction did not reach commit point");

    for (LogDefer err : e.result().log().logs()) {
        System.err.println(err.toString());
    }
}
```

非同期APIの場合：

```JAVA
}).doOnError(err -> {
    if (err instanceof TransactionCommitAmbiguous) {
        System.err.println("Transaction possibly committed: ");
    } else {
        System.err.println("Transaction failed: ");
    }

    for (LogDefer err : ((TransactionFailed) e).result().log().logs()) {
        // System.err is used for example, log failures to your own logging system
        System.err.println(err.toString());
    }
});
```

失敗したトランザクションには数十行、場合によっては数百行のログが含まれる可能性があります。そのため、アプリケーションは失敗したトランザクションを通常のエラーログとは別のファイルに書き込むことが望ましい場合があります。

便宜上、トランザクション関連のログを、他のエラーログと同じ扱いとする構成オプションもあります。この場合、失敗したトランザクションのすべてのログが次のように`WARN`レベルでログに記録されます。

```JAVA
.logOnFailure(true, Event.Severity.WARN)
```

Couchbase Server Java SDKのデフォルトでは、ロギングイベントバスは、クラスパスでSLF4J / logback、log4j1、およびlog4j2を検索して使用し、`java.util.Logging`にフォールバックするように設定されています。

詳細については、[Java SDK loggingドキュメント](https://docs.couchbase.com/java-sdk/current/howtos/collecting-information-and-logging.html)を参照してください。

`java.util.Logging`を使用した例を示します

```JAVA
final Logger LOGGER = Logger.getLogger("transactions");

try {
    TransactionResult result = transactions.run((ctx) -> {
        // ... transactional code here ...
    });
} catch (TransactionCommitAmbiguous err) {
    // The transaction may or may not have reached commit point
    LOGGER.info("Transaction returned TransactionCommitAmbiguous and" + " may have succeeded, logs:");
    err.result().log().logs().forEach(log -> LOGGER.info(log.toString()));
} catch (TransactionFailed err) {
    // The transaction definitely did not reach commit point
    LOGGER.info("Transaction failed with TransactionFailed, logs:");
    err.result().log().logs().forEach(log -> LOGGER.info(log.toString()));
}
```

## トレース
テレメトリは、パフォーマンスの監視に特に役立ちます。

CouchbaseJava SDKがトレース用に構成されている場合、トランザクションを監視するために、それ以上の作業は必要ありません。トランザクションスパンが自動的に出力されます。これを構成する方法については、[Couchbase Java SDK Request Tracing ドキュメンテーション](https://docs.couchbase.com/java-sdk/current/howtos/observability-tracing.html)を参照してください。

### 親スパン(Parent Span)
トランザクションスパンを使用/出力するには上記で十分ですが、アプリケーションは、トランザクションがより大きなスパンの一部であることを示したい場合があります（たとえば、ユーザー要求）。これは、親スパンとして渡すことで実行できます。

既存のOpenTelemetryスパンがある場合は、それをCouchbase　Serverの`RequestSpan`に簡単に変換して、トランザクションライブラリーに渡すことができます。

```JAVA
Span span = Span.current(); // this is a span created by your code earlier
RequestSpan wrapped = OpenTelemetryRequestSpan.wrap(span);

transactions.run((ctx) -> {
    // your transaction
}, PerTransactionConfigBuilder.create().parentSpan(wrapped).build());
```