このマイクロサービスでhttps://github.com/dcdh/inner-friends-user-profile-picture私は opentelemetry を実装しようとしています。
ただし、スパンの 1 つが欠落しているため、E2ETest は失敗しています。掘った後、私は彼を見つけましたが、彼は親に執着していません.
孤立したスパン「HazelcastUserProfilePictureCacheRepository.store」は、2 つのスパンを持つ 2 番目のトレースにある必要があります。
失敗するコードの例
このマイクロサービスは、ヘキサゴナル アーキテクチャを使用して設計しました。ドメインは Mutiny を使用して Async 方式で設計します。インフラストラクチャに関してquarkus-smallrye-context-propagationは、コンテキストを伝播するために使用します。オープンテレメトリに関しては、プログラムで新しいスパンを作成するOpenTelemetryTracingServiceので、ここに親コンテキストを挿入する必要があるかもしれません。ただし、それを行う方法についてはまったくわかりません(スパンビルダーでアタッチするためにそれを取得する適切な方法は何ですか)。
エントリポイントが入っている保存機能についてSaveUserProfilePictureUseCase
@Override
public Uni<R> execute(final SaveUserProfilePictureCommand command,
final ResponseTransformer<R> responseTransformer) {
return Uni.createFrom()
.deferred(() -> profilePictureRepository.save(command.userPseudo(), command.picture(), command.mediaType()))
.chain(profilePictureSaved -> userProfilePictureCacheRepository.storeFeatured(command.userPseudo(), profilePictureSaved)
.onItemOrFailure().transform((item, exception) -> profilePictureSaved))
.map(profilePictureSaved -> responseTransformer.toResponse(profilePictureSaved))
.onFailure(ProfilePictureRepositoryException.class)
.recoverWithItem(profilePictureRepositoryException -> responseTransformer.toResponse((ProfilePictureRepositoryException) profilePictureRepositoryException))
.onFailure()
.recoverWithItem(exception -> responseTransformer.toResponse(exception));
}
インフラストラクチャで s3 ストレージを呼び出します
@Override
public Uni<ProfilePictureSaved> save(final UserPseudo userPseudo,
final byte[] picture,
final SupportedMediaType mediaType) throws ProfilePictureRepositoryException {
return Uni.createFrom()
.deferred(() -> {
final Span span = openTelemetryTracingService.startANewSpan("S3ProfilePictureRepository.save");
final PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(bucketUserProfilePictureName)
.key(s3ObjectKeyProvider.objectKey(userPseudo, mediaType).value())
.contentType(mediaType.contentType())
.build();
return Uni.createFrom()
.completionStage(() -> s3AsyncClient.putObject(putObjectRequest, AsyncRequestBody.fromBytes(picture)))
.map(putObjectResponse -> new S3ProfilePictureSaved(userPseudo, mediaType, putObjectResponse))
.onFailure(SdkException.class)
.transform(exception -> {
LOG.error(exception);
openTelemetryTracingService.markSpanInError(span);
return new ProfilePictureRepositoryException();
})
.onTermination()
.invoke(() -> openTelemetryTracingService.endSpan(span));
});
}
hazelcast キャッシュ リポジトリを呼び出している
@Override
public Uni<CachedUserProfilePicture> storeFeatured(final UserPseudo userPseudo, final ProfilePictureIdentifier featured) {
return Uni.createFrom()
.deferred(() -> {
final Span span = openTelemetryTracingService.startANewSpan("HazelcastUserProfilePictureCacheRepository.store");
return Uni.createFrom()
.completionStage(() -> hazelcastInstance.getMap(MAP_NAME).getAsync(userPseudo.pseudo()))
.replaceIfNullWith(() -> HazelcastCachedUserProfilePicture.newBuilder().setUserPseudo(userPseudo.pseudo()).build())
.onItem().castTo(HazelcastCachedUserProfilePicture.class)
.chain(hazelcastCachedUserProfilePicture -> {
hazelcastCachedUserProfilePicture.setFeaturedProfilePictureIdentifier(new HazelcastProfilePictureIdentifier(featured));
return Uni.createFrom().completionStage(() -> hazelcastInstance.getMap(MAP_NAME).putAsync(userPseudo.pseudo(), hazelcastCachedUserProfilePicture))
.map(response -> hazelcastCachedUserProfilePicture);
})
.onItem().castTo(HazelcastCachedUserProfilePicture.class)
.onTermination()
.invoke(() -> openTelemetryTracingService.endSpan(span));
});
}
どちらもopenTelemtryTracingServiceスパンのライフサイクルを管理するために を呼び出します。
再現する手順
- コードをチェックアウトする
should_store_user_profile_pictureE2ETest で実行
SaveUserProfilePictureUseCaseUni をチェーンするときにコンテキストが失われているはずだと思います。
この実装の何が問題なのか教えてください。
事前に感謝します。
よろしく、
ダミアン
