0

このマイクロサービスで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スパンのライフサイクルを管理するために を呼び出します。

再現する手順

  1. コードをチェックアウトする
  2. should_store_user_profile_pictureE2ETest で実行

SaveUserProfilePictureUseCaseUni をチェーンするときにコンテキストが失われているはずだと思います。

この実装の何が問題なのか教えてください。

事前に感謝します。

よろしく、

ダミアン

4

0 に答える 0