diff --git a/CHANGELOG.md b/CHANGELOG.md index 7603b319d0..910d15b4a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ release. ## Unreleased +* Add cartServiceFailure feature flag triggering Cart Service errors + ([#824](https://github.com/open-telemetry/opentelemetry-demo/pull/824)) * [paymentservice] update JS SDKs to 1.12.0/0.38.0 ([#853](https://github.com/open-telemetry/opentelemetry-demo/pull/853)) * [frontend] update JS SDKs to 1.12.0/0.38.0 diff --git a/docker-compose.yml b/docker-compose.yml index 70bc4bc182..f06380dad6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -91,6 +91,7 @@ services: - "${CART_SERVICE_PORT}" environment: - CART_SERVICE_PORT + - FEATURE_FLAG_GRPC_SERVICE_ADDR - REDIS_ADDR - OTEL_EXPORTER_OTLP_ENDPOINT - OTEL_RESOURCE_ATTRIBUTES diff --git a/src/cartservice/src/Program.cs b/src/cartservice/src/Program.cs index 58b4221e34..cf4b57138b 100644 --- a/src/cartservice/src/Program.cs +++ b/src/cartservice/src/Program.cs @@ -3,6 +3,7 @@ using System; using cartservice.cartstore; +using cartservice.featureflags; using cartservice.services; using Microsoft.AspNetCore.Builder; @@ -30,6 +31,7 @@ Console.WriteLine("Initialization completed"); builder.Services.AddSingleton(cartStore); +builder.Services.AddSingleton(); // see https://opentelemetry.io/docs/instrumentation/net/getting-started/ diff --git a/src/cartservice/src/featureflags/FeatureFlagHelper.cs b/src/cartservice/src/featureflags/FeatureFlagHelper.cs new file mode 100644 index 0000000000..6fe6fe147a --- /dev/null +++ b/src/cartservice/src/featureflags/FeatureFlagHelper.cs @@ -0,0 +1,32 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +using System; +using System.Threading.Tasks; +using Oteldemo; + +namespace cartservice.featureflags; + +public class FeatureFlagHelper +{ + private readonly static Random Random = new Random(); + private readonly FeatureFlagService.FeatureFlagServiceClient _featureFlagServiceClient; + + public FeatureFlagHelper() + { + var featureFlagServiceUri = new Uri($"http://{Environment.GetEnvironmentVariable("FEATURE_FLAG_GRPC_SERVICE_ADDR")}"); + var channel = Grpc.Net.Client.GrpcChannel.ForAddress(featureFlagServiceUri); + _featureFlagServiceClient = new FeatureFlagService.FeatureFlagServiceClient(channel); + } + + public async Task GenerateCartError() + { + if (Random.Next(10) != 1) + { + return false; + } + + var getFlagRequest = new GetFlagRequest { Name = "cartServiceFailure" }; + var getFlagResponse = await _featureFlagServiceClient.GetFlagAsync(getFlagRequest); + return getFlagResponse.Flag.Enabled; + } +} diff --git a/src/cartservice/src/services/CartService.cs b/src/cartservice/src/services/CartService.cs index 9d8d11b1eb..26ee0390b3 100644 --- a/src/cartservice/src/services/CartService.cs +++ b/src/cartservice/src/services/CartService.cs @@ -3,7 +3,9 @@ using System.Diagnostics; using System.Threading.Tasks; using Grpc.Core; +using OpenTelemetry.Trace; using cartservice.cartstore; +using cartservice.featureflags; using Oteldemo; namespace cartservice.services @@ -11,11 +13,14 @@ namespace cartservice.services public class CartService : Oteldemo.CartService.CartServiceBase { private readonly static Empty Empty = new Empty(); + private readonly static ICartStore BadCartStore = new RedisCartStore("badhost:1234"); private readonly ICartStore _cartStore; + private readonly FeatureFlagHelper _featureFlagHelper; - public CartService(ICartStore cartStore) + public CartService(ICartStore cartStore, FeatureFlagHelper featureFlagService) { _cartStore = cartStore; + _featureFlagHelper = featureFlagService; } public async override Task AddItem(AddItemRequest request, ServerCallContext context) @@ -52,7 +57,24 @@ public async override Task EmptyCart(EmptyCartRequest request, ServerCall activity?.SetTag("app.user.id", request.UserId); activity?.AddEvent(new("Empty cart")); - await _cartStore.EmptyCartAsync(request.UserId); + try + { + if (await _featureFlagHelper.GenerateCartError()) + { + await BadCartStore.EmptyCartAsync(request.UserId); + } + else + { + await _cartStore.EmptyCartAsync(request.UserId); + } + } + catch (RpcException ex) + { + Activity.Current?.RecordException(ex); + Activity.Current?.SetStatus(ActivityStatusCode.Error, ex.Message); + throw; + } + return Empty; } } diff --git a/src/featureflagservice/priv/repo/migrations/20220524172636_create_featureflags.exs b/src/featureflagservice/priv/repo/migrations/20220524172636_create_featureflags.exs index f251cad0fe..a33df54743 100644 --- a/src/featureflagservice/priv/repo/migrations/20220524172636_create_featureflags.exs +++ b/src/featureflagservice/priv/repo/migrations/20220524172636_create_featureflags.exs @@ -32,11 +32,17 @@ defmodule Featureflagservice.Repo.Migrations.CreateFeatureflags do name: "adServiceFailure", description: "Fail ad service requests sporadically", enabled: false}) + + repo().insert(%Featureflagservice.FeatureFlags.FeatureFlag{ + name: "cartServiceFailure", + description: "Fail cart service requests sporadically", + enabled: false}) end defp execute_down do repo().delete(%Featureflagservice.FeatureFlags.FeatureFlag{name: "productCatalogFailure"}) repo().delete(%Featureflagservice.FeatureFlags.FeatureFlag{name: "recommendationCache"}) repo().delete(%Featureflagservice.FeatureFlags.FeatureFlag{name: "adServiceFailure"}) + repo().delete(%Featureflagservice.FeatureFlags.FeatureFlag{name: "cartServiceFailure"}) end end