From 439fda6cd72265616686af03f49cc51b0933dd70 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 11:15:19 +0200 Subject: [PATCH 01/60] add Dapr in the cartService --- .env | 4 +- components/cart-state-store.yaml | 14 ++ components/pubsub.yaml | 22 ++ docker-compose.yml | 28 ++- src/cart/src/Program.cs | 11 +- src/cart/src/cart.csproj | 2 + .../cartstore/DaprStateManagementCartStore.cs | 167 +++++++++++++ src/cart/src/cartstore/ValkeyCartStore.cs | 236 ------------------ 8 files changed, 237 insertions(+), 247 deletions(-) create mode 100644 components/cart-state-store.yaml create mode 100644 components/pubsub.yaml create mode 100644 src/cart/src/cartstore/DaprStateManagementCartStore.cs delete mode 100644 src/cart/src/cartstore/ValkeyCartStore.cs diff --git a/.env b/.env index 199e14d2ee..609502c7bb 100644 --- a/.env +++ b/.env @@ -2,7 +2,7 @@ # Demo App version IMAGE_VERSION=2.0.2 -IMAGE_NAME=ghcr.io/open-telemetry/demo +IMAGE_NAME=hrexed/open-telemetry/demo DEMO_VERSION=latest # Build Args @@ -23,7 +23,7 @@ VALKEY_IMAGE=valkey/valkey:8.1-alpine TRACETEST_IMAGE=kubeshop/tracetest:${TRACETEST_IMAGE_VERSION} # Demo Platform -ENV_PLATFORM=local +ENV_PLATFORM=linux/amd64 # OpenTelemetry Collector HOST_FILESYSTEM=/ diff --git a/components/cart-state-store.yaml b/components/cart-state-store.yaml new file mode 100644 index 0000000000..0144510617 --- /dev/null +++ b/components/cart-state-store.yaml @@ -0,0 +1,14 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: cart-state-store +spec: + type: state.redis + version: v1 + metadata: + - name: redisHost + value: valkey-cart:6379 + - name: redisPassword + value: "" + - name: enableTLS + value: false \ No newline at end of file diff --git a/components/pubsub.yaml b/components/pubsub.yaml new file mode 100644 index 0000000000..b49443580f --- /dev/null +++ b/components/pubsub.yaml @@ -0,0 +1,22 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: pubsub +spec: + type: pubsub.kafka + version: v1 + metadata: + - name: brokers # Required. Kafka broker connection setting + value: "kafka:9092" + - name: authType # Required. + value: "none" + - name: disableTls # Optional. Disable TLS. This is not safe for production!! You should read the `Mutual TLS` section for how to use TLS. + value: "false" + - name: publishingScopes + value: "checkout=orders" + - name: subscriptionScopes + value: "accounting=orders;fraud-detection=orders" +scopes: +- accounting +- checkout +- fraud-detection \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 4041652b63..63d5300d8d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -80,6 +80,21 @@ services: condition: service_started logging: *logging + cart-dapr: + image: "daprio/daprd:edge" + container_name: cart-dapr + command: [ "./daprd", + "-app-id", "cart", + "-app-port", "3000", + "-placement-host-address", "dapr-placement:50006", + "-dapr-grpc-port", "50002", + "-dapr-http-port", "3500", + "-resources-path", "/components" ] + volumes: + - "./components/:/components" + depends_on: + - cart + network_mode: "service:cart" # Cart service cart: image: ${IMAGE_NAME}:${DEMO_VERSION}-cart @@ -100,7 +115,8 @@ services: - CART_PORT - FLAGD_HOST - FLAGD_PORT - - VALKEY_ADDR + - DAPR_GRPC_PORT=50002 + - DAPR_HTTP_PORT=3500 - OTEL_EXPORTER_OTLP_ENDPOINT - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=cart @@ -689,7 +705,15 @@ services: - "${VALKEY_PORT}" logging: *logging - + # ******************** + # Dapr Components + # ******************** + dapr-placement: + image: "daprio/dapr" + container_name: dapr-placement + command: [ "./placement", "-port", "50006" ] + ports: + - "50006:50006" # ******************** # Telemetry Components # ******************** diff --git a/src/cart/src/Program.cs b/src/cart/src/Program.cs index 365c7db35c..5a19d6f725 100644 --- a/src/cart/src/Program.cs +++ b/src/cart/src/Program.cs @@ -21,11 +21,7 @@ var builder = WebApplication.CreateBuilder(args); string valkeyAddress = builder.Configuration["VALKEY_ADDR"]; -if (string.IsNullOrEmpty(valkeyAddress)) -{ - Console.WriteLine("VALKEY_ADDR environment variable is required."); - Environment.Exit(1); -} + builder.Logging .AddOpenTelemetry(options => options.AddOtlpExporter()) @@ -33,7 +29,8 @@ builder.Services.AddSingleton(x=> { - var store = new ValkeyCartStore(x.GetRequiredService>(), valkeyAddress); + var store = new DaprStateManagementCartStore(x.GetRequiredService>(), "cart-state-store"); + store.Initialize(); return store; }); @@ -48,7 +45,7 @@ builder.Services.AddSingleton(x => new CartService( x.GetRequiredService(), - new ValkeyCartStore(x.GetRequiredService>(), "badhost:1234"), + new DaprStateManagementCartStore(x.GetRequiredService>(), "bad-state-store"), x.GetRequiredService() )); diff --git a/src/cart/src/cart.csproj b/src/cart/src/cart.csproj index 128b386916..0e5cc7c597 100644 --- a/src/cart/src/cart.csproj +++ b/src/cart/src/cart.csproj @@ -31,6 +31,8 @@ + + diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs new file mode 100644 index 0000000000..81e9b1487a --- /dev/null +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -0,0 +1,167 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +using System; +using System.Linq; +using System.Threading.Tasks; +using Grpc.Core; +using Google.Protobuf; +using Microsoft.Extensions.Logging; +using System.Diagnostics.Metrics; +using System.Diagnostics; +using Dapr.Client; + +namespace cart.cartstore; + +public class DaprStateManagementCartStore : ICartStore +{ + private readonly ILogger _logger; + private readonly string _daprStoreName; + private DaprClient _client; + private readonly byte[] _emptyCartBytes; + private static readonly ActivitySource CartActivitySource = new("OpenTelemetry.Demo.Cart"); + private static readonly Meter CartMeter = new Meter("OpenTelemetry.Demo.Cart"); + private static readonly Histogram addItemHistogram = CartMeter.CreateHistogram( + "app.cart.add_item.latency", + advice: new InstrumentAdvice + { + HistogramBucketBoundaries = [ 500000, 600000, 700000, 800000, 900000, 1000000, 1100000 ] + }); + private static readonly Histogram getCartHistogram = CartMeter.CreateHistogram( + "app.cart.get_cart.latency", + advice: new InstrumentAdvice + { + HistogramBucketBoundaries = [ 300000, 400000, 500000, 600000, 700000, 800000, 900000 ] + }); + + public DaprStateManagementCartStore(ILogger logger, string daprStoreName) + { + _logger = logger; + _daprStoreName = daprStoreName; + // Serialize empty cart into byte array. + var cart = new Oteldemo.Cart(); + _emptyCartBytes = cart.ToByteArray(); + } + + public void Initialize() + { + if (_client is null) + _client = new DaprClientBuilder().Build(); + } + + public async Task AddItemAsync(string userId, string productId, int quantity) + { + var stopwatch = Stopwatch.StartNew(); + _logger.LogInformation("AddItemAsync called with userId={userId}, productId={productId}, quantity={quantity}", userId, productId, quantity); + + try + { + + var value = await _client.GetStateAsync(_daprStoreName, userId.ToString()); + + Oteldemo.Cart cart; + if (value is null) + { + cart = new Oteldemo.Cart + { + UserId = userId + }; + cart.Items.Add(new Oteldemo.CartItem { ProductId = productId, Quantity = quantity }); + } + else + { + cart = Oteldemo.Cart.Parser.ParseFrom(value); + var existingItem = cart.Items.SingleOrDefault(i => i.ProductId == productId); + if (existingItem == null) + { + cart.Items.Add(new Oteldemo.CartItem { ProductId = productId, Quantity = quantity }); + } + else + { + existingItem.Quantity += quantity; + } + } + await _client.SaveStateAsync(_daprStoreName, userId.ToString(), cart.ToByteArray()); + } + catch (DaprException daprEx) + { + if (daprEx.TryGetExtendedErrorInfo(out DaprExtendedErrorInfo errorInfo)) + { + + _logger.LogInformation("Dapr error: code: {errorInfo.Code} , message: {errorInfo.Message}", errorInfo.Code,errorInfo.Message); + + + foreach (DaprExtendedErrorDetail detail in errorInfo.Details) + { + Console.WriteLine(detail.ErrorType); + + switch (detail.ErrorType) + { + case ExtendedErrorType.ErrorInfo: + _logger.LogInformation("Dapr error: resons : {detail.Reason} , message: {detail.Domain}", detail.Reason,detail.Domain); + + default: + _logger.LogInformation("Dapr error: typeUrl : {detail.TypeUrl} ", detail.TypeUrl); + } + } + throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); + + } + } + catch (Exception ex) + { + throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); + } + finally + { + addItemHistogram.Record(stopwatch.ElapsedTicks); + } + } + + public async Task EmptyCartAsync(string userId) + { + _logger.LogInformation("EmptyCartAsync called with userId={userId}", userId); + + try + { + await _client.SaveStateAsync(_daprStoreName, userId.ToString(), _emptyCartBytes); + } + catch (Exception ex) + { + throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); + } + } + + public async Task GetCartAsync(string userId) + { + var stopwatch = Stopwatch.StartNew(); + _logger.LogInformation("GetCartAsync called with userId={userId}", userId); + + try + { + + // Access the cart from the cache + var value = await _client.GetStateAsync(_daprStoreName, userId.ToString()); + + if (value is not null) + { + return Oteldemo.Cart.Parser.ParseFrom(value); + } + + // We decided to return empty cart in cases when user wasn't in the cache before + return new Oteldemo.Cart(); + } + catch (Exception ex) + { + throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); + } + finally + { + getCartHistogram.Record(stopwatch.ElapsedTicks); + } + } + + public async Task PingAsync() + { + return await _client.CheckOutboundHealthAsync(); + } +} diff --git a/src/cart/src/cartstore/ValkeyCartStore.cs b/src/cart/src/cartstore/ValkeyCartStore.cs deleted file mode 100644 index a486839ee8..0000000000 --- a/src/cart/src/cartstore/ValkeyCartStore.cs +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 -using System; -using System.Linq; -using System.Threading.Tasks; -using Grpc.Core; -using StackExchange.Redis; -using Google.Protobuf; -using Microsoft.Extensions.Logging; -using System.Diagnostics.Metrics; -using System.Diagnostics; - -namespace cart.cartstore; - -public class ValkeyCartStore : ICartStore -{ - private readonly ILogger _logger; - private const string CartFieldName = "cart"; - private const int RedisRetryNumber = 30; - - private volatile ConnectionMultiplexer _redis; - private volatile bool _isRedisConnectionOpened; - - private readonly object _locker = new(); - private readonly byte[] _emptyCartBytes; - private readonly string _connectionString; - - private static readonly ActivitySource CartActivitySource = new("OpenTelemetry.Demo.Cart"); - private static readonly Meter CartMeter = new Meter("OpenTelemetry.Demo.Cart"); - private static readonly Histogram addItemHistogram = CartMeter.CreateHistogram( - "app.cart.add_item.latency", - advice: new InstrumentAdvice - { - HistogramBucketBoundaries = [ 500000, 600000, 700000, 800000, 900000, 1000000, 1100000 ] - }); - private static readonly Histogram getCartHistogram = CartMeter.CreateHistogram( - "app.cart.get_cart.latency", - advice: new InstrumentAdvice - { - HistogramBucketBoundaries = [ 300000, 400000, 500000, 600000, 700000, 800000, 900000 ] - }); - private readonly ConfigurationOptions _redisConnectionOptions; - - public ValkeyCartStore(ILogger logger, string valkeyAddress) - { - _logger = logger; - // Serialize empty cart into byte array. - var cart = new Oteldemo.Cart(); - _emptyCartBytes = cart.ToByteArray(); - _connectionString = $"{valkeyAddress},ssl=false,allowAdmin=true,abortConnect=false"; - - _redisConnectionOptions = ConfigurationOptions.Parse(_connectionString); - - // Try to reconnect multiple times if the first retry fails. - _redisConnectionOptions.ConnectRetry = RedisRetryNumber; - _redisConnectionOptions.ReconnectRetryPolicy = new ExponentialRetry(1000); - - _redisConnectionOptions.KeepAlive = 180; - } - - public ConnectionMultiplexer GetConnection() - { - EnsureRedisConnected(); - return _redis; - } - - public void Initialize() - { - EnsureRedisConnected(); - } - - private void EnsureRedisConnected() - { - if (_isRedisConnectionOpened) - { - return; - } - - // Connection is closed or failed - open a new one but only at the first thread - lock (_locker) - { - if (_isRedisConnectionOpened) - { - return; - } - - _logger.LogDebug("Connecting to Redis: {_connectionString}", _connectionString); - _redis = ConnectionMultiplexer.Connect(_redisConnectionOptions); - - if (_redis == null || !_redis.IsConnected) - { - _logger.LogError("Wasn't able to connect to redis"); - - // We weren't able to connect to Redis despite some retries with exponential backoff. - throw new ApplicationException("Wasn't able to connect to redis"); - } - - _logger.LogInformation("Successfully connected to Redis"); - var cache = _redis.GetDatabase(); - - _logger.LogDebug("Performing small test"); - cache.StringSet("cart", "OK" ); - object res = cache.StringGet("cart"); - _logger.LogDebug("Small test result: {res}", res); - - _redis.InternalError += (_, e) => { Console.WriteLine(e.Exception); }; - _redis.ConnectionRestored += (_, _) => - { - _isRedisConnectionOpened = true; - _logger.LogInformation("Connection to redis was restored successfully."); - }; - _redis.ConnectionFailed += (_, _) => - { - _logger.LogInformation("Connection failed. Disposing the object"); - _isRedisConnectionOpened = false; - }; - - _isRedisConnectionOpened = true; - } - } - - public async Task AddItemAsync(string userId, string productId, int quantity) - { - var stopwatch = Stopwatch.StartNew(); - _logger.LogInformation("AddItemAsync called with userId={userId}, productId={productId}, quantity={quantity}", userId, productId, quantity); - - try - { - EnsureRedisConnected(); - - var db = _redis.GetDatabase(); - - // Access the cart from the cache - var value = await db.HashGetAsync(userId, CartFieldName); - - Oteldemo.Cart cart; - if (value.IsNull) - { - cart = new Oteldemo.Cart - { - UserId = userId - }; - cart.Items.Add(new Oteldemo.CartItem { ProductId = productId, Quantity = quantity }); - } - else - { - cart = Oteldemo.Cart.Parser.ParseFrom(value); - var existingItem = cart.Items.SingleOrDefault(i => i.ProductId == productId); - if (existingItem == null) - { - cart.Items.Add(new Oteldemo.CartItem { ProductId = productId, Quantity = quantity }); - } - else - { - existingItem.Quantity += quantity; - } - } - - await db.HashSetAsync(userId, new[]{ new HashEntry(CartFieldName, cart.ToByteArray()) }); - await db.KeyExpireAsync(userId, TimeSpan.FromMinutes(60)); - } - catch (Exception ex) - { - throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); - } - finally - { - addItemHistogram.Record(stopwatch.ElapsedTicks); - } - } - - public async Task EmptyCartAsync(string userId) - { - _logger.LogInformation("EmptyCartAsync called with userId={userId}", userId); - - try - { - EnsureRedisConnected(); - var db = _redis.GetDatabase(); - - // Update the cache with empty cart for given user - await db.HashSetAsync(userId, new[] { new HashEntry(CartFieldName, _emptyCartBytes) }); - await db.KeyExpireAsync(userId, TimeSpan.FromMinutes(60)); - } - catch (Exception ex) - { - throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); - } - } - - public async Task GetCartAsync(string userId) - { - var stopwatch = Stopwatch.StartNew(); - _logger.LogInformation("GetCartAsync called with userId={userId}", userId); - - try - { - EnsureRedisConnected(); - - var db = _redis.GetDatabase(); - - // Access the cart from the cache - var value = await db.HashGetAsync(userId, CartFieldName); - - if (!value.IsNull) - { - return Oteldemo.Cart.Parser.ParseFrom(value); - } - - // We decided to return empty cart in cases when user wasn't in the cache before - return new Oteldemo.Cart(); - } - catch (Exception ex) - { - throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); - } - finally - { - getCartHistogram.Record(stopwatch.ElapsedTicks); - } - } - - public bool Ping() - { - try - { - var cache = _redis.GetDatabase(); - var res = cache.Ping(); - return res != TimeSpan.Zero; - } - catch (Exception) - { - return false; - } - } -} From 52d5f14376353d99e8827af2f982f3ea1c2a0da9 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 14:41:50 +0200 Subject: [PATCH 02/60] add Dapr in the cartService --- .../cartstore/DaprStateManagementCartStore.cs | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index 81e9b1487a..b8a24edb07 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -125,6 +125,31 @@ public async Task EmptyCartAsync(string userId) { await _client.SaveStateAsync(_daprStoreName, userId.ToString(), _emptyCartBytes); } + catch (DaprException daprEx) + { + if (daprEx.TryGetExtendedErrorInfo(out DaprExtendedErrorInfo errorInfo)) + { + + _logger.LogInformation("Dapr error: code: {errorInfo.Code} , message: {errorInfo.Message}", errorInfo.Code,errorInfo.Message); + + + foreach (DaprExtendedErrorDetail detail in errorInfo.Details) + { + Console.WriteLine(detail.ErrorType); + + switch (detail.ErrorType) + { + case ExtendedErrorType.ErrorInfo: + _logger.LogInformation("Dapr error: resons : {detail.Reason} , message: {detail.Domain}", detail.Reason,detail.Domain); + + default: + _logger.LogInformation("Dapr error: typeUrl : {detail.TypeUrl} ", detail.TypeUrl); + } + } + throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); + + } + } catch (Exception ex) { throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); @@ -150,6 +175,31 @@ public async Task EmptyCartAsync(string userId) // We decided to return empty cart in cases when user wasn't in the cache before return new Oteldemo.Cart(); } + catch (DaprException daprEx) + { + if (daprEx.TryGetExtendedErrorInfo(out DaprExtendedErrorInfo errorInfo)) + { + + _logger.LogInformation("Dapr error: code: {errorInfo.Code} , message: {errorInfo.Message}", errorInfo.Code,errorInfo.Message); + + + foreach (DaprExtendedErrorDetail detail in errorInfo.Details) + { + Console.WriteLine(detail.ErrorType); + + switch (detail.ErrorType) + { + case ExtendedErrorType.ErrorInfo: + _logger.LogInformation("Dapr error: resons : {detail.Reason} , message: {detail.Domain}", detail.Reason,detail.Domain); + + default: + _logger.LogInformation("Dapr error: typeUrl : {detail.TypeUrl} ", detail.TypeUrl); + } + } + throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); + + } + } catch (Exception ex) { throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); @@ -159,7 +209,19 @@ public async Task EmptyCartAsync(string userId) getCartHistogram.Record(stopwatch.ElapsedTicks); } } + public bool Ping() + { + try + { + var isDaprReady = await client.CheckHealthAsync(); + return isDaprReady; + } + catch (Exception) + { + return false; + } + } public async Task PingAsync() { return await _client.CheckOutboundHealthAsync(); From 41c970be72fa9d633157c57523a72fe257a331c7 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 15:11:21 +0200 Subject: [PATCH 03/60] add Dapr in the cartService --- src/cart/src/Program.cs | 3 +-- src/cart/src/cartstore/DaprStateManagementCartStore.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cart/src/Program.cs b/src/cart/src/Program.cs index 5a19d6f725..aea9e49ff2 100644 --- a/src/cart/src/Program.cs +++ b/src/cart/src/Program.cs @@ -79,8 +79,7 @@ var app = builder.Build(); -var ValkeyCartStore = (ValkeyCartStore) app.Services.GetRequiredService(); -app.Services.GetRequiredService().AddConnection(ValkeyCartStore.GetConnection()); + app.MapGrpcService(); app.MapGrpcHealthChecksService(); diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index b8a24edb07..132ade7fc8 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -9,7 +9,7 @@ using System.Diagnostics.Metrics; using System.Diagnostics; using Dapr.Client; - +using Dapr.Common.Exceptions namespace cart.cartstore; public class DaprStateManagementCartStore : ICartStore From e68a2e00b58a216097c3dbd4abf51fc1a6e8e279 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 15:13:44 +0200 Subject: [PATCH 04/60] add Dapr in the cartService --- src/cart/src/cartstore/DaprStateManagementCartStore.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index 132ade7fc8..063736cba4 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -9,7 +9,8 @@ using System.Diagnostics.Metrics; using System.Diagnostics; using Dapr.Client; -using Dapr.Common.Exceptions +using Dapr.Common.Exceptions; + namespace cart.cartstore; public class DaprStateManagementCartStore : ICartStore From c0bf516a78bcc81944a2f10cf657f0947b2572d0 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 15:21:07 +0200 Subject: [PATCH 05/60] add Dapr in the cartService --- src/cart/src/cartstore/DaprStateManagementCartStore.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index 063736cba4..415c54e029 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -9,7 +9,7 @@ using System.Diagnostics.Metrics; using System.Diagnostics; using Dapr.Client; -using Dapr.Common.Exceptions; +using Dapr.Common.Exceptions.DaprException; namespace cart.cartstore; @@ -104,7 +104,7 @@ public async Task AddItemAsync(string userId, string productId, int quantity) _logger.LogInformation("Dapr error: typeUrl : {detail.TypeUrl} ", detail.TypeUrl); } } - throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); + throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {daprEx}")); } } @@ -147,7 +147,7 @@ public async Task EmptyCartAsync(string userId) _logger.LogInformation("Dapr error: typeUrl : {detail.TypeUrl} ", detail.TypeUrl); } } - throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); + throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {daprExv}")); } } @@ -197,7 +197,7 @@ public async Task EmptyCartAsync(string userId) _logger.LogInformation("Dapr error: typeUrl : {detail.TypeUrl} ", detail.TypeUrl); } } - throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}")); + throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {daprEx}")); } } From ae54b15144b4cbed026cca1a35511c4fb0072343 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 15:26:49 +0200 Subject: [PATCH 06/60] add Dapr in the cartService --- src/cart/src/cartstore/DaprStateManagementCartStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index 415c54e029..e4c4215b21 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -9,7 +9,7 @@ using System.Diagnostics.Metrics; using System.Diagnostics; using Dapr.Client; -using Dapr.Common.Exceptions.DaprException; +using Dapr.Common.Exceptions; namespace cart.cartstore; From 163a15f8a705a2e83dab86831f5dc57f4fc4e376 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 15:32:24 +0200 Subject: [PATCH 07/60] add Dapr in the cartService --- src/cart/src/cartstore/DaprStateManagementCartStore.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index e4c4215b21..430c0c2b99 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -10,6 +10,7 @@ using System.Diagnostics; using Dapr.Client; using Dapr.Common.Exceptions; +using Dapr.DaprException; namespace cart.cartstore; From 0fda7069cf51aee68e684776612f5bd67605d22c Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 17:09:41 +0200 Subject: [PATCH 08/60] add Dapr in the cartService --- src/cart/src/cartstore/DaprStateManagementCartStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index 430c0c2b99..fa3b959268 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -10,7 +10,7 @@ using System.Diagnostics; using Dapr.Client; using Dapr.Common.Exceptions; -using Dapr.DaprException; +using Dapr; namespace cart.cartstore; From 7d433e1756fdb5c5648c5e723ed4ed0420656cf4 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 17:23:01 +0200 Subject: [PATCH 09/60] add Dapr in the cartService --- src/cart/src/cartstore/DaprStateManagementCartStore.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index fa3b959268..5b86c20a3b 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -98,7 +98,7 @@ public async Task AddItemAsync(string userId, string productId, int quantity) switch (detail.ErrorType) { - case ExtendedErrorType.ErrorInfo: + case DaprExtendedErrorType.ErrorInfo: _logger.LogInformation("Dapr error: resons : {detail.Reason} , message: {detail.Domain}", detail.Reason,detail.Domain); default: @@ -141,7 +141,7 @@ public async Task EmptyCartAsync(string userId) switch (detail.ErrorType) { - case ExtendedErrorType.ErrorInfo: + case DaprExtendedErrorType.ErrorInfo: _logger.LogInformation("Dapr error: resons : {detail.Reason} , message: {detail.Domain}", detail.Reason,detail.Domain); default: @@ -191,7 +191,7 @@ public async Task EmptyCartAsync(string userId) switch (detail.ErrorType) { - case ExtendedErrorType.ErrorInfo: + case DaprExtendedErrorType.ErrorInfo: _logger.LogInformation("Dapr error: resons : {detail.Reason} , message: {detail.Domain}", detail.Reason,detail.Domain); default: From ea0bbdcd6f344253751e38aec9a8025db51b8b4c Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 17:36:47 +0200 Subject: [PATCH 10/60] add Dapr in the cartService --- src/cart/src/cartstore/DaprStateManagementCartStore.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index 5b86c20a3b..182fb2aafc 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -98,7 +98,7 @@ public async Task AddItemAsync(string userId, string productId, int quantity) switch (detail.ErrorType) { - case DaprExtendedErrorType.ErrorInfo: + case DaprExtendedErrorConstants.ErrorInfo: _logger.LogInformation("Dapr error: resons : {detail.Reason} , message: {detail.Domain}", detail.Reason,detail.Domain); default: @@ -141,7 +141,7 @@ public async Task EmptyCartAsync(string userId) switch (detail.ErrorType) { - case DaprExtendedErrorType.ErrorInfo: + case DaprExtendedErrorConstants.ErrorInfo: _logger.LogInformation("Dapr error: resons : {detail.Reason} , message: {detail.Domain}", detail.Reason,detail.Domain); default: @@ -191,7 +191,7 @@ public async Task EmptyCartAsync(string userId) switch (detail.ErrorType) { - case DaprExtendedErrorType.ErrorInfo: + case DaprExtendedErrorConstants.ErrorInfo: _logger.LogInformation("Dapr error: resons : {detail.Reason} , message: {detail.Domain}", detail.Reason,detail.Domain); default: From ebcdfaf69dd7a835dd5b1e09961fdd269a230e99 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 17:40:46 +0200 Subject: [PATCH 11/60] add Dapr in the cartService --- .../cartstore/DaprStateManagementCartStore.cs | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index 182fb2aafc..6e37fc97e6 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -92,19 +92,7 @@ public async Task AddItemAsync(string userId, string productId, int quantity) _logger.LogInformation("Dapr error: code: {errorInfo.Code} , message: {errorInfo.Message}", errorInfo.Code,errorInfo.Message); - foreach (DaprExtendedErrorDetail detail in errorInfo.Details) - { - Console.WriteLine(detail.ErrorType); - - switch (detail.ErrorType) - { - case DaprExtendedErrorConstants.ErrorInfo: - _logger.LogInformation("Dapr error: resons : {detail.Reason} , message: {detail.Domain}", detail.Reason,detail.Domain); - default: - _logger.LogInformation("Dapr error: typeUrl : {detail.TypeUrl} ", detail.TypeUrl); - } - } throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {daprEx}")); } @@ -135,19 +123,7 @@ public async Task EmptyCartAsync(string userId) _logger.LogInformation("Dapr error: code: {errorInfo.Code} , message: {errorInfo.Message}", errorInfo.Code,errorInfo.Message); - foreach (DaprExtendedErrorDetail detail in errorInfo.Details) - { - Console.WriteLine(detail.ErrorType); - - switch (detail.ErrorType) - { - case DaprExtendedErrorConstants.ErrorInfo: - _logger.LogInformation("Dapr error: resons : {detail.Reason} , message: {detail.Domain}", detail.Reason,detail.Domain); - default: - _logger.LogInformation("Dapr error: typeUrl : {detail.TypeUrl} ", detail.TypeUrl); - } - } throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {daprExv}")); } @@ -185,19 +161,6 @@ public async Task EmptyCartAsync(string userId) _logger.LogInformation("Dapr error: code: {errorInfo.Code} , message: {errorInfo.Message}", errorInfo.Code,errorInfo.Message); - foreach (DaprExtendedErrorDetail detail in errorInfo.Details) - { - Console.WriteLine(detail.ErrorType); - - switch (detail.ErrorType) - { - case DaprExtendedErrorConstants.ErrorInfo: - _logger.LogInformation("Dapr error: resons : {detail.Reason} , message: {detail.Domain}", detail.Reason,detail.Domain); - - default: - _logger.LogInformation("Dapr error: typeUrl : {detail.TypeUrl} ", detail.TypeUrl); - } - } throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {daprEx}")); } From 29aca733bed73eed662700828bea28c30b54e632 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 17:47:05 +0200 Subject: [PATCH 12/60] add Dapr in the cartService --- src/cart/src/cartstore/DaprStateManagementCartStore.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index 6e37fc97e6..6c488ef414 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -124,7 +124,7 @@ public async Task EmptyCartAsync(string userId) - throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {daprExv}")); + throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {daprEx}")); } } @@ -174,7 +174,7 @@ public async Task EmptyCartAsync(string userId) getCartHistogram.Record(stopwatch.ElapsedTicks); } } - public bool Ping() + public async Task Ping() { try { From c94fea43b2659197f09ec55368aeec54c46f5075 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 17:49:46 +0200 Subject: [PATCH 13/60] add Dapr in the cartService --- src/cart/src/cartstore/ICartStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cart/src/cartstore/ICartStore.cs b/src/cart/src/cartstore/ICartStore.cs index 80e249e5d6..fd05b38a68 100644 --- a/src/cart/src/cartstore/ICartStore.cs +++ b/src/cart/src/cartstore/ICartStore.cs @@ -13,5 +13,5 @@ public interface ICartStore Task GetCartAsync(string userId); - bool Ping(); + Task PingAsync(); } From 0aa0c51e444dd616a572d78710d7e62baa27f3d6 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 17:53:35 +0200 Subject: [PATCH 14/60] add Dapr in the cartService --- Makefile | 10 +- kubernetes/opentelemetry-demo.yaml | 5 + src/accounting/Accounting.csproj | 2 + src/accounting/Program.cs | 2 + .../cartstore/DaprStateManagementCartStore.cs | 2 +- src/checkout/go.mod | 2 + src/checkout/kafka/producer.go | 43 --- src/checkout/main.go | 101 ++---- src/fraud-detection/build.gradle.kts | 1 + .../src/main/kotlin/frauddetection/main.kt | 6 +- .../utils/telemetry/FrontendTracer.ts | 2 + src/loadgenerator/locustfile_load.py | 295 ++++++++++++++++++ src/product-catalog/main.go | 2 + src/sqllite/Dockerfile | 14 + src/sqllite/product/init.sql | 7 + 15 files changed, 369 insertions(+), 125 deletions(-) delete mode 100644 src/checkout/kafka/producer.go create mode 100644 src/loadgenerator/locustfile_load.py create mode 100644 src/sqllite/Dockerfile create mode 100644 src/sqllite/product/init.sql diff --git a/Makefile b/Makefile index 96ce7efdf0..54a6a4ae8e 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ TOOLS_DIR := ./internal/tools MISSPELL_BINARY=bin/misspell MISSPELL = $(TOOLS_DIR)/$(MISSPELL_BINARY) -DOCKER_COMPOSE_CMD ?= docker compose +DOCKER_COMPOSE_CMD ?= docker-compose DOCKER_COMPOSE_ENV=--env-file .env --env-file .env.override DOCKER_COMPOSE_BUILD_ARGS= @@ -103,12 +103,12 @@ build-and-push: # Create multiplatform builder for buildx .PHONY: create-multiplatform-builder create-multiplatform-builder: - docker buildx create --name otel-demo-builder --bootstrap --use --driver docker-container --config ./buildkitd.toml + docker-buildx create --name otel-demo-builder --bootstrap --use --driver docker-container --config ./buildkitd.toml # Remove multiplatform builder for buildx .PHONY: remove-multiplatform-builder remove-multiplatform-builder: - docker buildx rm otel-demo-builder + docker-buildx rm otel-demo-builder # Build and push multiplatform images (linux/amd64, linux/arm64) using buildx. # Requires docker with buildx enabled and a multi-platform capable builder in use. @@ -116,12 +116,12 @@ remove-multiplatform-builder: .PHONY: build-multiplatform build-multiplatform: # Because buildx bake does not support --env-file yet, we need to load it into the environment first. - set -a; . ./.env.override; set +a && docker buildx bake -f docker-compose.yml --load --set "*.platform=linux/amd64,linux/arm64" + set -a; . ./.env.override; set +a && docker-buildx bake -f docker-compose.yml --load --set "*.platform=linux/amd64,linux/arm64" .PHONY: build-multiplatform-and-push build-multiplatform-and-push: # Because buildx bake does not support --env-file yet, we need to load it into the environment first. - set -a; . ./.env.override; set +a && docker buildx bake -f docker-compose.yml --push --set "*.platform=linux/amd64,linux/arm64" + set -a; . ./.env.override; set +a && docker-buildx bake -f docker-compose.yml --push --set "*.platform=linux/amd64,linux/arm64" .PHONY: clean-images clean-images: diff --git a/kubernetes/opentelemetry-demo.yaml b/kubernetes/opentelemetry-demo.yaml index 3159432588..6523f5e21b 100644 --- a/kubernetes/opentelemetry-demo.yaml +++ b/kubernetes/opentelemetry-demo.yaml @@ -11437,6 +11437,11 @@ spec: app.kubernetes.io/instance: opentelemetry-demo app.kubernetes.io/component: cart app.kubernetes.io/name: cart + annotations: + dapr.io/enabled: "true" + dapr.io/app-id: "cart" + dapr.io/app-port: "8080" + dapr.io/config: "cart-state-store" spec: serviceAccountName: opentelemetry-demo containers: diff --git a/src/accounting/Accounting.csproj b/src/accounting/Accounting.csproj index 092d737fe6..2c128152f6 100644 --- a/src/accounting/Accounting.csproj +++ b/src/accounting/Accounting.csproj @@ -18,6 +18,8 @@ + + diff --git a/src/accounting/Program.cs b/src/accounting/Program.cs index 54a5c44657..135fcde281 100644 --- a/src/accounting/Program.cs +++ b/src/accounting/Program.cs @@ -4,6 +4,8 @@ using Accounting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Dapr; +using Dapr.Client; Console.WriteLine("Accounting service started"); diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index 6c488ef414..d26aa5bb82 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -178,7 +178,7 @@ public async Task Ping() { try { - var isDaprReady = await client.CheckHealthAsync(); + var isDaprReady = await _client.CheckHealthAsync(); return isDaprReady; } diff --git a/src/checkout/go.mod b/src/checkout/go.mod index 38e7e6f731..81eff70249 100644 --- a/src/checkout/go.mod +++ b/src/checkout/go.mod @@ -6,6 +6,7 @@ toolchain go1.22.9 require ( github.com/IBM/sarama v1.45.1 + github.com/dapr/go-sdk v1.15.0 github.com/google/uuid v1.6.0 github.com/open-feature/go-sdk v1.14.1 github.com/open-feature/go-sdk-contrib/hooks/open-telemetry v0.3.4 @@ -32,6 +33,7 @@ require ( connectrpc.com/connect v1.18.1 // indirect connectrpc.com/otelconnect v0.7.1 // indirect github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect + github.com/dapr/dapr v1.14.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/diegoholiveira/jsonlogic/v3 v3.7.4 // indirect diff --git a/src/checkout/kafka/producer.go b/src/checkout/kafka/producer.go deleted file mode 100644 index 1304f1b976..0000000000 --- a/src/checkout/kafka/producer.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 -package kafka - -import ( - "github.com/IBM/sarama" - "github.com/sirupsen/logrus" -) - -var ( - Topic = "orders" - ProtocolVersion = sarama.V3_0_0_0 -) - -func CreateKafkaProducer(brokers []string, log *logrus.Logger) (sarama.AsyncProducer, error) { - sarama.Logger = log - - saramaConfig := sarama.NewConfig() - saramaConfig.Producer.Return.Successes = true - saramaConfig.Producer.Return.Errors = true - - // Sarama has an issue in a single broker kafka if the kafka broker is restarted. - // This setting is to prevent that issue from manifesting itself, but may swallow failed messages. - saramaConfig.Producer.RequiredAcks = sarama.NoResponse - - saramaConfig.Version = ProtocolVersion - - // So we can know the partition and offset of messages. - saramaConfig.Producer.Return.Successes = true - - producer, err := sarama.NewAsyncProducer(brokers, saramaConfig) - if err != nil { - return nil, err - } - - // We will log to STDOUT if we're not able to produce messages. - go func() { - for err := range producer.Errors() { - log.Errorf("Failed to write message: %+v", err) - } - }() - return producer, nil -} diff --git a/src/checkout/main.go b/src/checkout/main.go index c9d40c7f06..d17c175a2b 100644 --- a/src/checkout/main.go +++ b/src/checkout/main.go @@ -18,7 +18,9 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.24.0" "go.opentelemetry.io/otel/trace" - "github.com/IBM/sarama" + dapr "github.com/dapr/go-sdk/client" + + "github.com/google/uuid" otelhooks "github.com/open-feature/go-sdk-contrib/hooks/open-telemetry/pkg" flagd "github.com/open-feature/go-sdk-contrib/providers/flagd/pkg" @@ -43,7 +45,6 @@ import ( "google.golang.org/protobuf/proto" pb "github.com/open-telemetry/opentelemetry-demo/src/checkout/genproto/oteldemo" - "github.com/open-telemetry/opentelemetry-demo/src/checkout/kafka" "github.com/open-telemetry/opentelemetry-demo/src/checkout/money" ) @@ -126,9 +127,8 @@ type checkout struct { shippingSvcAddr string emailSvcAddr string paymentSvcAddr string - kafkaBrokerSvcAddr string pb.UnimplementedCheckoutServiceServer - KafkaProducerClient sarama.AsyncProducer + daprClient dapr.Client shippingSvcClient pb.ShippingServiceClient productCatalogSvcClient pb.ProductCatalogServiceClient cartSvcClient pb.CartServiceClient @@ -197,14 +197,13 @@ func main() { svc.paymentSvcClient = pb.NewPaymentServiceClient(c) defer c.Close() - svc.kafkaBrokerSvcAddr = os.Getenv("KAFKA_ADDR") - if svc.kafkaBrokerSvcAddr != "" { - svc.KafkaProducerClient, err = kafka.CreateKafkaProducer([]string{svc.kafkaBrokerSvcAddr}, log) - if err != nil { - log.Fatal(err) - } - } + svc.daprClient, err = dapr.NewClient() + //#TODO! add error handling dapr + if err != nil { + log.Fatal(err) + } + log.Infof("service config: %+v", svc) @@ -316,11 +315,9 @@ func (cs *checkout) PlaceOrder(ctx context.Context, req *pb.PlaceOrderRequest) ( log.Infof("order confirmation email sent to %q", req.Email) } - // send to kafka only if kafka broker address is set - if cs.kafkaBrokerSvcAddr != "" { - log.Infof("sending to postProcessor") - cs.sendToPostProcessor(ctx, orderResult) - } + + cs.sendToPostProcessor(ctx, orderResult) + //#TODO! add errorhandling resp := &pb.PlaceOrderResponse{Order: orderResult} return resp, nil @@ -496,78 +493,34 @@ func (cs *checkout) sendToPostProcessor(ctx context.Context, result *pb.OrderRes return } - msg := sarama.ProducerMessage{ - Topic: kafka.Topic, - Value: sarama.ByteEncoder(message), - } + var opts = []dapr.PublishEventOption{ + dapr.PublishEventWithContentType("application/octet-stream"), + } + + if err := cs.daprClient.PublishEvent(ctx, PUBSUB_NAME, TOPIC_NAME, message, opts...); err != nil { + panic(err) + //TODO# add error handling + } // Inject tracing info into message span := createProducerSpan(ctx, &msg) defer span.End() - // Send message and handle response - startTime := time.Now() - select { - case cs.KafkaProducerClient.Input() <- &msg: - log.Infof("Message sent to Kafka: %v", msg) - select { - case successMsg := <-cs.KafkaProducerClient.Successes(): - span.SetAttributes( - attribute.Bool("messaging.kafka.producer.success", true), - attribute.Int("messaging.kafka.producer.duration_ms", int(time.Since(startTime).Milliseconds())), - attribute.KeyValue(semconv.MessagingKafkaMessageOffset(int(successMsg.Offset))), - ) - log.Infof("Successful to write message. offset: %v, duration: %v", successMsg.Offset, time.Since(startTime)) - case errMsg := <-cs.KafkaProducerClient.Errors(): - span.SetAttributes( - attribute.Bool("messaging.kafka.producer.success", false), - attribute.Int("messaging.kafka.producer.duration_ms", int(time.Since(startTime).Milliseconds())), - ) - span.SetStatus(otelcodes.Error, errMsg.Err.Error()) - log.Errorf("Failed to write message: %v", errMsg.Err) - case <-ctx.Done(): - span.SetAttributes( - attribute.Bool("messaging.kafka.producer.success", false), - attribute.Int("messaging.kafka.producer.duration_ms", int(time.Since(startTime).Milliseconds())), - ) - span.SetStatus(otelcodes.Error, "Context cancelled: "+ctx.Err().Error()) - log.Warnf("Context canceled before success message received: %v", ctx.Err()) - } - case <-ctx.Done(): - span.SetAttributes( - attribute.Bool("messaging.kafka.producer.success", false), - attribute.Int("messaging.kafka.producer.duration_ms", int(time.Since(startTime).Milliseconds())), - ) - span.SetStatus(otelcodes.Error, "Failed to send: "+ctx.Err().Error()) - log.Errorf("Failed to send message to Kafka within context deadline: %v", ctx.Err()) - return - } - ffValue := cs.getIntFeatureFlag(ctx, "kafkaQueueProblems") - if ffValue > 0 { - log.Infof("Warning: FeatureFlag 'kafkaQueueProblems' is activated, overloading queue now.") - for i := 0; i < ffValue; i++ { - go func(i int) { - cs.KafkaProducerClient.Input() <- &msg - _ = <-cs.KafkaProducerClient.Successes() - }(i) - } - log.Infof("Done with #%d messages for overload simulation.", ffValue) - } } -func createProducerSpan(ctx context.Context, msg *sarama.ProducerMessage) trace.Span { +func createProducerSpan(ctx context.Context, topic string) trace.Span { spanContext, span := tracer.Start( ctx, - fmt.Sprintf("%s publish", msg.Topic), + fmt.Sprintf("%s publish", topic), trace.WithSpanKind(trace.SpanKindProducer), trace.WithAttributes( semconv.PeerService("kafka"), semconv.NetworkTransportTCP, semconv.MessagingSystemKafka, - semconv.MessagingDestinationName(msg.Topic), + semconv.MessagingDestinationName(topic), semconv.MessagingOperationPublish, - semconv.MessagingKafkaDestinationPartition(int(msg.Partition)), + ), ) @@ -575,9 +528,7 @@ func createProducerSpan(ctx context.Context, msg *sarama.ProducerMessage) trace. propagator := otel.GetTextMapPropagator() propagator.Inject(spanContext, carrier) - for key, value := range carrier { - msg.Headers = append(msg.Headers, sarama.RecordHeader{Key: []byte(key), Value: []byte(value)}) - } + return span } diff --git a/src/fraud-detection/build.gradle.kts b/src/fraud-detection/build.gradle.kts index 2ce809ddbc..c37d6cd514 100644 --- a/src/fraud-detection/build.gradle.kts +++ b/src/fraud-detection/build.gradle.kts @@ -31,6 +31,7 @@ dependencies { testImplementation(kotlin("test")) implementation(kotlin("script-runtime")) implementation("org.apache.kafka:kafka-clients:3.9.0") + implementation("com.google.api.grpc:proto-google-common-protos:2.53.0") implementation("io.grpc:grpc-protobuf:${grpcVersion}") implementation("io.grpc:grpc-stub:${grpcVersion}") diff --git a/src/fraud-detection/src/main/kotlin/frauddetection/main.kt b/src/fraud-detection/src/main/kotlin/frauddetection/main.kt index bcb480ae77..c4cf975ccf 100644 --- a/src/fraud-detection/src/main/kotlin/frauddetection/main.kt +++ b/src/fraud-detection/src/main/kotlin/frauddetection/main.kt @@ -9,6 +9,7 @@ import org.apache.kafka.clients.consumer.ConsumerConfig.* import org.apache.kafka.clients.consumer.KafkaConsumer import org.apache.kafka.common.serialization.ByteArrayDeserializer import org.apache.kafka.common.serialization.StringDeserializer + import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.Logger import oteldemo.Demo.* @@ -39,6 +40,9 @@ fun main() { props[KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java.name props[VALUE_DESERIALIZER_CLASS_CONFIG] = ByteArrayDeserializer::class.java.name props[GROUP_ID_CONFIG] = groupID + + ///---- + //#TODO add dapr consumer val bootstrapServers = System.getenv("KAFKA_ADDR") if (bootstrapServers == null) { println("KAFKA_ADDR is not supplied") @@ -68,7 +72,7 @@ fun main() { } } } - +///----- /** * Retrieves the status of a feature flag from the Feature Flag service. * diff --git a/src/frontend/utils/telemetry/FrontendTracer.ts b/src/frontend/utils/telemetry/FrontendTracer.ts index 8f4de75455..1de1d2fc54 100644 --- a/src/frontend/utils/telemetry/FrontendTracer.ts +++ b/src/frontend/utils/telemetry/FrontendTracer.ts @@ -42,6 +42,8 @@ const FrontendTracer = async () => { ], }); + provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter())); + const contextManager = new ZoneContextManager(); provider.register({ diff --git a/src/loadgenerator/locustfile_load.py b/src/loadgenerator/locustfile_load.py new file mode 100644 index 0000000000..926d42529c --- /dev/null +++ b/src/loadgenerator/locustfile_load.py @@ -0,0 +1,295 @@ +#!/usr/bin/python +# +# Copyright 2018 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import random +import uuid +import os +from locust import HttpUser, task, between +from locust import LoadTestShape + +from opentelemetry import context, baggage, trace +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import (BatchSpanProcessor) +from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter +from opentelemetry.instrumentation.requests import RequestsInstrumentor +from opentelemetry.instrumentation.urllib3 import URLLib3Instrumentor + +tracer_provider = TracerProvider() +trace.set_tracer_provider(tracer_provider) +tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter())) + +# Instrumenting manually to avoid error with locust gevent monkey +RequestsInstrumentor().instrument() +URLLib3Instrumentor().instrument() + +products = [ + "0PUK6V6EV0", + "1YMWWN1N4O", + "2ZYFJ3GM2N", + "66VCHSJNUP", + "6E92ZMYYFZ", + "9SIQT8TOJO", + "L9ECAV7KIM", + "LS4PSXUNUM", + "OLJCESPC7Z" +] +HOST = os.getenv('ENV_HOST') +people = [ + { + "email": "larry_sergei@example.com", + "address": { + "streetAddress": "1600 Amphitheatre Parkway", + "zipCode": 94043, + "city": "Mountain View", + "state": "CA", + "country": "United States" + }, + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4432-8015-6152-0454", + "creditCardExpirationMonth": 1, + "creditCardExpirationYear": 2039, + "creditCardCvv": 672 + } + }, + { + "email": "bill@example.com", + "address": { + "streetAddress": "One Microsoft Way", + "zipCode": 98052, + "city": "Redmond", + "state": "WA", + "country": "United States" + }, + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4532-4211-7434-1278", + "creditCardExpirationMonth": 2, + "creditCardExpirationYear": 2039, + "creditCardCvv": 114 + } + }, + { + "email": "steve@example.com", + "address": { + "streetAddress": "One Apple Park Way", + "zipCode": 95014, + "city": "Cupertino", + "state": "CA", + "country": "United States" + }, + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4532-6178-2799-1951", + "creditCardExpirationMonth": 3, + "creditCardExpirationYear": 2039, + "creditCardCvv": 239 + } + }, + { + "email": "mark@example.com", + "address": { + "streetAddress": "1 Hacker Way", + "zipCode": 94025, + "city": "Menlo Park", + "state": "CA", + "country": "United States" + }, + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4539-1103-5661-7083", + "creditCardExpirationMonth": 4, + "creditCardExpirationYear": 2039, + "creditCardCvv": 784 + } + }, + { + "email": "jeff@example.com", + "address": { + "streetAddress": "410 Terry Ave N", + "zipCode": 98109, + "city": "Seattle", + "state": "WA", + "country": "United States" + }, + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4916-0816-6217-7968", + "creditCardExpirationMonth": 5, + "creditCardExpirationYear": 2039, + "creditCardCvv": 397 + } + }, + { + "email": "reed@example.com", + "address": { + "streetAddress": "100 Winchester Circle", + "zipCode": 95032, + "city": "Los Gatos", + "state": "CA", + "country": "United States" + }, + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4929-5431-0337-5647", + "creditCardExpirationMonth": 6, + "creditCardExpirationYear": 2039, + "creditCardCvv": 793 + } + }, + { + "email": "tobias@example.com", + "address": { + "streetAddress": "150 Elgin St", + "zipCode": 214, + "city": "Ottawa", + "state": "ON", + "country": "Canada" + }, + "userCurrency": "CAD", + "creditCard": { + "creditCardNumber": "4763-1844-9699-8031", + "creditCardExpirationMonth": 7, + "creditCardExpirationYear": 2039, + "creditCardCvv": 488 + } + }, + { + "email": "jack@example.com", + "address": { + "streetAddress": "1355 Market St", + "zipCode": 94103, + "city": "San Francisco", + "state": "CA", + "country": "United States" + }, + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4929-6495-8333-3657", + "creditCardExpirationMonth": 8, + "creditCardExpirationYear": 2039, + "creditCardCvv": 159 + } + }, + { + "email": "moore@example.com", + "address": { + "streetAddress": "2200 Mission College Blvd", + "zipCode": 95054, + "city": "Santa Clara", + "state": "CA", + "country": "United States" + }, + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4485-4803-8707-3547", + "creditCardExpirationMonth": 9, + "creditCardExpirationYear": 2039, + "creditCardCvv": 682 + } + } +] + + +class WebsiteUser(HttpUser): + wait_time = between(1, 10) + + @task(1) + def index(self): + self.client.get("/") + + @task(10) + def browse_product(self): + self.client.get("/api/products/" + random.choice(products)) + + @task(3) + def view_cart(self): + self.client.get("/api/cart") + + @task(2) + def add_to_cart(self, user=""): + if user == "": + user = str(uuid.uuid1()) + product = random.choice(products) + self.client.get("/api/products/" + product) + cart_item = { + "item": { + "productId": product, + "quantity": random.choice([1, 2, 3, 4, 5, 10]) + }, + "userId": user + } + self.client.post("/api/cart", json=cart_item,headers={"Host: "+ HOST}) + + @task(1) + def checkout(self): + # checkout call with an item added to cart + user = str(uuid.uuid1()) + self.add_to_cart(user=user) + checkout_person = random.choice(people) + checkout_person["userId"] = user + self.client.post("/api/checkout", json=checkout_person,headers={"Host: "+ HOST}) + + @task(1) + def checkout_multi(self): + # checkout call which adds 2-4 different items to cart before checkout + user = str(uuid.uuid1()) + for i in range(random.choice([2, 3, 4])): + self.add_to_cart(user=user) + checkout_person = random.choice(people) + checkout_person["userId"] = user + self.client.post("/api/checkout", json=checkout_person,headers={"Host: "+ HOST}) + + def on_start(self): + ctx = baggage.set_baggage("synthetic_request", "true") + context.attach(ctx) + self.index() + +class StagesShape(LoadTestShape): + """ + A simply load test shape class that has different user and spawn_rate at + different stages. + Keyword arguments: + stages -- A list of dicts, each representing a stage with the following keys: + duration -- When this many seconds pass the test is advanced to the next stage + users -- Total user count + spawn_rate -- Number of users to start/stop per second + stop -- A boolean that can stop that test at a specific stage + stop_at_end -- Can be set to stop once all stages have run. + """ + + stages = [ + {"duration": 60, "users": 10, "spawn_rate": 10}, + {"duration": 600, "users": 50, "spawn_rate": 10}, + {"duration": 600, "users": 100, "spawn_rate": 10}, + {"duration": 600, "users": 150, "spawn_rate": 10}, + {"duration": 600, "users": 200, "spawn_rate": 10}, + {"duration": 600, "users": 250, "spawn_rate": 10}, + {"duration": 600, "users": 300, "spawn_rate": 10}, + {"duration": 600, "users": 350, "spawn_rate": 10}, + {"duration": 600, "users": 400, "spawn_rate": 10}, + {"duration": 600, "users": 450, "spawn_rate": 10}, + ] + + def tick(self): + run_time = self.get_run_time() + + for stage in self.stages: + if run_time < stage["duration"]: + tick_data = (stage["users"], stage["spawn_rate"]) + return tick_data + + return None \ No newline at end of file diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index fbdfd4718e..c506291da7 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -215,6 +215,8 @@ func loadProductCatalog() { } func readProductFiles() ([]*pb.Product, error) { + /// # todo change the souerce of data + // find all .json files in the products directory entries, err := os.ReadDir("./products") diff --git a/src/sqllite/Dockerfile b/src/sqllite/Dockerfile new file mode 100644 index 0000000000..973216b8de --- /dev/null +++ b/src/sqllite/Dockerfile @@ -0,0 +1,14 @@ +# Use a lightweight base image +FROM alpine:latest + +# Install SQLite +RUN apk --no-cache add sqlite + +# Create a directory to store the database +WORKDIR /db + +# Copy your SQL script into the container +COPY product/init.sql /docker-entrypoint-initdb.d/ + +# Command to run when the container starts +CMD ["sh", "-c", "sqlite3 /db/mydatabase.db < /docker-entrypoint-initdb.d/init.sql && tail -f /dev/null"] \ No newline at end of file diff --git a/src/sqllite/product/init.sql b/src/sqllite/product/init.sql new file mode 100644 index 0000000000..917a97d65a --- /dev/null +++ b/src/sqllite/product/init.sql @@ -0,0 +1,7 @@ +CREATE TABLE [Product] ( + [products] TEXT +); + +INSERT INTO [Product] ([products]) +VALUES +('[{"id":"OLJCESPC7Z","name":"National Park Foundation Explorascope","description":"The National Park Foundation’s (NPF) Explorascope 60AZ is a manual alt-azimuth, refractor telescope perfect for celestial viewing on the go. The NPF Explorascope 60 can view the planets, moon, star clusters and brighter deep sky objects like the Orion Nebula and Andromeda Galaxy.","picture":"NationalParkFoundationExplorascope.jpg","priceUsd":{"currencyCode":"USD","units":101,"nanos":960000000},"categories":["telescopes"]},{"id":"66VCHSJNUP","name":"Starsense Explorer Refractor Telescope","description":"The first telescope that uses your smartphone to analyze the night sky and calculate its position in real time. StarSense Explorer is ideal for beginners thanks to the app’s user-friendly interface and detailed tutorials. It’s like having your own personal tour guide of the night sky","picture":"StarsenseExplorer.jpg","priceUsd":{"currencyCode":"USD","units":349,"nanos":950000000},"categories":["telescopes"]},{"id":"1YMWWN1N4O","name":"Eclipsmart Travel Refractor Telescope","description":"Dedicated white-light solar scope for the observer on the go. The 50mm refracting solar scope uses Solar Safe, ISO compliant, full-aperture glass filter material to ensure the safest view of solar events. The kit comes complete with everything you need, including the dedicated travel solar scope, a Solar Safe finderscope, tripod, a high quality 20mm (18x) Kellner eyepiece and a nylon backpack to carry everything in. This Travel Solar Scope makes it easy to share the Sun as well as partial and total solar eclipses with the whole family and offers much higher magnifications than you would otherwise get using handheld solar viewers or binoculars.","picture":"EclipsmartTravelRefractorTelescope.jpg","priceUsd":{"currencyCode":"USD","units":129,"nanos":950000000},"categories":["telescopes","travel"]},{"id":"L9ECAV7KIM","name":"Lens Cleaning Kit","description":"Wipe away dust, dirt, fingerprints and other particles on your lenses to see clearly with the Lens Cleaning Kit. This cleaning kit works on all glass and optical surfaces, including telescopes, binoculars, spotting scopes, monoculars, microscopes, and even your camera lenses, computer screens, and mobile devices. The kit comes complete with a retractable lens brush to remove dust particles and dirt and two options to clean smudges and fingerprints off of your optics, pre-moistened lens wipes and a bottled lens cleaning fluid with soft cloth.","picture":"LensCleaningKit.jpg","priceUsd":{"currencyCode":"USD","units":21,"nanos":950000000},"categories":["accessories"]},{"id":"2ZYFJ3GM2N","name":"Roof Binoculars","description":"This versatile, all-around binocular is a great choice for the trail, the stadium, the arena, or just about anywhere you want a close-up view of the action without sacrificing brightness or detail. It’s an especially great companion for nature observation and bird watching, with ED glass that helps you spot the subtlest field markings and a close focus of just 6.5 feet.","picture":"RoofBinoculars.jpg","priceUsd":{"currencyCode":"USD","units":209,"nanos":950000000},"categories":["binoculars"]},{"id":"0PUK6V6EV0","name":"Solar System Color Imager","description":"You have your new telescope and have observed Saturn and Jupiter. Now you''re ready to take the next step and start imaging them. But where do you begin? The NexImage 10 Solar System Imager is the perfect solution.","picture":"SolarSystemColorImager.jpg","priceUsd":{"currencyCode":"USD","units":175,"nanos":0},"categories":["accessories","telescopes"]},{"id":"LS4PSXUNUM","name":"Red Flashlight","description":"This 3-in-1 device features a 3-mode red flashlight, a hand warmer, and a portable power bank for recharging your personal electronics on the go. Whether you use it to light the way at an astronomy star party, a night walk, or wildlife research, ThermoTorch 3 Astro Red’s rugged, IPX4-rated design will withstand your everyday activities.","picture":"RedFlashlight.jpg","priceUsd":{"currencyCode":"USD","units":57,"nanos":80000000},"categories":["accessories","flashlights"]},{"id":"9SIQT8TOJO","name":"Optical Tube Assembly","description":"Capturing impressive deep-sky astroimages is easier than ever with Rowe-Ackermann Schmidt Astrograph (RASA) V2, the perfect companion to today’s top DSLR or astronomical CCD cameras. This fast, wide-field f/2.2 system allows for shorter exposure times compared to traditional f/10 astroimaging, without sacrificing resolution. Because shorter sub-exposure times are possible, your equatorial mount won’t need to accurately track over extended periods. The short focal length also lessens equatorial tracking demands. In many cases, autoguiding will not be required.","picture":"OpticalTubeAssembly.jpg","priceUsd":{"currencyCode":"USD","units":3599,"nanos":0},"categories":["accessories","telescopes","assembly"]},{"id":"6E92ZMYYFZ","name":"Solar Filter","description":"Enhance your viewing experience with EclipSmart Solar Filter for 8” telescopes. With two Velcro straps and four self-adhesive Velcro pads for added safety, you can be assured that the solar filter cannot be accidentally knocked off and will provide Solar Safe, ISO compliant viewing.","picture":"SolarFilter.jpg","priceUsd":{"currencyCode":"USD","units":69,"nanos":950000000},"categories":["accessories","telescopes"]},{"id":"HQTGWGPNH4","name":"The Comet Book","description":"A 16th-century treatise on comets, created anonymously in Flanders (now northern France) and now held at the Universitätsbibliothek Kassel. Commonly known as The Comet Book (or Kometenbuch in German), its full title translates as “Comets and their General and Particular Meanings, According to Ptolomeé, Albumasar, Haly, Aliquind and other Astrologers”. The image is from https://publicdomainreview.org/collection/the-comet-book, made available by the Universitätsbibliothek Kassel under a CC-BY SA 4.0 license (https://creativecommons.org/licenses/by-sa/4.0/)","picture":"TheCometBook.jpg","priceUsd":{"currencyCode":"USD","units":0,"nanos":990000000},"categories":["books"]}]'); From 702bc1dc6d8e4c37dcde76a60871da1981318704 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 18:00:57 +0200 Subject: [PATCH 15/60] add Dapr in the cartService --- Makefile | 10 +++++----- kubernetes/opentelemetry-demo.yaml | 5 ----- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 54a6a4ae8e..96ce7efdf0 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ TOOLS_DIR := ./internal/tools MISSPELL_BINARY=bin/misspell MISSPELL = $(TOOLS_DIR)/$(MISSPELL_BINARY) -DOCKER_COMPOSE_CMD ?= docker-compose +DOCKER_COMPOSE_CMD ?= docker compose DOCKER_COMPOSE_ENV=--env-file .env --env-file .env.override DOCKER_COMPOSE_BUILD_ARGS= @@ -103,12 +103,12 @@ build-and-push: # Create multiplatform builder for buildx .PHONY: create-multiplatform-builder create-multiplatform-builder: - docker-buildx create --name otel-demo-builder --bootstrap --use --driver docker-container --config ./buildkitd.toml + docker buildx create --name otel-demo-builder --bootstrap --use --driver docker-container --config ./buildkitd.toml # Remove multiplatform builder for buildx .PHONY: remove-multiplatform-builder remove-multiplatform-builder: - docker-buildx rm otel-demo-builder + docker buildx rm otel-demo-builder # Build and push multiplatform images (linux/amd64, linux/arm64) using buildx. # Requires docker with buildx enabled and a multi-platform capable builder in use. @@ -116,12 +116,12 @@ remove-multiplatform-builder: .PHONY: build-multiplatform build-multiplatform: # Because buildx bake does not support --env-file yet, we need to load it into the environment first. - set -a; . ./.env.override; set +a && docker-buildx bake -f docker-compose.yml --load --set "*.platform=linux/amd64,linux/arm64" + set -a; . ./.env.override; set +a && docker buildx bake -f docker-compose.yml --load --set "*.platform=linux/amd64,linux/arm64" .PHONY: build-multiplatform-and-push build-multiplatform-and-push: # Because buildx bake does not support --env-file yet, we need to load it into the environment first. - set -a; . ./.env.override; set +a && docker-buildx bake -f docker-compose.yml --push --set "*.platform=linux/amd64,linux/arm64" + set -a; . ./.env.override; set +a && docker buildx bake -f docker-compose.yml --push --set "*.platform=linux/amd64,linux/arm64" .PHONY: clean-images clean-images: diff --git a/kubernetes/opentelemetry-demo.yaml b/kubernetes/opentelemetry-demo.yaml index 6523f5e21b..3159432588 100644 --- a/kubernetes/opentelemetry-demo.yaml +++ b/kubernetes/opentelemetry-demo.yaml @@ -11437,11 +11437,6 @@ spec: app.kubernetes.io/instance: opentelemetry-demo app.kubernetes.io/component: cart app.kubernetes.io/name: cart - annotations: - dapr.io/enabled: "true" - dapr.io/app-id: "cart" - dapr.io/app-port: "8080" - dapr.io/config: "cart-state-store" spec: serviceAccountName: opentelemetry-demo containers: From 08ebf88e356895bc569e3fcb3430907ba3443aa6 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 18:03:04 +0200 Subject: [PATCH 16/60] add Dapr in the cartService --- src/checkout/go.mod | 2 - src/checkout/kafka/producer.go | 43 ++++++++++++++ src/checkout/main.go | 101 ++++++++++++++++++++++++--------- src/product-catalog/main.go | 2 - 4 files changed, 118 insertions(+), 30 deletions(-) create mode 100644 src/checkout/kafka/producer.go diff --git a/src/checkout/go.mod b/src/checkout/go.mod index 81eff70249..38e7e6f731 100644 --- a/src/checkout/go.mod +++ b/src/checkout/go.mod @@ -6,7 +6,6 @@ toolchain go1.22.9 require ( github.com/IBM/sarama v1.45.1 - github.com/dapr/go-sdk v1.15.0 github.com/google/uuid v1.6.0 github.com/open-feature/go-sdk v1.14.1 github.com/open-feature/go-sdk-contrib/hooks/open-telemetry v0.3.4 @@ -33,7 +32,6 @@ require ( connectrpc.com/connect v1.18.1 // indirect connectrpc.com/otelconnect v0.7.1 // indirect github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect - github.com/dapr/dapr v1.14.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/diegoholiveira/jsonlogic/v3 v3.7.4 // indirect diff --git a/src/checkout/kafka/producer.go b/src/checkout/kafka/producer.go new file mode 100644 index 0000000000..1304f1b976 --- /dev/null +++ b/src/checkout/kafka/producer.go @@ -0,0 +1,43 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +package kafka + +import ( + "github.com/IBM/sarama" + "github.com/sirupsen/logrus" +) + +var ( + Topic = "orders" + ProtocolVersion = sarama.V3_0_0_0 +) + +func CreateKafkaProducer(brokers []string, log *logrus.Logger) (sarama.AsyncProducer, error) { + sarama.Logger = log + + saramaConfig := sarama.NewConfig() + saramaConfig.Producer.Return.Successes = true + saramaConfig.Producer.Return.Errors = true + + // Sarama has an issue in a single broker kafka if the kafka broker is restarted. + // This setting is to prevent that issue from manifesting itself, but may swallow failed messages. + saramaConfig.Producer.RequiredAcks = sarama.NoResponse + + saramaConfig.Version = ProtocolVersion + + // So we can know the partition and offset of messages. + saramaConfig.Producer.Return.Successes = true + + producer, err := sarama.NewAsyncProducer(brokers, saramaConfig) + if err != nil { + return nil, err + } + + // We will log to STDOUT if we're not able to produce messages. + go func() { + for err := range producer.Errors() { + log.Errorf("Failed to write message: %+v", err) + } + }() + return producer, nil +} diff --git a/src/checkout/main.go b/src/checkout/main.go index d17c175a2b..c9d40c7f06 100644 --- a/src/checkout/main.go +++ b/src/checkout/main.go @@ -18,9 +18,7 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.24.0" "go.opentelemetry.io/otel/trace" - dapr "github.com/dapr/go-sdk/client" - - + "github.com/IBM/sarama" "github.com/google/uuid" otelhooks "github.com/open-feature/go-sdk-contrib/hooks/open-telemetry/pkg" flagd "github.com/open-feature/go-sdk-contrib/providers/flagd/pkg" @@ -45,6 +43,7 @@ import ( "google.golang.org/protobuf/proto" pb "github.com/open-telemetry/opentelemetry-demo/src/checkout/genproto/oteldemo" + "github.com/open-telemetry/opentelemetry-demo/src/checkout/kafka" "github.com/open-telemetry/opentelemetry-demo/src/checkout/money" ) @@ -127,8 +126,9 @@ type checkout struct { shippingSvcAddr string emailSvcAddr string paymentSvcAddr string + kafkaBrokerSvcAddr string pb.UnimplementedCheckoutServiceServer - daprClient dapr.Client + KafkaProducerClient sarama.AsyncProducer shippingSvcClient pb.ShippingServiceClient productCatalogSvcClient pb.ProductCatalogServiceClient cartSvcClient pb.CartServiceClient @@ -197,13 +197,14 @@ func main() { svc.paymentSvcClient = pb.NewPaymentServiceClient(c) defer c.Close() + svc.kafkaBrokerSvcAddr = os.Getenv("KAFKA_ADDR") - svc.daprClient, err = dapr.NewClient() - //#TODO! add error handling dapr - if err != nil { - log.Fatal(err) - } - + if svc.kafkaBrokerSvcAddr != "" { + svc.KafkaProducerClient, err = kafka.CreateKafkaProducer([]string{svc.kafkaBrokerSvcAddr}, log) + if err != nil { + log.Fatal(err) + } + } log.Infof("service config: %+v", svc) @@ -315,9 +316,11 @@ func (cs *checkout) PlaceOrder(ctx context.Context, req *pb.PlaceOrderRequest) ( log.Infof("order confirmation email sent to %q", req.Email) } - - cs.sendToPostProcessor(ctx, orderResult) - //#TODO! add errorhandling + // send to kafka only if kafka broker address is set + if cs.kafkaBrokerSvcAddr != "" { + log.Infof("sending to postProcessor") + cs.sendToPostProcessor(ctx, orderResult) + } resp := &pb.PlaceOrderResponse{Order: orderResult} return resp, nil @@ -493,34 +496,78 @@ func (cs *checkout) sendToPostProcessor(ctx context.Context, result *pb.OrderRes return } - var opts = []dapr.PublishEventOption{ - dapr.PublishEventWithContentType("application/octet-stream"), - } - - if err := cs.daprClient.PublishEvent(ctx, PUBSUB_NAME, TOPIC_NAME, message, opts...); err != nil { - panic(err) - //TODO# add error handling - } + msg := sarama.ProducerMessage{ + Topic: kafka.Topic, + Value: sarama.ByteEncoder(message), + } // Inject tracing info into message span := createProducerSpan(ctx, &msg) defer span.End() + // Send message and handle response + startTime := time.Now() + select { + case cs.KafkaProducerClient.Input() <- &msg: + log.Infof("Message sent to Kafka: %v", msg) + select { + case successMsg := <-cs.KafkaProducerClient.Successes(): + span.SetAttributes( + attribute.Bool("messaging.kafka.producer.success", true), + attribute.Int("messaging.kafka.producer.duration_ms", int(time.Since(startTime).Milliseconds())), + attribute.KeyValue(semconv.MessagingKafkaMessageOffset(int(successMsg.Offset))), + ) + log.Infof("Successful to write message. offset: %v, duration: %v", successMsg.Offset, time.Since(startTime)) + case errMsg := <-cs.KafkaProducerClient.Errors(): + span.SetAttributes( + attribute.Bool("messaging.kafka.producer.success", false), + attribute.Int("messaging.kafka.producer.duration_ms", int(time.Since(startTime).Milliseconds())), + ) + span.SetStatus(otelcodes.Error, errMsg.Err.Error()) + log.Errorf("Failed to write message: %v", errMsg.Err) + case <-ctx.Done(): + span.SetAttributes( + attribute.Bool("messaging.kafka.producer.success", false), + attribute.Int("messaging.kafka.producer.duration_ms", int(time.Since(startTime).Milliseconds())), + ) + span.SetStatus(otelcodes.Error, "Context cancelled: "+ctx.Err().Error()) + log.Warnf("Context canceled before success message received: %v", ctx.Err()) + } + case <-ctx.Done(): + span.SetAttributes( + attribute.Bool("messaging.kafka.producer.success", false), + attribute.Int("messaging.kafka.producer.duration_ms", int(time.Since(startTime).Milliseconds())), + ) + span.SetStatus(otelcodes.Error, "Failed to send: "+ctx.Err().Error()) + log.Errorf("Failed to send message to Kafka within context deadline: %v", ctx.Err()) + return + } + ffValue := cs.getIntFeatureFlag(ctx, "kafkaQueueProblems") + if ffValue > 0 { + log.Infof("Warning: FeatureFlag 'kafkaQueueProblems' is activated, overloading queue now.") + for i := 0; i < ffValue; i++ { + go func(i int) { + cs.KafkaProducerClient.Input() <- &msg + _ = <-cs.KafkaProducerClient.Successes() + }(i) + } + log.Infof("Done with #%d messages for overload simulation.", ffValue) + } } -func createProducerSpan(ctx context.Context, topic string) trace.Span { +func createProducerSpan(ctx context.Context, msg *sarama.ProducerMessage) trace.Span { spanContext, span := tracer.Start( ctx, - fmt.Sprintf("%s publish", topic), + fmt.Sprintf("%s publish", msg.Topic), trace.WithSpanKind(trace.SpanKindProducer), trace.WithAttributes( semconv.PeerService("kafka"), semconv.NetworkTransportTCP, semconv.MessagingSystemKafka, - semconv.MessagingDestinationName(topic), + semconv.MessagingDestinationName(msg.Topic), semconv.MessagingOperationPublish, - + semconv.MessagingKafkaDestinationPartition(int(msg.Partition)), ), ) @@ -528,7 +575,9 @@ func createProducerSpan(ctx context.Context, topic string) trace.Span { propagator := otel.GetTextMapPropagator() propagator.Inject(spanContext, carrier) - + for key, value := range carrier { + msg.Headers = append(msg.Headers, sarama.RecordHeader{Key: []byte(key), Value: []byte(value)}) + } return span } diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index c506291da7..fbdfd4718e 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -215,8 +215,6 @@ func loadProductCatalog() { } func readProductFiles() ([]*pb.Product, error) { - /// # todo change the souerce of data - // find all .json files in the products directory entries, err := os.ReadDir("./products") From 7f6267630aef3b04d6a6b3aa118c7f4ab20b3f0a Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 18:08:59 +0200 Subject: [PATCH 17/60] add Dapr in the cartService --- src/cart/src/cartstore/DaprStateManagementCartStore.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index d26aa5bb82..32caea416b 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -149,9 +149,13 @@ public async Task EmptyCartAsync(string userId) { return Oteldemo.Cart.Parser.ParseFrom(value); } + else + { + return new Oteldemo.Cart(); + } // We decided to return empty cart in cases when user wasn't in the cache before - return new Oteldemo.Cart(); + } catch (DaprException daprEx) { From a2df81295665913081842438e6ece7ae59daf5a0 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 18:21:14 +0200 Subject: [PATCH 18/60] add Dapr in the cartService --- src/cart/src/cartstore/DaprStateManagementCartStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index 32caea416b..a843875ecf 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -155,7 +155,7 @@ public async Task EmptyCartAsync(string userId) } // We decided to return empty cart in cases when user wasn't in the cache before - + return new Oteldemo.Cart(); } catch (DaprException daprEx) { From 477755ef4394fc9b0a53ea98c8f394f616e0a9e1 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 18:38:37 +0200 Subject: [PATCH 19/60] add Dapr in the cartService --- .../cartstore/DaprStateManagementCartStore.cs | 25 +++---------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/cart/src/cartstore/DaprStateManagementCartStore.cs b/src/cart/src/cartstore/DaprStateManagementCartStore.cs index a843875ecf..ce080edd4e 100644 --- a/src/cart/src/cartstore/DaprStateManagementCartStore.cs +++ b/src/cart/src/cartstore/DaprStateManagementCartStore.cs @@ -149,13 +149,10 @@ public async Task EmptyCartAsync(string userId) { return Oteldemo.Cart.Parser.ParseFrom(value); } - else - { - return new Oteldemo.Cart(); - } + // We decided to return empty cart in cases when user wasn't in the cache before - return new Oteldemo.Cart(); + return new Oteldemo.Cart(); } catch (DaprException daprEx) { @@ -163,11 +160,9 @@ public async Task EmptyCartAsync(string userId) { _logger.LogInformation("Dapr error: code: {errorInfo.Code} , message: {errorInfo.Message}", errorInfo.Code,errorInfo.Message); + } + throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage with Dapr. {daprEx}")); - - throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {daprEx}")); - - } } catch (Exception ex) { @@ -178,19 +173,7 @@ public async Task EmptyCartAsync(string userId) getCartHistogram.Record(stopwatch.ElapsedTicks); } } - public async Task Ping() - { - try - { - var isDaprReady = await _client.CheckHealthAsync(); - return isDaprReady; - } - catch (Exception) - { - return false; - } - } public async Task PingAsync() { return await _client.CheckOutboundHealthAsync(); From 19931824c203947a5258a5db61dfb389c8a09973 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 7 Apr 2025 18:53:40 +0200 Subject: [PATCH 20/60] add Dapr in the cartService --- src/frontend/utils/telemetry/FrontendTracer.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/frontend/utils/telemetry/FrontendTracer.ts b/src/frontend/utils/telemetry/FrontendTracer.ts index 1de1d2fc54..8f4de75455 100644 --- a/src/frontend/utils/telemetry/FrontendTracer.ts +++ b/src/frontend/utils/telemetry/FrontendTracer.ts @@ -42,8 +42,6 @@ const FrontendTracer = async () => { ], }); - provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter())); - const contextManager = new ZoneContextManager(); provider.register({ From 4c8122532ec51ab0056a5ff4865d2392dc954d78 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Tue, 8 Apr 2025 11:42:51 +0200 Subject: [PATCH 21/60] updated docker-compose.yaml and the changed the dapr configuraton; --- .env | 2 +- .../components}/cart-state-store.yaml | 2 -- {components => dapr/components}/pubsub.yaml | 0 dapr/config.yaml | 17 +++++++++++++++++ docker-compose.yml | 10 ++++++---- 5 files changed, 24 insertions(+), 7 deletions(-) rename {components => dapr/components}/cart-state-store.yaml (85%) rename {components => dapr/components}/pubsub.yaml (100%) create mode 100644 dapr/config.yaml diff --git a/.env b/.env index 609502c7bb..57c6ecf49f 100644 --- a/.env +++ b/.env @@ -2,7 +2,7 @@ # Demo App version IMAGE_VERSION=2.0.2 -IMAGE_NAME=hrexed/open-telemetry/demo +IMAGE_NAME=ghcr.io/open-telemetry/demo DEMO_VERSION=latest # Build Args diff --git a/components/cart-state-store.yaml b/dapr/components/cart-state-store.yaml similarity index 85% rename from components/cart-state-store.yaml rename to dapr/components/cart-state-store.yaml index 0144510617..f565a51363 100644 --- a/components/cart-state-store.yaml +++ b/dapr/components/cart-state-store.yaml @@ -8,7 +8,5 @@ spec: metadata: - name: redisHost value: valkey-cart:6379 - - name: redisPassword - value: "" - name: enableTLS value: false \ No newline at end of file diff --git a/components/pubsub.yaml b/dapr/components/pubsub.yaml similarity index 100% rename from components/pubsub.yaml rename to dapr/components/pubsub.yaml diff --git a/dapr/config.yaml b/dapr/config.yaml new file mode 100644 index 0000000000..60781a0d52 --- /dev/null +++ b/dapr/config.yaml @@ -0,0 +1,17 @@ +apiVersion: dapr.io/v1alpha1 +kind: Configuration +metadata: + name: app-config +spec: + metrics: + enabled: true + recordErrorCodes: true + logging: + apiLogging: + enabled: true + tracing: + samplingRate: "1" + otel: + endpointAddress: "otel-gateway-collector:4317:4317" + isSecure: true + protocol: grpc \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 63d5300d8d..40a467e8ca 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -85,15 +85,17 @@ services: container_name: cart-dapr command: [ "./daprd", "-app-id", "cart", - "-app-port", "3000", + "-app-port", "${CART_PORT}", "-placement-host-address", "dapr-placement:50006", "-dapr-grpc-port", "50002", "-dapr-http-port", "3500", - "-resources-path", "/components" ] + "-resources-path", "/dapr/components" + "-config", "/dapr/config.yaml"] volumes: - - "./components/:/components" + - "./dapr/:/dapr" depends_on: - cart + - valkey-cart network_mode: "service:cart" # Cart service cart: @@ -122,7 +124,7 @@ services: - OTEL_SERVICE_NAME=cart - ASPNETCORE_URLS=http://*:${CART_PORT} depends_on: - valkey-cart: + dapr-placement: condition: service_started otel-collector: condition: service_started From 0c029eef18eaca7b6333ded3973282b7ac81b50e Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Tue, 8 Apr 2025 12:38:40 +0200 Subject: [PATCH 22/60] added the change on the changelog.md --- CHANGELOG.md | 2 ++ dapr/config.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8f30fcc9e..0c6b4ba041 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ the release. ([#2114](https://github.com/open-telemetry/opentelemetry-demo/pull/2114)) * [flagd-ui] increase memory to 100MB ([#2120](https://github.com/open-telemetry/opentelemetry-demo/pull/2120)) +* [cart] removed the usage on valkey in the component and replaced it with the usage of Dapr client +* [sqllit] added the new sqllite service ( required for future change on the product catalog) ## 2.0.1 diff --git a/dapr/config.yaml b/dapr/config.yaml index 60781a0d52..7a3f143701 100644 --- a/dapr/config.yaml +++ b/dapr/config.yaml @@ -12,6 +12,6 @@ spec: tracing: samplingRate: "1" otel: - endpointAddress: "otel-gateway-collector:4317:4317" + endpointAddress: "otel-gateway-collector:4317" isSecure: true protocol: grpc \ No newline at end of file From 383de4670d3b965de994cc3ad1be8e8eb349bbc8 Mon Sep 17 00:00:00 2001 From: Henrik Rexed <81800915+henrikrexed@users.noreply.github.com> Date: Tue, 8 Apr 2025 15:36:10 +0200 Subject: [PATCH 23/60] Update .env change the local changes --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index 57c6ecf49f..199e14d2ee 100644 --- a/.env +++ b/.env @@ -23,7 +23,7 @@ VALKEY_IMAGE=valkey/valkey:8.1-alpine TRACETEST_IMAGE=kubeshop/tracetest:${TRACETEST_IMAGE_VERSION} # Demo Platform -ENV_PLATFORM=linux/amd64 +ENV_PLATFORM=local # OpenTelemetry Collector HOST_FILESYSTEM=/ From 4d5ac98edd3642cae98d8d86eebf7a4646f1d17b Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Tue, 8 Apr 2025 16:54:14 +0200 Subject: [PATCH 24/60] Remove the usage of a local file to a Postgresql database using the dapr client to query the content. --- dapr/components/product-store.yaml | 12 +++ docker-compose.yml | 32 +++++++ src/cart/src/Program.cs | 1 - src/postgresql/product/init.sql | 25 ++++++ src/product-catalog/go.mod | 1 + src/product-catalog/main.go | 139 ++++++++++++++++++++++------- src/sqllite/Dockerfile | 14 --- src/sqllite/product/init.sql | 7 -- 8 files changed, 176 insertions(+), 55 deletions(-) create mode 100644 dapr/components/product-store.yaml create mode 100644 src/postgresql/product/init.sql delete mode 100644 src/sqllite/Dockerfile delete mode 100644 src/sqllite/product/init.sql diff --git a/dapr/components/product-store.yaml b/dapr/components/product-store.yaml new file mode 100644 index 0000000000..7509a490f0 --- /dev/null +++ b/dapr/components/product-store.yaml @@ -0,0 +1,12 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: product-store +spec: + type: state.postgresql + version: v1 + metadata: + - name: connectionString + value: "host=product_db user=postgres password=example port=5432 connect_timeout=10 database=postgres" + - name: tableName + value: "product" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 40a467e8ca..b9f37a42ea 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -478,6 +478,36 @@ services: condition: service_started logging: *logging + product_db: + image: postgres:15.3-alpine3.18 + restart: always + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres123 + volumes: + - ./postgresql/product/init.sql:/docker-entrypoint-initdb.d/init.sql + - ./postgresql/data:/var/lib/postgresql/data + ports: + - 5436:5432 + product-dapr: + image: "daprio/daprd:edge" + container_name: product-dapr + command: [ "./daprd", + "-app-id", "product-catalog", + "-app-port", "${PRODUCT_CATALOG_PORT}", + "-placement-host-address", "dapr-placement:50006", + "-dapr-grpc-port", "50002", + "-dapr-http-port", "3500", + "-resources-path", "/dapr/components" + "-config", "/dapr/config.yaml" ] + volumes: + - "./dapr/:/dapr" + depends_on: + product_db: + condition: service_started + logging: *logging + network_mode: "service:product-catalog" + # Product Catalog service product-catalog: image: ${IMAGE_NAME}:${DEMO_VERSION}-product-catalog @@ -510,6 +540,8 @@ services: condition: service_started flagd: condition: service_started + product-dapr: + condition: service_started logging: *logging # Quote service diff --git a/src/cart/src/Program.cs b/src/cart/src/Program.cs index aea9e49ff2..43896a2921 100644 --- a/src/cart/src/Program.cs +++ b/src/cart/src/Program.cs @@ -20,7 +20,6 @@ using OpenFeature.Contrib.Hooks.Otel; var builder = WebApplication.CreateBuilder(args); -string valkeyAddress = builder.Configuration["VALKEY_ADDR"]; builder.Logging diff --git a/src/postgresql/product/init.sql b/src/postgresql/product/init.sql new file mode 100644 index 0000000000..f3e2bc4fe9 --- /dev/null +++ b/src/postgresql/product/init.sql @@ -0,0 +1,25 @@ + +DROP TABLE IF EXISTS "product"; + +CREATE TABLE "product" ( + "id" VARCHAR(512), + "name" VARCHAR(512), + "description" VARCHAR(512), + "picture" VARCHAR(512), + "priceUsd.currencyCode" VARCHAR(512), + "priceUsd.units" VARCHAR(512), + "priceUsd.nanos" INT, + "categories" VARCHAR(512) +); + +INSERT INTO "product" ("id", "name", "description", "picture", "priceUsd.currencyCode", "priceUsd.units", "priceUsd.nanos", "categories") VALUES + ('OLJCESPC7Z', 'National Park Foundation Explorascope', 'The National Park Foundation’s (NPF) Explorascope 60AZ is a manual alt-azimuth, refractor telescope perfect for celestial viewing on the go. The NPF Explorascope 60 can view the planets, moon, star clusters and brighter deep sky objects like the Orion Nebula and Andromeda Galaxy.', 'NationalParkFoundationExplorascope.jpg', 'USD', '101', '960000000', 'telescopes'), + ('66VCHSJNUP', 'Starsense Explorer Refractor Telescope', 'The first telescope that uses your smartphone to analyze the night sky and calculate its position in real time. StarSense Explorer is ideal for beginners thanks to the app’s user-friendly interface and detailed tutorials. It’s like having your own personal tour guide of the night sky', 'StarsenseExplorer.jpg', 'USD', '349', '950000000', 'telescopes'), + ('1YMWWN1N4O', 'Eclipsmart Travel Refractor Telescope', 'Dedicated white-light solar scope for the observer on the go. The 50mm refracting solar scope uses Solar Safe, ISO compliant, full-aperture glass filter material to ensure the safest view of solar events. The kit comes complete with everything you need, including the dedicated travel solar scope, a Solar Safe finderscope, tripod, a high quality 20mm (18x) Kellner eyepiece and a nylon backpack to carry everything in. This Travel Solar Scope makes it easy to share the Sun as well as partial and total solar eclipses with the whole family and offers much higher magnifications than you would otherwise get using handheld solar viewers or binoculars.', 'EclipsmartTravelRefractorTelescope.jpg', 'USD', '129', '950000000', 'telescopes,travel'), + ('L9ECAV7KIM', 'Lens Cleaning Kit', 'Wipe away dust, dirt, fingerprints and other particles on your lenses to see clearly with the Lens Cleaning Kit. This cleaning kit works on all glass and optical surfaces, including telescopes, binoculars, spotting scopes, monoculars, microscopes, and even your camera lenses, computer screens, and mobile devices. The kit comes complete with a retractable lens brush to remove dust particles and dirt and two options to clean smudges and fingerprints off of your optics, pre-moistened lens wipes and a bottled lens cleaning fluid with soft cloth.', 'LensCleaningKit.jpg', 'USD', '21', '950000000', 'accessories'), + ('2ZYFJ3GM2N', 'Roof Binoculars', 'This versatile, all-around binocular is a great choice for the trail, the stadium, the arena, or just about anywhere you want a close-up view of the action without sacrificing brightness or detail. It’s an especially great companion for nature observation and bird watching, with ED glass that helps you spot the subtlest field markings and a close focus of just 6.5 feet.', 'RoofBinoculars.jpg', 'USD', '209', '950000000', 'binoculars'), + ('0PUK6V6EV0', 'Solar System Color Imager', 'You have your new telescope and have observed Saturn and Jupiter. Now you\'re ready to take the next step and start imaging them. But where do you begin? The NexImage 10 Solar System Imager is the perfect solution.', 'SolarSystemColorImager.jpg', 'USD', '175', '0', 'accessories,telescopes'), + ('LS4PSXUNUM', 'Red Flashlight', 'This 3-in-1 device features a 3-mode red flashlight, a hand warmer, and a portable power bank for recharging your personal electronics on the go. Whether you use it to light the way at an astronomy star party, a night walk, or wildlife research, ThermoTorch 3 Astro Red’s rugged, IPX4-rated design will withstand your everyday activities.', 'RedFlashlight.jpg', 'USD', '57', '80000000', 'accessories,flashlights'), + ('9SIQT8TOJO', 'Optical Tube Assembly', 'Capturing impressive deep-sky astroimages is easier than ever with Rowe-Ackermann Schmidt Astrograph (RASA) V2, the perfect companion to today’s top DSLR or astronomical CCD cameras. This fast, wide-field f/2.2 system allows for shorter exposure times compared to traditional f/10 astroimaging, without sacrificing resolution. Because shorter sub-exposure times are possible, your equatorial mount won’t need to accurately track over extended periods. The short focal length also lessens equatorial tracking demands. In many cases, autoguiding will not be required.', 'OpticalTubeAssembly.jpg', 'USD', '3599', '0', 'accessories,telescopes,assembly'), + ('6E92ZMYYFZ', 'Solar Filter', 'Enhance your viewing experience with EclipSmart Solar Filter for 8” telescopes. With two Velcro straps and four self-adhesive Velcro pads for added safety, you can be assured that the solar filter cannot be accidentally knocked off and will provide Solar Safe, ISO compliant viewing.', 'SolarFilter.jpg', 'USD', '69', '950000000', 'accessories,telescopes'), + ('HQTGWGPNH4', 'The Comet Book', 'A 16th-century treatise on comets, created anonymously in Flanders (now northern France) and now held at the Universitätsbibliothek Kassel. Commonly known as The Comet Book (or Kometenbuch in German), its full title translates as “Comets and their General and Particular Meanings, According to Ptolomeé, Albumasar, Haly, Aliquind and other Astrologers”. The image is from https://publicdomainreview.org/collection/the-comet-book, made available by the Universitätsbibliothek Kassel under a CC-BY SA 4.0 license (https://creativecommons.org/licenses/by-sa/4.0/)', 'TheCometBook.jpg', 'USD', '0', '990000000', 'books'); \ No newline at end of file diff --git a/src/product-catalog/go.mod b/src/product-catalog/go.mod index 71d9c999e3..17036797b3 100644 --- a/src/product-catalog/go.mod +++ b/src/product-catalog/go.mod @@ -20,6 +20,7 @@ require ( google.golang.org/grpc v1.71.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.5 + github.com/dapr/go-sdk/client v1.15.4 ) require ( diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index fbdfd4718e..cc967900eb 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -45,6 +45,7 @@ import ( "google.golang.org/grpc/reflection" "google.golang.org/grpc/status" "google.golang.org/protobuf/encoding/protojson" + dapr "github.com/dapr/go-sdk/client" ) var ( @@ -55,9 +56,36 @@ var ( ) const DEFAULT_RELOAD_INTERVAL = 10 +const dapr_store = "product-store" +type Product_SQL struct { + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + Picture string `protobuf:"bytes,4,opt,name=picture,proto3" json:"picture,omitempty"` + PriceUSCurrencyCode string `protobuf:"bytes,1,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` + // The whole units of the amount. + // For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar. + PriceUSCurrencyCode int64 `protobuf:"varint,2,opt,name=units,proto3" json:"units,omitempty"` + // Number of nano (10^-9) units of the amount. + // The value must be between -999,999,999 and +999,999,999 inclusive. + // If `units` is positive, `nanos` must be positive or zero. + // If `units` is zero, `nanos` can be positive, zero, or negative. + // If `units` is negative, `nanos` must be negative or zero. + // For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000. + PriceUSCurrencyCode int32 `protobuf:"varint,3,opt,name=nanos,proto3" json:"nanos,omitempty" + Categories []string `protobuf:"bytes,6,rep,name=categories,proto3" json:"categories,omitempty"` + +} func init() { log = logrus.New() + client, err := dapr.NewClient() + if err != nil { + log.Fatalf("Cannot create Dapr client : %s", err) + panic(err) + } + defer client.Close() + loadProductCatalog() } @@ -213,43 +241,88 @@ func loadProductCatalog() { } }() } +func sendQueryToBackend() ([]*pb.Product, error) +{ + query := `{ + + "sort": [ + { + "key": "name", + "order": "ASC" + } + ] + }` + // Use the client to query the state + queryResponse, err := client.QueryState(ctx, dapr_store, query) + if err != nil { + log.Fatal(err) + st := status.Convert(err) + + log.Fatal("Code: %s\n", st.Code().String()) + log.Fatal("Message: %s\n", st.Message()) + + for _, detail := range st.Details() { + switch t := detail.(type) { + case *errdetails.ErrorInfo: + // Handle ErrorInfo details + log.Fatal("ErrorInfo:\n- Domain: %s\n- Reason: %s\n- Metadata: %v\n", t.GetDomain(), t.GetReason(), t.GetMetadata()) + case *errdetails.BadRequest: + // Handle BadRequest details + fmt.Println("BadRequest:") + for _, violation := range t.GetFieldViolations() { + log.Fatal("- Key: %s\n", violation.GetField()) + log.Fatal("- The %q field was wrong: %s\n", violation.GetField(), violation.GetDescription()) + } + case *errdetails.ResourceInfo: + // Handle ResourceInfo details + log.Fatal("ResourceInfo:\n- Resource type: %s\n- Resource name: %s\n- Owner: %s\n- Description: %s\n", + t.GetResourceType(), t.GetResourceName(), t.GetOwner(), t.GetDescription()) + case *errdetails.Help: + // Handle ResourceInfo details + log.Fatal("HelpInfo:") + for _, link := range t.GetLinks() { + log.Fatal("- Url: %s\n", link.Url) + log.Fatal("- Description: %s\n", link.Description) + } + + default: + // Add cases for other types of details you expect + log.Fatal("Unhandled error detail type: %v\n", t) + } + } + } + + for _, product := range queryResponse { + var data Product_SQL + var json; + err := product.Unmarshal(&data) + + if err != nil { + log.Fatal("Unhandled error detail type: %v\n", err) + } + + products = append(products, pb.Product{ + Id: data.id, + Name: data.name, + Description: data.description, + Picture: data.Picture, + PriceUsd: pb.Money{ + CurrencyCode: data.priceUsd.currencyCode, + Units: data.priceUsd.units, + Nanos: data.priceUsd.nanos + }, + Categories: data.categories + + }) + } + log.Infof("Loaded %d products", len(products)) + return products +} func readProductFiles() ([]*pb.Product, error) { - // find all .json files in the products directory - entries, err := os.ReadDir("./products") - if err != nil { - return nil, err - } - - jsonFiles := make([]fs.FileInfo, 0, len(entries)) - for _, entry := range entries { - if strings.HasSuffix(entry.Name(), ".json") { - info, err := entry.Info() - if err != nil { - return nil, err - } - jsonFiles = append(jsonFiles, info) - } - } - - // read the contents of each .json file and unmarshal into a ListProductsResponse - // then append the products to the catalog - var products []*pb.Product - for _, f := range jsonFiles { - jsonData, err := os.ReadFile("./products/" + f.Name()) - if err != nil { - return nil, err - } - - var res pb.ListProductsResponse - if err := protojson.Unmarshal(jsonData, &res); err != nil { - return nil, err - } - - products = append(products, res.Products...) - } + products = sendQueryToBackend() log.Infof("Loaded %d products", len(products)) return products, nil diff --git a/src/sqllite/Dockerfile b/src/sqllite/Dockerfile deleted file mode 100644 index 973216b8de..0000000000 --- a/src/sqllite/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -# Use a lightweight base image -FROM alpine:latest - -# Install SQLite -RUN apk --no-cache add sqlite - -# Create a directory to store the database -WORKDIR /db - -# Copy your SQL script into the container -COPY product/init.sql /docker-entrypoint-initdb.d/ - -# Command to run when the container starts -CMD ["sh", "-c", "sqlite3 /db/mydatabase.db < /docker-entrypoint-initdb.d/init.sql && tail -f /dev/null"] \ No newline at end of file diff --git a/src/sqllite/product/init.sql b/src/sqllite/product/init.sql deleted file mode 100644 index 917a97d65a..0000000000 --- a/src/sqllite/product/init.sql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE TABLE [Product] ( - [products] TEXT -); - -INSERT INTO [Product] ([products]) -VALUES -('[{"id":"OLJCESPC7Z","name":"National Park Foundation Explorascope","description":"The National Park Foundation’s (NPF) Explorascope 60AZ is a manual alt-azimuth, refractor telescope perfect for celestial viewing on the go. The NPF Explorascope 60 can view the planets, moon, star clusters and brighter deep sky objects like the Orion Nebula and Andromeda Galaxy.","picture":"NationalParkFoundationExplorascope.jpg","priceUsd":{"currencyCode":"USD","units":101,"nanos":960000000},"categories":["telescopes"]},{"id":"66VCHSJNUP","name":"Starsense Explorer Refractor Telescope","description":"The first telescope that uses your smartphone to analyze the night sky and calculate its position in real time. StarSense Explorer is ideal for beginners thanks to the app’s user-friendly interface and detailed tutorials. It’s like having your own personal tour guide of the night sky","picture":"StarsenseExplorer.jpg","priceUsd":{"currencyCode":"USD","units":349,"nanos":950000000},"categories":["telescopes"]},{"id":"1YMWWN1N4O","name":"Eclipsmart Travel Refractor Telescope","description":"Dedicated white-light solar scope for the observer on the go. The 50mm refracting solar scope uses Solar Safe, ISO compliant, full-aperture glass filter material to ensure the safest view of solar events. The kit comes complete with everything you need, including the dedicated travel solar scope, a Solar Safe finderscope, tripod, a high quality 20mm (18x) Kellner eyepiece and a nylon backpack to carry everything in. This Travel Solar Scope makes it easy to share the Sun as well as partial and total solar eclipses with the whole family and offers much higher magnifications than you would otherwise get using handheld solar viewers or binoculars.","picture":"EclipsmartTravelRefractorTelescope.jpg","priceUsd":{"currencyCode":"USD","units":129,"nanos":950000000},"categories":["telescopes","travel"]},{"id":"L9ECAV7KIM","name":"Lens Cleaning Kit","description":"Wipe away dust, dirt, fingerprints and other particles on your lenses to see clearly with the Lens Cleaning Kit. This cleaning kit works on all glass and optical surfaces, including telescopes, binoculars, spotting scopes, monoculars, microscopes, and even your camera lenses, computer screens, and mobile devices. The kit comes complete with a retractable lens brush to remove dust particles and dirt and two options to clean smudges and fingerprints off of your optics, pre-moistened lens wipes and a bottled lens cleaning fluid with soft cloth.","picture":"LensCleaningKit.jpg","priceUsd":{"currencyCode":"USD","units":21,"nanos":950000000},"categories":["accessories"]},{"id":"2ZYFJ3GM2N","name":"Roof Binoculars","description":"This versatile, all-around binocular is a great choice for the trail, the stadium, the arena, or just about anywhere you want a close-up view of the action without sacrificing brightness or detail. It’s an especially great companion for nature observation and bird watching, with ED glass that helps you spot the subtlest field markings and a close focus of just 6.5 feet.","picture":"RoofBinoculars.jpg","priceUsd":{"currencyCode":"USD","units":209,"nanos":950000000},"categories":["binoculars"]},{"id":"0PUK6V6EV0","name":"Solar System Color Imager","description":"You have your new telescope and have observed Saturn and Jupiter. Now you''re ready to take the next step and start imaging them. But where do you begin? The NexImage 10 Solar System Imager is the perfect solution.","picture":"SolarSystemColorImager.jpg","priceUsd":{"currencyCode":"USD","units":175,"nanos":0},"categories":["accessories","telescopes"]},{"id":"LS4PSXUNUM","name":"Red Flashlight","description":"This 3-in-1 device features a 3-mode red flashlight, a hand warmer, and a portable power bank for recharging your personal electronics on the go. Whether you use it to light the way at an astronomy star party, a night walk, or wildlife research, ThermoTorch 3 Astro Red’s rugged, IPX4-rated design will withstand your everyday activities.","picture":"RedFlashlight.jpg","priceUsd":{"currencyCode":"USD","units":57,"nanos":80000000},"categories":["accessories","flashlights"]},{"id":"9SIQT8TOJO","name":"Optical Tube Assembly","description":"Capturing impressive deep-sky astroimages is easier than ever with Rowe-Ackermann Schmidt Astrograph (RASA) V2, the perfect companion to today’s top DSLR or astronomical CCD cameras. This fast, wide-field f/2.2 system allows for shorter exposure times compared to traditional f/10 astroimaging, without sacrificing resolution. Because shorter sub-exposure times are possible, your equatorial mount won’t need to accurately track over extended periods. The short focal length also lessens equatorial tracking demands. In many cases, autoguiding will not be required.","picture":"OpticalTubeAssembly.jpg","priceUsd":{"currencyCode":"USD","units":3599,"nanos":0},"categories":["accessories","telescopes","assembly"]},{"id":"6E92ZMYYFZ","name":"Solar Filter","description":"Enhance your viewing experience with EclipSmart Solar Filter for 8” telescopes. With two Velcro straps and four self-adhesive Velcro pads for added safety, you can be assured that the solar filter cannot be accidentally knocked off and will provide Solar Safe, ISO compliant viewing.","picture":"SolarFilter.jpg","priceUsd":{"currencyCode":"USD","units":69,"nanos":950000000},"categories":["accessories","telescopes"]},{"id":"HQTGWGPNH4","name":"The Comet Book","description":"A 16th-century treatise on comets, created anonymously in Flanders (now northern France) and now held at the Universitätsbibliothek Kassel. Commonly known as The Comet Book (or Kometenbuch in German), its full title translates as “Comets and their General and Particular Meanings, According to Ptolomeé, Albumasar, Haly, Aliquind and other Astrologers”. The image is from https://publicdomainreview.org/collection/the-comet-book, made available by the Universitätsbibliothek Kassel under a CC-BY SA 4.0 license (https://creativecommons.org/licenses/by-sa/4.0/)","picture":"TheCometBook.jpg","priceUsd":{"currencyCode":"USD","units":0,"nanos":990000000},"categories":["books"]}]'); From 826f35a85a97492da3199eb1055e738f6a3a9dc2 Mon Sep 17 00:00:00 2001 From: Henrik Rexed <81800915+henrikrexed@users.noreply.github.com> Date: Tue, 8 Apr 2025 17:28:39 +0200 Subject: [PATCH 25/60] Update docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 40a467e8ca..fce353f65d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -89,7 +89,7 @@ services: "-placement-host-address", "dapr-placement:50006", "-dapr-grpc-port", "50002", "-dapr-http-port", "3500", - "-resources-path", "/dapr/components" + "-resources-path", "/dapr/components", "-config", "/dapr/config.yaml"] volumes: - "./dapr/:/dapr" From 6799038a2bdc4fd005b44a9d939d4aeac23957b1 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Tue, 8 Apr 2025 17:30:05 +0200 Subject: [PATCH 26/60] issue in the docker compose .yaml --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index b9f37a42ea..c1030730c5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -89,7 +89,7 @@ services: "-placement-host-address", "dapr-placement:50006", "-dapr-grpc-port", "50002", "-dapr-http-port", "3500", - "-resources-path", "/dapr/components" + "-resources-path", "/dapr/components", "-config", "/dapr/config.yaml"] volumes: - "./dapr/:/dapr" @@ -498,7 +498,7 @@ services: "-placement-host-address", "dapr-placement:50006", "-dapr-grpc-port", "50002", "-dapr-http-port", "3500", - "-resources-path", "/dapr/components" + "-resources-path", "/dapr/components", "-config", "/dapr/config.yaml" ] volumes: - "./dapr/:/dapr" From 8bee495867fbc7aa03e15de02c5fe6b01f65cc97 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Tue, 8 Apr 2025 17:52:33 +0200 Subject: [PATCH 27/60] issue in the docker compose .yaml --- docker-compose.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index c1030730c5..be295e528d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -489,6 +489,7 @@ services: - ./postgresql/data:/var/lib/postgresql/data ports: - 5436:5432 + product-dapr: image: "daprio/daprd:edge" container_name: product-dapr @@ -540,8 +541,9 @@ services: condition: service_started flagd: condition: service_started - product-dapr: + dapr-placement: condition: service_started + logging: *logging # Quote service From ed67a05d2b9f54bd060fc7e58973aef6234b51c9 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Tue, 8 Apr 2025 18:12:55 +0200 Subject: [PATCH 28/60] update go.sum and go.mod --- src/product-catalog/go.mod | 3 ++- src/product-catalog/go.sum | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/product-catalog/go.mod b/src/product-catalog/go.mod index 17036797b3..b2fbd394d4 100644 --- a/src/product-catalog/go.mod +++ b/src/product-catalog/go.mod @@ -20,10 +20,11 @@ require ( google.golang.org/grpc v1.71.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.5 - github.com/dapr/go-sdk/client v1.15.4 + ) require ( + github.com/dapr/dapr v1.15.0-rc.1 // indirect buf.build/gen/go/open-feature/flagd/connectrpc/go v1.17.0-20240906125204-0a6a901b42e8.1 // indirect buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20250127221518-be6d1143b690.2 // indirect buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.5-20250127221518-be6d1143b690.1 // indirect diff --git a/src/product-catalog/go.sum b/src/product-catalog/go.sum index 2c54cde3d1..d58c359b36 100644 --- a/src/product-catalog/go.sum +++ b/src/product-catalog/go.sum @@ -8,6 +8,8 @@ connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw= connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY= connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= +github.com/dapr/dapr v1.15.0-rc.1 h1:7JP3zSannxQwV27A9pPR2b/DSNmgcSjJOhRDwM4eFpQ= +github.com/dapr/dapr v1.15.0-rc.1/go.mod h1:SycZrBWgfmog+C5T4p0X6VIpnREQ3xajrYxdih+gn9w= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= From ac61fbbf0fd0008b18e5bf3c482248bb22bb7c6a Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Tue, 8 Apr 2025 18:14:39 +0200 Subject: [PATCH 29/60] update go.sum and go.mod --- src/product-catalog/go.mod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/product-catalog/go.mod b/src/product-catalog/go.mod index b2fbd394d4..d70ad9f9a5 100644 --- a/src/product-catalog/go.mod +++ b/src/product-catalog/go.mod @@ -1,8 +1,8 @@ module github.com/opentelemetry/opentelemetry-demo/src/product-catalog -go 1.22.7 +go 1.23.3 -toolchain go1.22.9 +toolchain go1.23.6 require ( github.com/open-feature/go-sdk v1.14.1 From 517c3c30a914cd26cf9824c47bbd2b7837a9085e Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Tue, 8 Apr 2025 18:16:39 +0200 Subject: [PATCH 30/60] update go.sum and go.mod --- src/product-catalog/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/product-catalog/Dockerfile b/src/product-catalog/Dockerfile index a13aafb9bb..66d0cf2474 100644 --- a/src/product-catalog/Dockerfile +++ b/src/product-catalog/Dockerfile @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 -FROM golang:1.22-alpine AS builder +FROM golang:1.23-alpine AS builder WORKDIR /usr/src/app/ From 68b2c330c9541ade8af6536cc239d20cd3084ed4 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Tue, 8 Apr 2025 18:30:21 +0200 Subject: [PATCH 31/60] update go.sum and go.mod --- src/product-catalog/Dockerfile | 2 +- src/product-catalog/go.mod | 6 +++--- src/product-catalog/go.sum | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/product-catalog/Dockerfile b/src/product-catalog/Dockerfile index 66d0cf2474..a13aafb9bb 100644 --- a/src/product-catalog/Dockerfile +++ b/src/product-catalog/Dockerfile @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 -FROM golang:1.23-alpine AS builder +FROM golang:1.22-alpine AS builder WORKDIR /usr/src/app/ diff --git a/src/product-catalog/go.mod b/src/product-catalog/go.mod index d70ad9f9a5..b479776bd4 100644 --- a/src/product-catalog/go.mod +++ b/src/product-catalog/go.mod @@ -1,8 +1,8 @@ module github.com/opentelemetry/opentelemetry-demo/src/product-catalog -go 1.23.3 +go 1.22.6 -toolchain go1.23.6 +toolchain go1.22.6 require ( github.com/open-feature/go-sdk v1.14.1 @@ -24,7 +24,7 @@ require ( ) require ( - github.com/dapr/dapr v1.15.0-rc.1 // indirect + github.com/dapr/dapr v1.14.0 // indirect buf.build/gen/go/open-feature/flagd/connectrpc/go v1.17.0-20240906125204-0a6a901b42e8.1 // indirect buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20250127221518-be6d1143b690.2 // indirect buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.5-20250127221518-be6d1143b690.1 // indirect diff --git a/src/product-catalog/go.sum b/src/product-catalog/go.sum index d58c359b36..0c23bb37ff 100644 --- a/src/product-catalog/go.sum +++ b/src/product-catalog/go.sum @@ -8,8 +8,10 @@ connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw= connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY= connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= -github.com/dapr/dapr v1.15.0-rc.1 h1:7JP3zSannxQwV27A9pPR2b/DSNmgcSjJOhRDwM4eFpQ= -github.com/dapr/dapr v1.15.0-rc.1/go.mod h1:SycZrBWgfmog+C5T4p0X6VIpnREQ3xajrYxdih+gn9w= +github.com/dapr/dapr v1.14.0 h1:SIQsNX1kH31JRDIS4k8IZ6eomM/BAcOP844PhQIT+BQ= +github.com/dapr/dapr v1.14.0/go.mod h1:oDNgaPHQIDZ3G4n4g89TElXWgkluYwcar41DI/oF4gw= +github.com/dapr/go-sdk v1.11.0 h1:clANpOQd6MsfvSa6snaX8MVk6eRx26Vsj5GxGdQ6mpE= +github.com/dapr/go-sdk v1.11.0/go.mod h1:btZ/tX8eYnx0fg3HiJUku8J5QBRXHsp3kAB1BUiTxXY= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= From c95e23311e2b8611a146e91f7a4bc8e77b11c33a Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Tue, 8 Apr 2025 18:40:07 +0200 Subject: [PATCH 32/60] update go.sum and go.mod --- src/product-catalog/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/product-catalog/Dockerfile b/src/product-catalog/Dockerfile index a13aafb9bb..e1f210c621 100644 --- a/src/product-catalog/Dockerfile +++ b/src/product-catalog/Dockerfile @@ -7,8 +7,8 @@ FROM golang:1.22-alpine AS builder WORKDIR /usr/src/app/ RUN --mount=type=cache,target=/go/pkg/mod/ \ - --mount=type=bind,source=./src/product-catalog/go.sum,target=go.sum \ - --mount=type=bind,source=./src/product-catalog/go.mod,target=go.mod \ + --mount=type=bind,source=./src/product-catalog/go.sum,target=go.sum,readonly\ + --mount=type=bind,source=./src/product-catalog/go.mod,target=go.mod,rw \ go mod download RUN --mount=type=cache,target=/go/pkg/mod/ \ From 04805257513ba9291bea937ac41ab9767b01f13c Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Tue, 8 Apr 2025 18:42:38 +0200 Subject: [PATCH 33/60] update go.sum and go.mod --- src/product-catalog/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/product-catalog/Dockerfile b/src/product-catalog/Dockerfile index e1f210c621..9c072f122c 100644 --- a/src/product-catalog/Dockerfile +++ b/src/product-catalog/Dockerfile @@ -9,7 +9,7 @@ WORKDIR /usr/src/app/ RUN --mount=type=cache,target=/go/pkg/mod/ \ --mount=type=bind,source=./src/product-catalog/go.sum,target=go.sum,readonly\ --mount=type=bind,source=./src/product-catalog/go.mod,target=go.mod,rw \ - go mod download + go mod tidy RUN --mount=type=cache,target=/go/pkg/mod/ \ --mount=type=cache,target=/root/.cache/go-build \ From 5d8c3cb7ce33cbf608e38d4b6247057f20aea8d6 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Tue, 8 Apr 2025 18:44:05 +0200 Subject: [PATCH 34/60] update go.sum and go.mod --- src/product-catalog/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/product-catalog/Dockerfile b/src/product-catalog/Dockerfile index 9c072f122c..22056410e3 100644 --- a/src/product-catalog/Dockerfile +++ b/src/product-catalog/Dockerfile @@ -7,7 +7,7 @@ FROM golang:1.22-alpine AS builder WORKDIR /usr/src/app/ RUN --mount=type=cache,target=/go/pkg/mod/ \ - --mount=type=bind,source=./src/product-catalog/go.sum,target=go.sum,readonly\ + --mount=type=bind,source=./src/product-catalog/go.sum,target=go.sum,rw\ --mount=type=bind,source=./src/product-catalog/go.mod,target=go.mod,rw \ go mod tidy From 56666ad824d249cbd718319364784a2a8a2f50f1 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Wed, 9 Apr 2025 15:28:09 +0200 Subject: [PATCH 35/60] update go.sum and go.mod & dockerfile, resolve compilation issues --- src/product-catalog/Dockerfile | 6 +- src/product-catalog/go.mod | 10 +-- src/product-catalog/go.sum | 12 +-- src/product-catalog/main.go | 144 ++++++++++++++------------------- 4 files changed, 74 insertions(+), 98 deletions(-) diff --git a/src/product-catalog/Dockerfile b/src/product-catalog/Dockerfile index 22056410e3..a13aafb9bb 100644 --- a/src/product-catalog/Dockerfile +++ b/src/product-catalog/Dockerfile @@ -7,9 +7,9 @@ FROM golang:1.22-alpine AS builder WORKDIR /usr/src/app/ RUN --mount=type=cache,target=/go/pkg/mod/ \ - --mount=type=bind,source=./src/product-catalog/go.sum,target=go.sum,rw\ - --mount=type=bind,source=./src/product-catalog/go.mod,target=go.mod,rw \ - go mod tidy + --mount=type=bind,source=./src/product-catalog/go.sum,target=go.sum \ + --mount=type=bind,source=./src/product-catalog/go.mod,target=go.mod \ + go mod download RUN --mount=type=cache,target=/go/pkg/mod/ \ --mount=type=cache,target=/root/.cache/go-build \ diff --git a/src/product-catalog/go.mod b/src/product-catalog/go.mod index b479776bd4..6c38a59777 100644 --- a/src/product-catalog/go.mod +++ b/src/product-catalog/go.mod @@ -1,10 +1,11 @@ module github.com/opentelemetry/opentelemetry-demo/src/product-catalog -go 1.22.6 +go 1.23.6 -toolchain go1.22.6 +toolchain go1.24.2 require ( + github.com/dapr/go-sdk v1.12.0 github.com/open-feature/go-sdk v1.14.1 github.com/open-feature/go-sdk-contrib/hooks/open-telemetry v0.3.4 github.com/open-feature/go-sdk-contrib/providers/flagd v0.2.6 @@ -20,11 +21,9 @@ require ( google.golang.org/grpc v1.71.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.5 - ) require ( - github.com/dapr/dapr v1.14.0 // indirect buf.build/gen/go/open-feature/flagd/connectrpc/go v1.17.0-20240906125204-0a6a901b42e8.1 // indirect buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20250127221518-be6d1143b690.2 // indirect buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.5-20250127221518-be6d1143b690.1 // indirect @@ -32,6 +31,7 @@ require ( connectrpc.com/otelconnect v0.7.1 // indirect github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/dapr/dapr v1.15.0-rc.17 // indirect github.com/diegoholiveira/jsonlogic/v3 v3.7.4 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect @@ -73,7 +73,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apimachinery v0.31.4 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect + k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect sigs.k8s.io/controller-runtime v0.19.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect diff --git a/src/product-catalog/go.sum b/src/product-catalog/go.sum index 0c23bb37ff..17d50600cc 100644 --- a/src/product-catalog/go.sum +++ b/src/product-catalog/go.sum @@ -8,14 +8,14 @@ connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw= connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY= connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= -github.com/dapr/dapr v1.14.0 h1:SIQsNX1kH31JRDIS4k8IZ6eomM/BAcOP844PhQIT+BQ= -github.com/dapr/dapr v1.14.0/go.mod h1:oDNgaPHQIDZ3G4n4g89TElXWgkluYwcar41DI/oF4gw= -github.com/dapr/go-sdk v1.11.0 h1:clANpOQd6MsfvSa6snaX8MVk6eRx26Vsj5GxGdQ6mpE= -github.com/dapr/go-sdk v1.11.0/go.mod h1:btZ/tX8eYnx0fg3HiJUku8J5QBRXHsp3kAB1BUiTxXY= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/dapr/dapr v1.15.0-rc.17 h1:bR0rd4FH81IteuOHTWVNyl58ZuQTDp3DYaTtXnpZ6JA= +github.com/dapr/dapr v1.15.0-rc.17/go.mod h1:SD0AXom2XpX7pr8eYlbJ+gHfNREsflsrzCR19AZJ7/Q= +github.com/dapr/go-sdk v1.12.0 h1:+9IHZ1faWwNg/HvZk1ht0oIU8eqOa9nvGMk+Nr+0qkc= +github.com/dapr/go-sdk v1.12.0/go.mod h1:RpZJ/pNfODlyk6x+whdtCrFI1/o0X67LCSwZeAZa64U= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -215,8 +215,8 @@ k8s.io/apimachinery v0.31.4 h1:8xjE2C4CzhYVm9DGf60yohpNUh5AEBnPxCryPBECmlM= k8s.io/apimachinery v0.31.4/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= +k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index cc967900eb..5a12e5b4a9 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -9,7 +9,6 @@ package main import ( "context" "fmt" - "io/fs" "net" "os" "os/signal" @@ -18,7 +17,7 @@ import ( "sync" "syscall" "time" - + "encoding/json" "github.com/sirupsen/logrus" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" @@ -44,7 +43,7 @@ import ( healthpb "google.golang.org/grpc/health/grpc_health_v1" "google.golang.org/grpc/reflection" "google.golang.org/grpc/status" - "google.golang.org/protobuf/encoding/protojson" + dapr "github.com/dapr/go-sdk/client" ) @@ -53,38 +52,28 @@ var ( catalog []*pb.Product resource *sdkresource.Resource initResourcesOnce sync.Once + ) const DEFAULT_RELOAD_INTERVAL = 10 const dapr_store = "product-store" type Product_SQL struct { - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - Picture string `protobuf:"bytes,4,opt,name=picture,proto3" json:"picture,omitempty"` - PriceUSCurrencyCode string `protobuf:"bytes,1,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` - // The whole units of the amount. - // For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar. - PriceUSCurrencyCode int64 `protobuf:"varint,2,opt,name=units,proto3" json:"units,omitempty"` - // Number of nano (10^-9) units of the amount. - // The value must be between -999,999,999 and +999,999,999 inclusive. - // If `units` is positive, `nanos` must be positive or zero. - // If `units` is zero, `nanos` can be positive, zero, or negative. - // If `units` is negative, `nanos` must be negative or zero. - // For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000. - PriceUSCurrencyCode int32 `protobuf:"varint,3,opt,name=nanos,proto3" json:"nanos,omitempty" - Categories []string `protobuf:"bytes,6,rep,name=categories,proto3" json:"categories,omitempty"` + Id string + Name string + Description string + Picture string + PriceUSCurrencyCode string + + PriceUSUnits int64 + + PriceUSNano int32 + Categories []string } func init() { log = logrus.New() - client, err := dapr.NewClient() - if err != nil { - log.Fatalf("Cannot create Dapr client : %s", err) - panic(err) - } - defer client.Close() + loadProductCatalog() @@ -241,8 +230,7 @@ func loadProductCatalog() { } }() } -func sendQueryToBackend() ([]*pb.Product, error) -{ +func sendQueryToBackend() ([]*pb.Product, error) { query := `{ "sort": [ @@ -252,78 +240,66 @@ func sendQueryToBackend() ([]*pb.Product, error) } ] }` + client, err := dapr.NewClient() + if err != nil { + log.Fatalf("Cannot create Dapr client : %s", err) + return nil, status.Errorf(codes.Internal, "Cannot create dapr client") + } + defer client.Close() + ctx := context.Background() // Use the client to query the state - queryResponse, err := client.QueryState(ctx, dapr_store, query) + queryResponse, err := client.QueryStateAlpha1(ctx, dapr_store, query,nil) if err != nil { - log.Fatal(err) - st := status.Convert(err) - - log.Fatal("Code: %s\n", st.Code().String()) - log.Fatal("Message: %s\n", st.Message()) - - for _, detail := range st.Details() { - switch t := detail.(type) { - case *errdetails.ErrorInfo: - // Handle ErrorInfo details - log.Fatal("ErrorInfo:\n- Domain: %s\n- Reason: %s\n- Metadata: %v\n", t.GetDomain(), t.GetReason(), t.GetMetadata()) - case *errdetails.BadRequest: - // Handle BadRequest details - fmt.Println("BadRequest:") - for _, violation := range t.GetFieldViolations() { - log.Fatal("- Key: %s\n", violation.GetField()) - log.Fatal("- The %q field was wrong: %s\n", violation.GetField(), violation.GetDescription()) - } - case *errdetails.ResourceInfo: - // Handle ResourceInfo details - log.Fatal("ResourceInfo:\n- Resource type: %s\n- Resource name: %s\n- Owner: %s\n- Description: %s\n", - t.GetResourceType(), t.GetResourceName(), t.GetOwner(), t.GetDescription()) - case *errdetails.Help: - // Handle ResourceInfo details - log.Fatal("HelpInfo:") - for _, link := range t.GetLinks() { - log.Fatal("- Url: %s\n", link.Url) - log.Fatal("- Description: %s\n", link.Description) - } - - default: - // Add cases for other types of details you expect - log.Fatal("Unhandled error detail type: %v\n", t) - } - } + log.Fatalf("DAPR ERROR when sending query: %s",err) + st := status.Convert(err) + + log.Fatalf("DAPR Code: %s\n", st.Code().String()) + log.Fatalf("DAPR Message: %s\n", st.Message()) + return nil, status.Errorf(codes.Internal, st.Message()) } + var products []*pb.Product + + for _, product := range queryResponse.Results { + - for _, product := range queryResponse { - var data Product_SQL - var json; - err := product.Unmarshal(&data) + + var jsonData Product_SQL + err := json.Unmarshal([]byte(product.Value), &jsonData) if err != nil { - log.Fatal("Unhandled error detail type: %v\n", err) - } + return nil, status.Errorf(codes.Internal, "error parsing the data") + } // Now jsonData is a map containing the parsed JSON structure fmt.Println(jsonData) + - products = append(products, pb.Product{ - Id: data.id, - Name: data.name, - Description: data.description, - Picture: data.Picture, - PriceUsd: pb.Money{ - CurrencyCode: data.priceUsd.currencyCode, - Units: data.priceUsd.units, - Nanos: data.priceUsd.nanos - }, - Categories: data.categories + money := pb.Money{ + CurrencyCode: jsonData.PriceUSCurrencyCode, + Units: jsonData.PriceUSUnits, + Nanos: jsonData.PriceUSNano, + } + + products = append(products, &pb.Product{ + Id: jsonData.Id, + Name: jsonData.Name, + Description: jsonData.Description, + Picture: jsonData.Picture, + PriceUsd: &money, + Categories: jsonData.Categories, }) } - log.Infof("Loaded %d products", len(products)) - return products + log.Infof("Loaded x%d products", len(products)) + return products, nil } func readProductFiles() ([]*pb.Product, error) { + var products []*pb.Product + products, err := sendQueryToBackend() + if err != nil { + return nil, status.Errorf(codes.Internal, "impossible to getproducts from storage") + + } - products = sendQueryToBackend() - log.Infof("Loaded %d products", len(products)) return products, nil } From dca7822cfb67cdb76d34121de74a587e0c3fea96 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Wed, 9 Apr 2025 15:30:28 +0200 Subject: [PATCH 36/60] add go tidy in Dockerfile --- src/product-catalog/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/product-catalog/Dockerfile b/src/product-catalog/Dockerfile index a13aafb9bb..46b19bfdb2 100644 --- a/src/product-catalog/Dockerfile +++ b/src/product-catalog/Dockerfile @@ -11,6 +11,8 @@ RUN --mount=type=cache,target=/go/pkg/mod/ \ --mount=type=bind,source=./src/product-catalog/go.mod,target=go.mod \ go mod download +RUN go mod tidy + RUN --mount=type=cache,target=/go/pkg/mod/ \ --mount=type=cache,target=/root/.cache/go-build \ --mount=type=bind,rw,source=./src/product-catalog,target=. \ From bf7ad13adc9a389459b1f49fa45ed4dabc00498a Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Wed, 9 Apr 2025 19:04:13 +0200 Subject: [PATCH 37/60] update go version in the dockerfile --- src/product-catalog/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/product-catalog/Dockerfile b/src/product-catalog/Dockerfile index 46b19bfdb2..f7a38fc32d 100644 --- a/src/product-catalog/Dockerfile +++ b/src/product-catalog/Dockerfile @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 -FROM golang:1.22-alpine AS builder +FROM golang:1.23-alpine AS builder WORKDIR /usr/src/app/ From 940455eb74c528dfc0692fbb9043601cc1eab8d2 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Wed, 9 Apr 2025 19:08:13 +0200 Subject: [PATCH 38/60] update go version in the dockerfile --- src/product-catalog/Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/product-catalog/Dockerfile b/src/product-catalog/Dockerfile index f7a38fc32d..5d78cd9c80 100644 --- a/src/product-catalog/Dockerfile +++ b/src/product-catalog/Dockerfile @@ -11,7 +11,10 @@ RUN --mount=type=cache,target=/go/pkg/mod/ \ --mount=type=bind,source=./src/product-catalog/go.mod,target=go.mod \ go mod download -RUN go mod tidy +RUN --mount=type=cache,target=/go/pkg/mod/ \ + --mount=type=bind,source=./src/product-catalog/go.sum,target=go.sum \ + --mount=type=bind,source=./src/product-catalog/go.mod,target=go.mod \ + go mod tidy RUN --mount=type=cache,target=/go/pkg/mod/ \ --mount=type=cache,target=/root/.cache/go-build \ From e067f45afd163ca9cc3ca6d370841818f62d0e3d Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Wed, 9 Apr 2025 19:08:53 +0200 Subject: [PATCH 39/60] update go version in the dockerfile --- src/product-catalog/Dockerfile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/product-catalog/Dockerfile b/src/product-catalog/Dockerfile index 5d78cd9c80..e5c042bfe1 100644 --- a/src/product-catalog/Dockerfile +++ b/src/product-catalog/Dockerfile @@ -11,10 +11,7 @@ RUN --mount=type=cache,target=/go/pkg/mod/ \ --mount=type=bind,source=./src/product-catalog/go.mod,target=go.mod \ go mod download -RUN --mount=type=cache,target=/go/pkg/mod/ \ - --mount=type=bind,source=./src/product-catalog/go.sum,target=go.sum \ - --mount=type=bind,source=./src/product-catalog/go.mod,target=go.mod \ - go mod tidy + RUN --mount=type=cache,target=/go/pkg/mod/ \ --mount=type=cache,target=/root/.cache/go-build \ From a042aca9ad640876ec8d8160f0e7b2b3e4124bbf Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Thu, 10 Apr 2025 15:47:41 +0200 Subject: [PATCH 40/60] change datamodel of the sql database to mach with stat api of DAPR. --- dapr/components/product-store.yaml | 2 +- src/postgresql/product/init.sql | 176 +++++++++++++++++++++++++---- src/product-catalog/main.go | 36 +----- 3 files changed, 158 insertions(+), 56 deletions(-) diff --git a/dapr/components/product-store.yaml b/dapr/components/product-store.yaml index 7509a490f0..119d02e424 100644 --- a/dapr/components/product-store.yaml +++ b/dapr/components/product-store.yaml @@ -9,4 +9,4 @@ spec: - name: connectionString value: "host=product_db user=postgres password=example port=5432 connect_timeout=10 database=postgres" - name: tableName - value: "product" \ No newline at end of file + value: "productstate" \ No newline at end of file diff --git a/src/postgresql/product/init.sql b/src/postgresql/product/init.sql index f3e2bc4fe9..2479a4b32a 100644 --- a/src/postgresql/product/init.sql +++ b/src/postgresql/product/init.sql @@ -1,25 +1,157 @@ -DROP TABLE IF EXISTS "product"; - -CREATE TABLE "product" ( - "id" VARCHAR(512), - "name" VARCHAR(512), - "description" VARCHAR(512), + DROP TABLE IF EXISTS "product"; + DROP TABLE IF EXISTS "productstate"; + CREATE TABLE "product" ( + "id" VARCHAR(20), + "name" VARCHAR(100), + "description" VARCHAR(1000), "picture" VARCHAR(512), - "priceUsd.currencyCode" VARCHAR(512), - "priceUsd.units" VARCHAR(512), - "priceUsd.nanos" INT, - "categories" VARCHAR(512) -); + "priceusdcurrencycode" VARCHAR(512), + "priceusdunits" VARCHAR(512), + "priceusdnanos" INT, + "categories" VARCHAR(1000) + ); + + INSERT INTO "product" ("id", "name", "description", "picture", "priceusdcurrencycode", "priceusdunits", "priceusdnanos", "categories") VALUES + ('OLJCESPC7Z', 'National Park Foundation Explorascope', 'The National Park Foundation’s (NPF) Explorascope 60AZ is a manual alt-azimuth, refractor telescope perfect for celestial viewing on the go. The NPF Explorascope 60 can view the planets, moon, star clusters and brighter deep sky objects like the Orion Nebula and Andromeda Galaxy.', 'NationalParkFoundationExplorascope.jpg', 'USD', '101', '960000000', 'telescopes'), + ('66VCHSJNUP', 'Starsense Explorer Refractor Telescope', 'The first telescope that uses your smartphone to analyze the night sky and calculate its position in real time. StarSense Explorer is ideal for beginners thanks to the app’s user-friendly interface and detailed tutorials. It’s like having your own personal tour guide of the night sky', 'StarsenseExplorer.jpg', 'USD', '349', '950000000', 'telescopes'), + ('1YMWWN1N4O', 'Eclipsmart Travel Refractor Telescope', 'Dedicated white-light solar scope for the observer on the go. The 50mm refracting solar scope uses Solar Safe, ISO compliant, full-aperture glass filter material to ensure the safest view of solar events. The kit comes complete with everything you need, including the dedicated travel solar scope, a Solar Safe finderscope, tripod, a high quality 20mm (18x) Kellner eyepiece and a nylon backpack to carry everything in. This Travel Solar Scope makes it easy to share the Sun as well as partial and total solar eclipses with the whole family and offers much higher magnifications than you would otherwise get using handheld solar viewers or binoculars.', 'EclipsmartTravelRefractorTelescope.jpg', 'USD', '129', '950000000', 'telescopes,travel'), + ('L9ECAV7KIM', 'Lens Cleaning Kit', 'Wipe away dust, dirt, fingerprints and other particles on your lenses to see clearly with the Lens Cleaning Kit. This cleaning kit works on all glass and optical surfaces, including telescopes, binoculars, spotting scopes, monoculars, microscopes, and even your camera lenses, computer screens, and mobile devices. The kit comes complete with a retractable lens brush to remove dust particles and dirt and two options to clean smudges and fingerprints off of your optics, pre-moistened lens wipes and a bottled lens cleaning fluid with soft cloth.', 'LensCleaningKit.jpg', 'USD', '21', '950000000', 'accessories'), + ('2ZYFJ3GM2N', 'Roof Binoculars', 'This versatile, all-around binocular is a great choice for the trail, the stadium, the arena, or just about anywhere you want a close-up view of the action without sacrificing brightness or detail. It’s an especially great companion for nature observation and bird watching, with ED glass that helps you spot the subtlest field markings and a close focus of just 6.5 feet.', 'RoofBinoculars.jpg', 'USD', '209', '950000000', 'binoculars'), + ('0PUK6V6EV0', 'Solar System Color Imager', 'You have your new telescope and have observed Saturn and Jupiter. Now you are ready to take the next step and start imaging them. But where do you begin? The NexImage 10 Solar System Imager is the perfect solution.', 'SolarSystemColorImager.jpg', 'USD', '175', '0', 'accessories,telescopes'), + ('LS4PSXUNUM', 'Red Flashlight', 'This 3-in-1 device features a 3-mode red flashlight, a hand warmer, and a portable power bank for recharging your personal electronics on the go. Whether you use it to light the way at an astronomy star party, a night walk, or wildlife research, ThermoTorch 3 Astro Red’s rugged, IPX4-rated design will withstand your everyday activities.', 'RedFlashlight.jpg', 'USD', '57', '80000000', 'accessories,flashlights'), + ('9SIQT8TOJO', 'Optical Tube Assembly', 'Capturing impressive deep-sky astroimages is easier than ever with Rowe-Ackermann Schmidt Astrograph (RASA) V2, the perfect companion to today’s top DSLR or astronomical CCD cameras. This fast, wide-field f/2.2 system allows for shorter exposure times compared to traditional f/10 astroimaging, without sacrificing resolution. Because shorter sub-exposure times are possible, your equatorial mount won’t need to accurately track over extended periods. The short focal length also lessens equatorial tracking demands. In many cases, autoguiding will not be required.', 'OpticalTubeAssembly.jpg', 'USD', '3599', '0', 'accessories,telescopes,assembly'), + ('6E92ZMYYFZ', 'Solar Filter', 'Enhance your viewing experience with EclipSmart Solar Filter for 8” telescopes. With two Velcro straps and four self-adhesive Velcro pads for added safety, you can be assured that the solar filter cannot be accidentally knocked off and will provide Solar Safe, ISO compliant viewing.', 'SolarFilter.jpg', 'USD', '69', '950000000', 'accessories,telescopes'), + ('HQTGWGPNH4', 'The Comet Book', 'A 16th-century treatise on comets, created anonymously in Flanders (now northern France) and now held at the Universitätsbibliothek Kassel. Commonly known as The Comet Book (or Kometenbuch in German), its full title translates as “Comets and their General and Particular Meanings, According to Ptolomeé, Albumasar, Haly, Aliquind and other Astrologers”. The image is from https://publicdomainreview.org/collection/the-comet-book, made available by the Universitätsbibliothek Kassel under a CC-BY SA 4.0 license (https://creativecommons.org/licenses/by-sa/4.0/)', 'TheCometBook.jpg', 'USD', '0', '990000000', 'books'); + + CREATE VIEW state AS + SELECT f.id AS key , f.id as etag, json_build_object('Id', json_agg(f.id),'Name', json_agg(f.name),'Picture',json_agg(f.picture),'PriceUSCurrencyCode',json_agg(f.priceusdcurrencycode), 'PriceUSUnits', json_agg(f.priceusdunits), 'PriceUSNano', json_agg(f.priceusdnanos), 'Categories', json_agg(f.categories)) AS value + FROM product f GROUP BY f.id; + + CREATE TABLE "productstate" ( + "key" VARCHAR(20), + "value" jsonb + ); + -INSERT INTO "product" ("id", "name", "description", "picture", "priceUsd.currencyCode", "priceUsd.units", "priceUsd.nanos", "categories") VALUES - ('OLJCESPC7Z', 'National Park Foundation Explorascope', 'The National Park Foundation’s (NPF) Explorascope 60AZ is a manual alt-azimuth, refractor telescope perfect for celestial viewing on the go. The NPF Explorascope 60 can view the planets, moon, star clusters and brighter deep sky objects like the Orion Nebula and Andromeda Galaxy.', 'NationalParkFoundationExplorascope.jpg', 'USD', '101', '960000000', 'telescopes'), - ('66VCHSJNUP', 'Starsense Explorer Refractor Telescope', 'The first telescope that uses your smartphone to analyze the night sky and calculate its position in real time. StarSense Explorer is ideal for beginners thanks to the app’s user-friendly interface and detailed tutorials. It’s like having your own personal tour guide of the night sky', 'StarsenseExplorer.jpg', 'USD', '349', '950000000', 'telescopes'), - ('1YMWWN1N4O', 'Eclipsmart Travel Refractor Telescope', 'Dedicated white-light solar scope for the observer on the go. The 50mm refracting solar scope uses Solar Safe, ISO compliant, full-aperture glass filter material to ensure the safest view of solar events. The kit comes complete with everything you need, including the dedicated travel solar scope, a Solar Safe finderscope, tripod, a high quality 20mm (18x) Kellner eyepiece and a nylon backpack to carry everything in. This Travel Solar Scope makes it easy to share the Sun as well as partial and total solar eclipses with the whole family and offers much higher magnifications than you would otherwise get using handheld solar viewers or binoculars.', 'EclipsmartTravelRefractorTelescope.jpg', 'USD', '129', '950000000', 'telescopes,travel'), - ('L9ECAV7KIM', 'Lens Cleaning Kit', 'Wipe away dust, dirt, fingerprints and other particles on your lenses to see clearly with the Lens Cleaning Kit. This cleaning kit works on all glass and optical surfaces, including telescopes, binoculars, spotting scopes, monoculars, microscopes, and even your camera lenses, computer screens, and mobile devices. The kit comes complete with a retractable lens brush to remove dust particles and dirt and two options to clean smudges and fingerprints off of your optics, pre-moistened lens wipes and a bottled lens cleaning fluid with soft cloth.', 'LensCleaningKit.jpg', 'USD', '21', '950000000', 'accessories'), - ('2ZYFJ3GM2N', 'Roof Binoculars', 'This versatile, all-around binocular is a great choice for the trail, the stadium, the arena, or just about anywhere you want a close-up view of the action without sacrificing brightness or detail. It’s an especially great companion for nature observation and bird watching, with ED glass that helps you spot the subtlest field markings and a close focus of just 6.5 feet.', 'RoofBinoculars.jpg', 'USD', '209', '950000000', 'binoculars'), - ('0PUK6V6EV0', 'Solar System Color Imager', 'You have your new telescope and have observed Saturn and Jupiter. Now you\'re ready to take the next step and start imaging them. But where do you begin? The NexImage 10 Solar System Imager is the perfect solution.', 'SolarSystemColorImager.jpg', 'USD', '175', '0', 'accessories,telescopes'), - ('LS4PSXUNUM', 'Red Flashlight', 'This 3-in-1 device features a 3-mode red flashlight, a hand warmer, and a portable power bank for recharging your personal electronics on the go. Whether you use it to light the way at an astronomy star party, a night walk, or wildlife research, ThermoTorch 3 Astro Red’s rugged, IPX4-rated design will withstand your everyday activities.', 'RedFlashlight.jpg', 'USD', '57', '80000000', 'accessories,flashlights'), - ('9SIQT8TOJO', 'Optical Tube Assembly', 'Capturing impressive deep-sky astroimages is easier than ever with Rowe-Ackermann Schmidt Astrograph (RASA) V2, the perfect companion to today’s top DSLR or astronomical CCD cameras. This fast, wide-field f/2.2 system allows for shorter exposure times compared to traditional f/10 astroimaging, without sacrificing resolution. Because shorter sub-exposure times are possible, your equatorial mount won’t need to accurately track over extended periods. The short focal length also lessens equatorial tracking demands. In many cases, autoguiding will not be required.', 'OpticalTubeAssembly.jpg', 'USD', '3599', '0', 'accessories,telescopes,assembly'), - ('6E92ZMYYFZ', 'Solar Filter', 'Enhance your viewing experience with EclipSmart Solar Filter for 8” telescopes. With two Velcro straps and four self-adhesive Velcro pads for added safety, you can be assured that the solar filter cannot be accidentally knocked off and will provide Solar Safe, ISO compliant viewing.', 'SolarFilter.jpg', 'USD', '69', '950000000', 'accessories,telescopes'), - ('HQTGWGPNH4', 'The Comet Book', 'A 16th-century treatise on comets, created anonymously in Flanders (now northern France) and now held at the Universitätsbibliothek Kassel. Commonly known as The Comet Book (or Kometenbuch in German), its full title translates as “Comets and their General and Particular Meanings, According to Ptolomeé, Albumasar, Haly, Aliquind and other Astrologers”. The image is from https://publicdomainreview.org/collection/the-comet-book, made available by the Universitätsbibliothek Kassel under a CC-BY SA 4.0 license (https://creativecommons.org/licenses/by-sa/4.0/)', 'TheCometBook.jpg', 'USD', '0', '990000000', 'books'); \ No newline at end of file + INSERT INTO "productstate" ("key", "value") VALUES + ('OLJCESPC7Z', '{ + "id": "OLJCESPC7Z", + "name": "National Park Foundation Explorascope", + "description": "The National Park Foundation’s (NPF) Explorascope 60AZ is a manual alt-azimuth, refractor telescope perfect for celestial viewing on the go. The NPF Explorascope 60 can view the planets, moon, star clusters and brighter deep sky objects like the Orion Nebula and Andromeda Galaxy.", + "picture": "NationalParkFoundationExplorascope.jpg", + "priceUsd": { + "currencyCode": "USD", + "units": 101, + "nanos": 960000000 + }, + "categories": ["telescopes"] + }'), + ('66VCHSJNUP', '{ + "id": "66VCHSJNUP", + "name": "Starsense Explorer Refractor Telescope", + "description": "The first telescope that uses your smartphone to analyze the night sky and calculate its position in real time. StarSense Explorer is ideal for beginners thanks to the app’s user-friendly interface and detailed tutorials. It’s like having your own personal tour guide of the night sky", + "picture": "StarsenseExplorer.jpg", + "priceUsd": { + "currencyCode": "USD", + "units": 349, + "nanos": 950000000 + }, + "categories": ["telescopes"] + }'), + ('1YMWWN1N4O', '{ + "id": "1YMWWN1N4O", + "name": "Eclipsmart Travel Refractor Telescope", + "description": "Dedicated white-light solar scope for the observer on the go. The 50mm refracting solar scope uses Solar Safe, ISO compliant, full-aperture glass filter material to ensure the safest view of solar events. The kit comes complete with everything you need, including the dedicated travel solar scope, a Solar Safe finderscope, tripod, a high quality 20mm (18x) Kellner eyepiece and a nylon backpack to carry everything in. This Travel Solar Scope makes it easy to share the Sun as well as partial and total solar eclipses with the whole family and offers much higher magnifications than you would otherwise get using handheld solar viewers or binoculars.", + "picture": "EclipsmartTravelRefractorTelescope.jpg", + "priceUsd": { + "currencyCode": "USD", + "units": 129, + "nanos": 950000000 + }, + "categories": ["telescopes", "travel"] + }'), + ('L9ECAV7KIM', '{ + "id": "L9ECAV7KIM", + "name": "Lens Cleaning Kit", + "description": "Wipe away dust, dirt, fingerprints and other particles on your lenses to see clearly with the Lens Cleaning Kit. This cleaning kit works on all glass and optical surfaces, including telescopes, binoculars, spotting scopes, monoculars, microscopes, and even your camera lenses, computer screens, and mobile devices. The kit comes complete with a retractable lens brush to remove dust particles and dirt and two options to clean smudges and fingerprints off of your optics, pre-moistened lens wipes and a bottled lens cleaning fluid with soft cloth.", + "picture": "LensCleaningKit.jpg", + "priceUsd": { + "currencyCode": "USD", + "units": 21, + "nanos": 950000000 + }, + "categories": ["accessories"] + }'), + ('2ZYFJ3GM2N', '{ + "id": "2ZYFJ3GM2N", + "name": "Roof Binoculars", + "description": "This versatile, all-around binocular is a great choice for the trail, the stadium, the arena, or just about anywhere you want a close-up view of the action without sacrificing brightness or detail. It’s an especially great companion for nature observation and bird watching, with ED glass that helps you spot the subtlest field markings and a close focus of just 6.5 feet.", + "picture": "RoofBinoculars.jpg", + "priceUsd": { + "currencyCode": "USD", + "units": 209, + "nanos": 950000000 + }, + "categories": ["binoculars"] + }'), + ('0PUK6V6EV0', '{ + "id": "0PUK6V6EV0", + "name": "Solar System Color Imager", + "description": "You have your new telescope and have observed Saturn and Jupiter. Now you are ready to take the next step and start imaging them. But where do you begin? The NexImage 10 Solar System Imager is the perfect solution.", + "picture": "SolarSystemColorImager.jpg", + "priceUsd": { + "currencyCode": "USD", + "units": 175, + "nanos": 0 + }, + "categories": ["accessories", "telescopes"] + }'), + ('LS4PSXUNUM', '{ + "id": "LS4PSXUNUM", + "name": "Red Flashlight", + "description": "This 3-in-1 device features a 3-mode red flashlight, a hand warmer, and a portable power bank for recharging your personal electronics on the go. Whether you use it to light the way at an astronomy star party, a night walk, or wildlife research, ThermoTorch 3 Astro Red’s rugged, IPX4-rated design will withstand your everyday activities.", + "picture": "RedFlashlight.jpg", + "priceUsd": { + "currencyCode": "USD", + "units": 57, + "nanos": 80000000 + }, + "categories": ["accessories", "flashlights"] + }'), + ('9SIQT8TOJO', '{ + "id": "9SIQT8TOJO", + "name": "Optical Tube Assembly", + "description": "Capturing impressive deep-sky astroimages is easier than ever with Rowe-Ackermann Schmidt Astrograph (RASA) V2, the perfect companion to today’s top DSLR or astronomical CCD cameras. This fast, wide-field f/2.2 system allows for shorter exposure times compared to traditional f/10 astroimaging, without sacrificing resolution. Because shorter sub-exposure times are possible, your equatorial mount won’t need to accurately track over extended periods. The short focal length also lessens equatorial tracking demands. In many cases, autoguiding will not be required.", + "picture": "OpticalTubeAssembly.jpg", + "priceUsd": { + "currencyCode": "USD", + "units": 3599, + "nanos": 0 + }, + "categories": ["accessories", "telescopes", "assembly"] + }'), + ('6E92ZMYYFZ', '{ + "id": "6E92ZMYYFZ", + "name": "Solar Filter", + "description": "Enhance your viewing experience with EclipSmart Solar Filter for 8” telescopes. With two Velcro straps and four self-adhesive Velcro pads for added safety, you can be assured that the solar filter cannot be accidentally knocked off and will provide Solar Safe, ISO compliant viewing.", + "picture": "SolarFilter.jpg", + "priceUsd": { + "currencyCode": "USD", + "units": 69, + "nanos": 950000000 + }, + "categories": ["accessories", "telescopes"] + }'), + ('HQTGWGPNH4', '{ + "id": "HQTGWGPNH4", + "name": "The Comet Book", + "description": "A 16th-century treatise on comets, created anonymously in Flanders (now northern France) and now held at the Universitätsbibliothek Kassel. Commonly known as The Comet Book (or Kometenbuch in German), its full title translates as “Comets and their General and Particular Meanings, According to Ptolomeé, Albumasar, Haly, Aliquind and other Astrologers”. The image is from https://publicdomainreview.org/collection/the-comet-book, made available by the Universitätsbibliothek Kassel under a CC-BY SA 4.0 license (https://creativecommons.org/licenses/by-sa/4.0/)", + "picture": "TheCometBook.jpg", + "priceUsd": { + "currencyCode": "USD", + "units": 0, + "nanos": 990000000 + }, + "categories": ["books"] + }'); \ No newline at end of file diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index 5a12e5b4a9..77e11dac72 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -57,19 +57,7 @@ var ( const DEFAULT_RELOAD_INTERVAL = 10 const dapr_store = "product-store" -type Product_SQL struct { - Id string - Name string - Description string - Picture string - PriceUSCurrencyCode string - PriceUSUnits int64 - - PriceUSNano int32 - Categories []string - -} func init() { log = logrus.New() @@ -235,7 +223,7 @@ func sendQueryToBackend() ([]*pb.Product, error) { "sort": [ { - "key": "name", + "key": "key", "order": "ASC" } ] @@ -261,31 +249,13 @@ func sendQueryToBackend() ([]*pb.Product, error) { for _, product := range queryResponse.Results { - - - - var jsonData Product_SQL + var jsonData pb.Product err := json.Unmarshal([]byte(product.Value), &jsonData) if err != nil { return nil, status.Errorf(codes.Internal, "error parsing the data") } // Now jsonData is a map containing the parsed JSON structure fmt.Println(jsonData) - - money := pb.Money{ - CurrencyCode: jsonData.PriceUSCurrencyCode, - Units: jsonData.PriceUSUnits, - Nanos: jsonData.PriceUSNano, - } - - products = append(products, &pb.Product{ - Id: jsonData.Id, - Name: jsonData.Name, - Description: jsonData.Description, - Picture: jsonData.Picture, - PriceUsd: &money, - Categories: jsonData.Categories, - - }) + products = append(products, product) } log.Infof("Loaded x%d products", len(products)) return products, nil From c2b754d910363c523e27c1ffc7755545f34d900a Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Thu, 10 Apr 2025 15:56:41 +0200 Subject: [PATCH 41/60] resolve compilation issue --- src/product-catalog/main.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index 77e11dac72..7c5b14afa7 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -249,13 +249,19 @@ func sendQueryToBackend() ([]*pb.Product, error) { for _, product := range queryResponse.Results { + + + var jsonData pb.Product err := json.Unmarshal([]byte(product.Value), &jsonData) if err != nil { return nil, status.Errorf(codes.Internal, "error parsing the data") } // Now jsonData is a map containing the parsed JSON structure fmt.Println(jsonData) - products = append(products, product) + + + + products = append(products, &jsonData) } log.Infof("Loaded x%d products", len(products)) return products, nil From 5dc1487c1dafcc33448a4913cf9fead3326e7b1e Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Thu, 10 Apr 2025 16:32:00 +0200 Subject: [PATCH 42/60] update the dapr query --- src/product-catalog/main.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index 7c5b14afa7..20332ee825 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -221,12 +221,6 @@ func loadProductCatalog() { func sendQueryToBackend() ([]*pb.Product, error) { query := `{ - "sort": [ - { - "key": "key", - "order": "ASC" - } - ] }` client, err := dapr.NewClient() if err != nil { From 4f96896138cb1b7da8b21175d913468a21d96f1e Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 14 Apr 2025 10:26:27 +0200 Subject: [PATCH 43/60] dapr runtime error --- src/product-catalog/main.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index 20332ee825..189d043ab5 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -52,7 +52,8 @@ var ( catalog []*pb.Product resource *sdkresource.Resource initResourcesOnce sync.Once - + client dapr.Client + daprerror error ) const DEFAULT_RELOAD_INTERVAL = 10 @@ -64,6 +65,7 @@ func init() { + loadProductCatalog() } @@ -117,6 +119,13 @@ func initMeterProvider() *sdkmetric.MeterProvider { } func main() { + + client, daprerror = dapr.NewClient() + if daprerror != nil { + log.Fatalf("Cannot create Dapr client : %s", daprerror) + + } + tp := initTracerProvider() defer func() { if err := tp.Shutdown(context.Background()); err != nil { @@ -222,12 +231,7 @@ func sendQueryToBackend() ([]*pb.Product, error) { query := `{ }` - client, err := dapr.NewClient() - if err != nil { - log.Fatalf("Cannot create Dapr client : %s", err) - return nil, status.Errorf(codes.Internal, "Cannot create dapr client") - } - defer client.Close() + ctx := context.Background() // Use the client to query the state queryResponse, err := client.QueryStateAlpha1(ctx, dapr_store, query,nil) From ad54dd97405781981930c248f3b690dce3c83883 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 14 Apr 2025 11:02:52 +0200 Subject: [PATCH 44/60] dapr runtime error --- src/product-catalog/main.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index 189d043ab5..15ad32b3ef 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -62,10 +62,11 @@ const dapr_store = "product-store" func init() { log = logrus.New() + client, daprerror = dapr.NewClient() + if daprerror != nil { + log.Fatalf("Cannot create Dapr client : %s", daprerror) - - - + } loadProductCatalog() } @@ -120,11 +121,7 @@ func initMeterProvider() *sdkmetric.MeterProvider { func main() { - client, daprerror = dapr.NewClient() - if daprerror != nil { - log.Fatalf("Cannot create Dapr client : %s", daprerror) - } tp := initTracerProvider() defer func() { From 8f4a3123e44521c03cd81ca87a19eac85759359a Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 14 Apr 2025 14:15:56 +0200 Subject: [PATCH 45/60] add logging for debuggin price issue --- src/product-catalog/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index 15ad32b3ef..6206082f09 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -246,7 +246,6 @@ func sendQueryToBackend() ([]*pb.Product, error) { - var jsonData pb.Product err := json.Unmarshal([]byte(product.Value), &jsonData) if err != nil { @@ -254,6 +253,7 @@ func sendQueryToBackend() ([]*pb.Product, error) { } // Now jsonData is a map containing the parsed JSON structure fmt.Println(jsonData) + log.Infof("Found the following product %s", string(product.Value)) products = append(products, &jsonData) From ac3edf0d63160d6c8d91ba7cf06014f2d32aa7b4 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 14 Apr 2025 14:30:10 +0200 Subject: [PATCH 46/60] changing Unmarshal method --- src/product-catalog/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index 6206082f09..575436abea 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -17,7 +17,6 @@ import ( "sync" "syscall" "time" - "encoding/json" "github.com/sirupsen/logrus" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" @@ -43,6 +42,7 @@ import ( healthpb "google.golang.org/grpc/health/grpc_health_v1" "google.golang.org/grpc/reflection" "google.golang.org/grpc/status" + "google.golang.org/protobuf/encoding/protojson" dapr "github.com/dapr/go-sdk/client" ) @@ -247,7 +247,7 @@ func sendQueryToBackend() ([]*pb.Product, error) { var jsonData pb.Product - err := json.Unmarshal([]byte(product.Value), &jsonData) + err := protojson.Unmarshal([]byte(product.Value), &jsonData) if err != nil { return nil, status.Errorf(codes.Internal, "error parsing the data") } // Now jsonData is a map containing the parsed JSON structure fmt.Println(jsonData) From 7774366b57cba877dc99ab95fc3cd5eb2950c0c2 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 14 Apr 2025 14:53:06 +0200 Subject: [PATCH 47/60] checking the parsing of the Money --- src/product-catalog/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index 575436abea..a6fdde7190 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -255,7 +255,7 @@ func sendQueryToBackend() ([]*pb.Product, error) { log.Infof("Found the following product %s", string(product.Value)) - + log.Infof("Currency of the product %d", jsonData.PriceUsd.CurrencyCode) products = append(products, &jsonData) } log.Infof("Loaded x%d products", len(products)) From 2e742ebcd93c6381831c9a7397ab87269740c46b Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 14 Apr 2025 15:52:00 +0200 Subject: [PATCH 48/60] add change log and removed the produc.json file from the product-catalog --- CHANGELOG.md | 6 + src/product-catalog/main.go | 5 - src/product-catalog/products/products.json | 124 --------------------- 3 files changed, 6 insertions(+), 129 deletions(-) delete mode 100644 src/product-catalog/products/products.json diff --git a/CHANGELOG.md b/CHANGELOG.md index e1e3bab0f9..30231f4a39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ the release. ## Unreleased +## 2.0.3 + +* [product catalog] removed the usage on the json file , repalced it with a Dapr client +* [sqllit] dropped the sqllite , because no support for dapr query +* [postgresl] added postgresql to add a storage of the product catalog ( default database used by dapr) + ## 2.0.2 * [frontend] Update OpenTelemetry Browser SDK initialization diff --git a/src/product-catalog/main.go b/src/product-catalog/main.go index a6fdde7190..3d5eda102e 100644 --- a/src/product-catalog/main.go +++ b/src/product-catalog/main.go @@ -251,11 +251,6 @@ func sendQueryToBackend() ([]*pb.Product, error) { if err != nil { return nil, status.Errorf(codes.Internal, "error parsing the data") } // Now jsonData is a map containing the parsed JSON structure fmt.Println(jsonData) - - - log.Infof("Found the following product %s", string(product.Value)) - - log.Infof("Currency of the product %d", jsonData.PriceUsd.CurrencyCode) products = append(products, &jsonData) } log.Infof("Loaded x%d products", len(products)) diff --git a/src/product-catalog/products/products.json b/src/product-catalog/products/products.json deleted file mode 100644 index b7d27b06ed..0000000000 --- a/src/product-catalog/products/products.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "products": [ - { - "id": "OLJCESPC7Z", - "name": "National Park Foundation Explorascope", - "description": "The National Park Foundation’s (NPF) Explorascope 60AZ is a manual alt-azimuth, refractor telescope perfect for celestial viewing on the go. The NPF Explorascope 60 can view the planets, moon, star clusters and brighter deep sky objects like the Orion Nebula and Andromeda Galaxy.", - "picture": "NationalParkFoundationExplorascope.jpg", - "priceUsd": { - "currencyCode": "USD", - "units": 101, - "nanos": 960000000 - }, - "categories": ["telescopes"] - }, - { - "id": "66VCHSJNUP", - "name": "Starsense Explorer Refractor Telescope", - "description": "The first telescope that uses your smartphone to analyze the night sky and calculate its position in real time. StarSense Explorer is ideal for beginners thanks to the app’s user-friendly interface and detailed tutorials. It’s like having your own personal tour guide of the night sky", - "picture": "StarsenseExplorer.jpg", - "priceUsd": { - "currencyCode": "USD", - "units": 349, - "nanos": 950000000 - }, - "categories": ["telescopes"] - }, - { - "id": "1YMWWN1N4O", - "name": "Eclipsmart Travel Refractor Telescope", - "description": "Dedicated white-light solar scope for the observer on the go. The 50mm refracting solar scope uses Solar Safe, ISO compliant, full-aperture glass filter material to ensure the safest view of solar events. The kit comes complete with everything you need, including the dedicated travel solar scope, a Solar Safe finderscope, tripod, a high quality 20mm (18x) Kellner eyepiece and a nylon backpack to carry everything in. This Travel Solar Scope makes it easy to share the Sun as well as partial and total solar eclipses with the whole family and offers much higher magnifications than you would otherwise get using handheld solar viewers or binoculars.", - "picture": "EclipsmartTravelRefractorTelescope.jpg", - "priceUsd": { - "currencyCode": "USD", - "units": 129, - "nanos": 950000000 - }, - "categories": ["telescopes", "travel"] - }, - { - "id": "L9ECAV7KIM", - "name": "Lens Cleaning Kit", - "description": "Wipe away dust, dirt, fingerprints and other particles on your lenses to see clearly with the Lens Cleaning Kit. This cleaning kit works on all glass and optical surfaces, including telescopes, binoculars, spotting scopes, monoculars, microscopes, and even your camera lenses, computer screens, and mobile devices. The kit comes complete with a retractable lens brush to remove dust particles and dirt and two options to clean smudges and fingerprints off of your optics, pre-moistened lens wipes and a bottled lens cleaning fluid with soft cloth.", - "picture": "LensCleaningKit.jpg", - "priceUsd": { - "currencyCode": "USD", - "units": 21, - "nanos": 950000000 - }, - "categories": ["accessories"] - }, - { - "id": "2ZYFJ3GM2N", - "name": "Roof Binoculars", - "description": "This versatile, all-around binocular is a great choice for the trail, the stadium, the arena, or just about anywhere you want a close-up view of the action without sacrificing brightness or detail. It’s an especially great companion for nature observation and bird watching, with ED glass that helps you spot the subtlest field markings and a close focus of just 6.5 feet.", - "picture": "RoofBinoculars.jpg", - "priceUsd": { - "currencyCode": "USD", - "units": 209, - "nanos": 950000000 - }, - "categories": ["binoculars"] - }, - { - "id": "0PUK6V6EV0", - "name": "Solar System Color Imager", - "description": "You have your new telescope and have observed Saturn and Jupiter. Now you're ready to take the next step and start imaging them. But where do you begin? The NexImage 10 Solar System Imager is the perfect solution.", - "picture": "SolarSystemColorImager.jpg", - "priceUsd": { - "currencyCode": "USD", - "units": 175, - "nanos": 0 - }, - "categories": ["accessories", "telescopes"] - }, - { - "id": "LS4PSXUNUM", - "name": "Red Flashlight", - "description": "This 3-in-1 device features a 3-mode red flashlight, a hand warmer, and a portable power bank for recharging your personal electronics on the go. Whether you use it to light the way at an astronomy star party, a night walk, or wildlife research, ThermoTorch 3 Astro Red’s rugged, IPX4-rated design will withstand your everyday activities.", - "picture": "RedFlashlight.jpg", - "priceUsd": { - "currencyCode": "USD", - "units": 57, - "nanos": 80000000 - }, - "categories": ["accessories", "flashlights"] - }, - { - "id": "9SIQT8TOJO", - "name": "Optical Tube Assembly", - "description": "Capturing impressive deep-sky astroimages is easier than ever with Rowe-Ackermann Schmidt Astrograph (RASA) V2, the perfect companion to today’s top DSLR or astronomical CCD cameras. This fast, wide-field f/2.2 system allows for shorter exposure times compared to traditional f/10 astroimaging, without sacrificing resolution. Because shorter sub-exposure times are possible, your equatorial mount won’t need to accurately track over extended periods. The short focal length also lessens equatorial tracking demands. In many cases, autoguiding will not be required.", - "picture": "OpticalTubeAssembly.jpg", - "priceUsd": { - "currencyCode": "USD", - "units": 3599, - "nanos": 0 - }, - "categories": ["accessories", "telescopes", "assembly"] - }, - { - "id": "6E92ZMYYFZ", - "name": "Solar Filter", - "description": "Enhance your viewing experience with EclipSmart Solar Filter for 8” telescopes. With two Velcro straps and four self-adhesive Velcro pads for added safety, you can be assured that the solar filter cannot be accidentally knocked off and will provide Solar Safe, ISO compliant viewing.", - "picture": "SolarFilter.jpg", - "priceUsd": { - "currencyCode": "USD", - "units": 69, - "nanos": 950000000 - }, - "categories": ["accessories", "telescopes"] - }, - { - "id": "HQTGWGPNH4", - "name": "The Comet Book", - "description": "A 16th-century treatise on comets, created anonymously in Flanders (now northern France) and now held at the Universitätsbibliothek Kassel. Commonly known as The Comet Book (or Kometenbuch in German), its full title translates as “Comets and their General and Particular Meanings, According to Ptolomeé, Albumasar, Haly, Aliquind and other Astrologers”. The image is from https://publicdomainreview.org/collection/the-comet-book, made available by the Universitätsbibliothek Kassel under a CC-BY SA 4.0 license (https://creativecommons.org/licenses/by-sa/4.0/)", - "picture": "TheCometBook.jpg", - "priceUsd": { - "currencyCode": "USD", - "units": 0, - "nanos": 990000000 - }, - "categories": ["books"] - } - ] -} From 1219a15cf796afeafc6dd5c348ad8b1974ab6ee5 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Fri, 23 May 2025 18:14:18 +0200 Subject: [PATCH 49/60] add change log and removed the produc.json file from the product-catalog --- .licenserc.json | 11 +- CHANGELOG.md | 3 +- dapr/components/cart-state-store.yaml | 2 +- dapr/components/product-store.yaml | 4 +- docker-compose.yml | 18 +- src/fraud-detection/build.gradle.kts | 1 - .../src/main/kotlin/frauddetection/main.kt | 6 +- src/load-generator/locustfile.py | 1 + src/loadgenerator/locustfile_load.py | 295 ------------------ 9 files changed, 19 insertions(+), 322 deletions(-) delete mode 100644 src/loadgenerator/locustfile_load.py diff --git a/.licenserc.json b/.licenserc.json index 7d8374c46b..8921ae440d 100644 --- a/.licenserc.json +++ b/.licenserc.json @@ -28,10 +28,18 @@ "# Copyright The OpenTelemetry Authors", "# SPDX-License-Identifier: Apache-2.0" ], + "**/**/*.{yaml,yml,yamllint}": [ + "# Copyright The OpenTelemetry Authors", + "# SPDX-License-Identifier: Apache-2.0" + ], "**/*.sql": [ "-- Copyright The OpenTelemetry Authors", "-- SPDX-License-Identifier: Apache-2.0" ], + "**/**/*.sql": [ + "-- Copyright The OpenTelemetry Authors", + "-- SPDX-License-Identifier: Apache-2.0" + ], "**/{Dockerfile,Makefile}": [ "# Copyright The OpenTelemetry Authors", "# SPDX-License-Identifier: Apache-2.0" @@ -53,6 +61,7 @@ "src/recommendation/demo_pb2.py", "src/recommendation/demo_pb2_grpc.py", "src/frontend/protos/demo.ts", - "internal/tools/" + "internal/tools/", + ] } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 0044370f59..dc53eecb7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,8 +39,7 @@ the release. * [quote] Updated open-telemetry/exporter-otlp to 1.2.1 which includes the fix for `IS_REMOTE` flag feature ([#2112](https://github.com/open-telemetry/opentelemetry-demo/pull/2112)) -* [load-generator] Change OpenFeature Evaluation to Remote Evaluation Protocol, - based on [this issue in OpenFeature/python-sdk-contrib](https://github.com/open-feature/python-sdk-contrib/issues/198) +* [load-generator] Change OpenFeature Evaluation to Remote Evaluation Protocol, based on [this issue in OpenFeature/python-sdk-contrib](https://github.com/open-feature/python-sdk-contrib/issues/198) ([#2114](https://github.com/open-telemetry/opentelemetry-demo/pull/2114)) * [flagd-ui] increase memory to 100MB ([#2120](https://github.com/open-telemetry/opentelemetry-demo/pull/2120)) diff --git a/dapr/components/cart-state-store.yaml b/dapr/components/cart-state-store.yaml index f565a51363..ef7369fc37 100644 --- a/dapr/components/cart-state-store.yaml +++ b/dapr/components/cart-state-store.yaml @@ -9,4 +9,4 @@ spec: - name: redisHost value: valkey-cart:6379 - name: enableTLS - value: false \ No newline at end of file + value: false \ No newline at end of file diff --git a/dapr/components/product-store.yaml b/dapr/components/product-store.yaml index 119d02e424..7dfc1385ac 100644 --- a/dapr/components/product-store.yaml +++ b/dapr/components/product-store.yaml @@ -9,4 +9,6 @@ spec: - name: connectionString value: "host=product_db user=postgres password=example port=5432 connect_timeout=10 database=postgres" - name: tableName - value: "productstate" \ No newline at end of file + value: productstate + - name: cleanupInterval + value: 0 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index db683e8018..05c67703a1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -83,14 +83,7 @@ services: cart-dapr: image: "daprio/daprd:edge" container_name: cart-dapr - command: [ "./daprd", - "-app-id", "cart", - "-app-port", "${CART_PORT}", - "-placement-host-address", "dapr-placement:50006", - "-dapr-grpc-port", "50002", - "-dapr-http-port", "3500", - "-resources-path", "/dapr/components", - "-config", "/dapr/config.yaml"] + command: [ "./daprd", "-app-id", "cart", "-app-port", "${CART_PORT}", "-placement-host-address", "dapr-placement:50006", "-dapr-grpc-port", "50002", "-dapr-http-port", "3500","-resources-path", "/dapr/components","-config", "/dapr/config.yaml"] volumes: - "./dapr/:/dapr" depends_on: @@ -494,14 +487,7 @@ services: product-dapr: image: "daprio/daprd:edge" container_name: product-dapr - command: [ "./daprd", - "-app-id", "product-catalog", - "-app-port", "${PRODUCT_CATALOG_PORT}", - "-placement-host-address", "dapr-placement:50006", - "-dapr-grpc-port", "50002", - "-dapr-http-port", "3500", - "-resources-path", "/dapr/components", - "-config", "/dapr/config.yaml" ] + command: [ "./daprd","-app-id", "product-catalog", "-app-port", "${PRODUCT_CATALOG_PORT}","-placement-host-address", "dapr-placement:50006","-dapr-grpc-port", "50002","-dapr-http-port", "3500", "-resources-path", "/dapr/components","-config", "/dapr/config.yaml" ] volumes: - "./dapr/:/dapr" depends_on: diff --git a/src/fraud-detection/build.gradle.kts b/src/fraud-detection/build.gradle.kts index c37d6cd514..2ce809ddbc 100644 --- a/src/fraud-detection/build.gradle.kts +++ b/src/fraud-detection/build.gradle.kts @@ -31,7 +31,6 @@ dependencies { testImplementation(kotlin("test")) implementation(kotlin("script-runtime")) implementation("org.apache.kafka:kafka-clients:3.9.0") - implementation("com.google.api.grpc:proto-google-common-protos:2.53.0") implementation("io.grpc:grpc-protobuf:${grpcVersion}") implementation("io.grpc:grpc-stub:${grpcVersion}") diff --git a/src/fraud-detection/src/main/kotlin/frauddetection/main.kt b/src/fraud-detection/src/main/kotlin/frauddetection/main.kt index c4cf975ccf..bcb480ae77 100644 --- a/src/fraud-detection/src/main/kotlin/frauddetection/main.kt +++ b/src/fraud-detection/src/main/kotlin/frauddetection/main.kt @@ -9,7 +9,6 @@ import org.apache.kafka.clients.consumer.ConsumerConfig.* import org.apache.kafka.clients.consumer.KafkaConsumer import org.apache.kafka.common.serialization.ByteArrayDeserializer import org.apache.kafka.common.serialization.StringDeserializer - import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.Logger import oteldemo.Demo.* @@ -40,9 +39,6 @@ fun main() { props[KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java.name props[VALUE_DESERIALIZER_CLASS_CONFIG] = ByteArrayDeserializer::class.java.name props[GROUP_ID_CONFIG] = groupID - - ///---- - //#TODO add dapr consumer val bootstrapServers = System.getenv("KAFKA_ADDR") if (bootstrapServers == null) { println("KAFKA_ADDR is not supplied") @@ -72,7 +68,7 @@ fun main() { } } } -///----- + /** * Retrieves the status of a feature flag from the Feature Flag service. * diff --git a/src/load-generator/locustfile.py b/src/load-generator/locustfile.py index 4f86fe4b79..9132d024d6 100644 --- a/src/load-generator/locustfile.py +++ b/src/load-generator/locustfile.py @@ -218,3 +218,4 @@ async def add_baggage_header(route: Route, request: Request): 'baggage': ', '.join(filter(None, (existing_baggage, 'synthetic_request=true'))) } await route.continue_(headers=headers) + diff --git a/src/loadgenerator/locustfile_load.py b/src/loadgenerator/locustfile_load.py deleted file mode 100644 index 926d42529c..0000000000 --- a/src/loadgenerator/locustfile_load.py +++ /dev/null @@ -1,295 +0,0 @@ -#!/usr/bin/python -# -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import random -import uuid -import os -from locust import HttpUser, task, between -from locust import LoadTestShape - -from opentelemetry import context, baggage, trace -from opentelemetry.sdk.trace import TracerProvider -from opentelemetry.sdk.trace.export import (BatchSpanProcessor) -from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter -from opentelemetry.instrumentation.requests import RequestsInstrumentor -from opentelemetry.instrumentation.urllib3 import URLLib3Instrumentor - -tracer_provider = TracerProvider() -trace.set_tracer_provider(tracer_provider) -tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter())) - -# Instrumenting manually to avoid error with locust gevent monkey -RequestsInstrumentor().instrument() -URLLib3Instrumentor().instrument() - -products = [ - "0PUK6V6EV0", - "1YMWWN1N4O", - "2ZYFJ3GM2N", - "66VCHSJNUP", - "6E92ZMYYFZ", - "9SIQT8TOJO", - "L9ECAV7KIM", - "LS4PSXUNUM", - "OLJCESPC7Z" -] -HOST = os.getenv('ENV_HOST') -people = [ - { - "email": "larry_sergei@example.com", - "address": { - "streetAddress": "1600 Amphitheatre Parkway", - "zipCode": 94043, - "city": "Mountain View", - "state": "CA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4432-8015-6152-0454", - "creditCardExpirationMonth": 1, - "creditCardExpirationYear": 2039, - "creditCardCvv": 672 - } - }, - { - "email": "bill@example.com", - "address": { - "streetAddress": "One Microsoft Way", - "zipCode": 98052, - "city": "Redmond", - "state": "WA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4532-4211-7434-1278", - "creditCardExpirationMonth": 2, - "creditCardExpirationYear": 2039, - "creditCardCvv": 114 - } - }, - { - "email": "steve@example.com", - "address": { - "streetAddress": "One Apple Park Way", - "zipCode": 95014, - "city": "Cupertino", - "state": "CA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4532-6178-2799-1951", - "creditCardExpirationMonth": 3, - "creditCardExpirationYear": 2039, - "creditCardCvv": 239 - } - }, - { - "email": "mark@example.com", - "address": { - "streetAddress": "1 Hacker Way", - "zipCode": 94025, - "city": "Menlo Park", - "state": "CA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4539-1103-5661-7083", - "creditCardExpirationMonth": 4, - "creditCardExpirationYear": 2039, - "creditCardCvv": 784 - } - }, - { - "email": "jeff@example.com", - "address": { - "streetAddress": "410 Terry Ave N", - "zipCode": 98109, - "city": "Seattle", - "state": "WA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4916-0816-6217-7968", - "creditCardExpirationMonth": 5, - "creditCardExpirationYear": 2039, - "creditCardCvv": 397 - } - }, - { - "email": "reed@example.com", - "address": { - "streetAddress": "100 Winchester Circle", - "zipCode": 95032, - "city": "Los Gatos", - "state": "CA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4929-5431-0337-5647", - "creditCardExpirationMonth": 6, - "creditCardExpirationYear": 2039, - "creditCardCvv": 793 - } - }, - { - "email": "tobias@example.com", - "address": { - "streetAddress": "150 Elgin St", - "zipCode": 214, - "city": "Ottawa", - "state": "ON", - "country": "Canada" - }, - "userCurrency": "CAD", - "creditCard": { - "creditCardNumber": "4763-1844-9699-8031", - "creditCardExpirationMonth": 7, - "creditCardExpirationYear": 2039, - "creditCardCvv": 488 - } - }, - { - "email": "jack@example.com", - "address": { - "streetAddress": "1355 Market St", - "zipCode": 94103, - "city": "San Francisco", - "state": "CA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4929-6495-8333-3657", - "creditCardExpirationMonth": 8, - "creditCardExpirationYear": 2039, - "creditCardCvv": 159 - } - }, - { - "email": "moore@example.com", - "address": { - "streetAddress": "2200 Mission College Blvd", - "zipCode": 95054, - "city": "Santa Clara", - "state": "CA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4485-4803-8707-3547", - "creditCardExpirationMonth": 9, - "creditCardExpirationYear": 2039, - "creditCardCvv": 682 - } - } -] - - -class WebsiteUser(HttpUser): - wait_time = between(1, 10) - - @task(1) - def index(self): - self.client.get("/") - - @task(10) - def browse_product(self): - self.client.get("/api/products/" + random.choice(products)) - - @task(3) - def view_cart(self): - self.client.get("/api/cart") - - @task(2) - def add_to_cart(self, user=""): - if user == "": - user = str(uuid.uuid1()) - product = random.choice(products) - self.client.get("/api/products/" + product) - cart_item = { - "item": { - "productId": product, - "quantity": random.choice([1, 2, 3, 4, 5, 10]) - }, - "userId": user - } - self.client.post("/api/cart", json=cart_item,headers={"Host: "+ HOST}) - - @task(1) - def checkout(self): - # checkout call with an item added to cart - user = str(uuid.uuid1()) - self.add_to_cart(user=user) - checkout_person = random.choice(people) - checkout_person["userId"] = user - self.client.post("/api/checkout", json=checkout_person,headers={"Host: "+ HOST}) - - @task(1) - def checkout_multi(self): - # checkout call which adds 2-4 different items to cart before checkout - user = str(uuid.uuid1()) - for i in range(random.choice([2, 3, 4])): - self.add_to_cart(user=user) - checkout_person = random.choice(people) - checkout_person["userId"] = user - self.client.post("/api/checkout", json=checkout_person,headers={"Host: "+ HOST}) - - def on_start(self): - ctx = baggage.set_baggage("synthetic_request", "true") - context.attach(ctx) - self.index() - -class StagesShape(LoadTestShape): - """ - A simply load test shape class that has different user and spawn_rate at - different stages. - Keyword arguments: - stages -- A list of dicts, each representing a stage with the following keys: - duration -- When this many seconds pass the test is advanced to the next stage - users -- Total user count - spawn_rate -- Number of users to start/stop per second - stop -- A boolean that can stop that test at a specific stage - stop_at_end -- Can be set to stop once all stages have run. - """ - - stages = [ - {"duration": 60, "users": 10, "spawn_rate": 10}, - {"duration": 600, "users": 50, "spawn_rate": 10}, - {"duration": 600, "users": 100, "spawn_rate": 10}, - {"duration": 600, "users": 150, "spawn_rate": 10}, - {"duration": 600, "users": 200, "spawn_rate": 10}, - {"duration": 600, "users": 250, "spawn_rate": 10}, - {"duration": 600, "users": 300, "spawn_rate": 10}, - {"duration": 600, "users": 350, "spawn_rate": 10}, - {"duration": 600, "users": 400, "spawn_rate": 10}, - {"duration": 600, "users": 450, "spawn_rate": 10}, - ] - - def tick(self): - run_time = self.get_run_time() - - for stage in self.stages: - if run_time < stage["duration"]: - tick_data = (stage["users"], stage["spawn_rate"]) - return tick_data - - return None \ No newline at end of file From 7092d2e25e29fdef4c78b3c13e3c400087d13877 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Fri, 23 May 2025 18:37:27 +0200 Subject: [PATCH 50/60] resole the various checks in failure --- .licenserc.json | 13 +++---------- CHANGELOG.md | 6 +++--- dapr/components/product-store.yaml | 2 +- dapr/components/pubsub.yaml | 8 ++++---- dapr/config.yaml | 2 +- docker-compose.yml | 6 ++++-- 6 files changed, 16 insertions(+), 21 deletions(-) diff --git a/.licenserc.json b/.licenserc.json index 8921ae440d..4f011a3adb 100644 --- a/.licenserc.json +++ b/.licenserc.json @@ -28,18 +28,12 @@ "# Copyright The OpenTelemetry Authors", "# SPDX-License-Identifier: Apache-2.0" ], - "**/**/*.{yaml,yml,yamllint}": [ - "# Copyright The OpenTelemetry Authors", - "# SPDX-License-Identifier: Apache-2.0" - ], + "**/*.sql": [ "-- Copyright The OpenTelemetry Authors", "-- SPDX-License-Identifier: Apache-2.0" ], - "**/**/*.sql": [ - "-- Copyright The OpenTelemetry Authors", - "-- SPDX-License-Identifier: Apache-2.0" - ], + "**/{Dockerfile,Makefile}": [ "# Copyright The OpenTelemetry Authors", "# SPDX-License-Identifier: Apache-2.0" @@ -61,7 +55,6 @@ "src/recommendation/demo_pb2.py", "src/recommendation/demo_pb2_grpc.py", "src/frontend/protos/demo.ts", - "internal/tools/", - + "internal/tools/" ] } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index dc53eecb7c..354dacec3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,9 @@ the release. ## 2.0.3 -* [product catalog] removed the usage on the json file , repalced it with a Dapr client -* [sqllit] dropped the sqllite , because no support for dapr query -* [postgresl] added postgresql to add a storage of the product catalog ( default database used by dapr) +* [product catalog] use it with a Dapr client +* [cartservice] Using Dapr to connect to valkey +* [postgresl] added postgresql for product * [chore] add GOMEMLIMIT to all Go services ([#2148](https://github.com/open-telemetry/opentelemetry-demo/pull/2148)) diff --git a/dapr/components/product-store.yaml b/dapr/components/product-store.yaml index 7dfc1385ac..bfffb91e2a 100644 --- a/dapr/components/product-store.yaml +++ b/dapr/components/product-store.yaml @@ -11,4 +11,4 @@ spec: - name: tableName value: productstate - name: cleanupInterval - value: 0 \ No newline at end of file + value: 0 diff --git a/dapr/components/pubsub.yaml b/dapr/components/pubsub.yaml index b49443580f..b3a9a990a0 100644 --- a/dapr/components/pubsub.yaml +++ b/dapr/components/pubsub.yaml @@ -6,11 +6,11 @@ spec: type: pubsub.kafka version: v1 metadata: - - name: brokers # Required. Kafka broker connection setting + - name: brokers # Required. Kafka broker connection setting value: "kafka:9092" - - name: authType # Required. + - name: authType value: "none" - - name: disableTls # Optional. Disable TLS. This is not safe for production!! You should read the `Mutual TLS` section for how to use TLS. + - name: disableTls # Optional. Disable TLS. This is not safe for production!! You should read the `Mutual TLS` section for how to use TLS. value: "false" - name: publishingScopes value: "checkout=orders" @@ -19,4 +19,4 @@ spec: scopes: - accounting - checkout -- fraud-detection \ No newline at end of file +- fraud-detection diff --git a/dapr/config.yaml b/dapr/config.yaml index 7a3f143701..f43dab1c48 100644 --- a/dapr/config.yaml +++ b/dapr/config.yaml @@ -14,4 +14,4 @@ spec: otel: endpointAddress: "otel-gateway-collector:4317" isSecure: true - protocol: grpc \ No newline at end of file + protocol: grpc diff --git a/docker-compose.yml b/docker-compose.yml index 05c67703a1..6516bbee73 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -83,7 +83,8 @@ services: cart-dapr: image: "daprio/daprd:edge" container_name: cart-dapr - command: [ "./daprd", "-app-id", "cart", "-app-port", "${CART_PORT}", "-placement-host-address", "dapr-placement:50006", "-dapr-grpc-port", "50002", "-dapr-http-port", "3500","-resources-path", "/dapr/components","-config", "/dapr/config.yaml"] + command: [ "./daprd", "-app-id", "cart", "-app-port", "${CART_PORT}", "-placement-host-address", "dapr-placement:50006", "-dapr-grpc-port", "50002", "-dapr-http-port", "3500", + "-resources-path", "/dapr/components", "-config", "/dapr/config.yaml"] volumes: - "./dapr/:/dapr" depends_on: @@ -487,7 +488,8 @@ services: product-dapr: image: "daprio/daprd:edge" container_name: product-dapr - command: [ "./daprd","-app-id", "product-catalog", "-app-port", "${PRODUCT_CATALOG_PORT}","-placement-host-address", "dapr-placement:50006","-dapr-grpc-port", "50002","-dapr-http-port", "3500", "-resources-path", "/dapr/components","-config", "/dapr/config.yaml" ] + command: [ "./daprd","-app-id", "product-catalog", "-app-port", "${PRODUCT_CATALOG_PORT}", "-placement-host-address", "dapr-placement:50006", "-dapr-grpc-port", "50002", "-dapr-http-port", + "3500", "-resources-path", "/dapr/components", "-config", "/dapr/config.yaml" ] volumes: - "./dapr/:/dapr" depends_on: From d4d391f6ed81297a8afb37bc683072e711dddfd4 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Fri, 23 May 2025 18:49:19 +0200 Subject: [PATCH 51/60] resole the various checks in failure --- CHANGELOG.md | 3 ++- dapr/components/cart-state-store.yaml | 2 +- docker-compose.yml | 22 ++++++++++++++++++---- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 354dacec3b..ea0d851cce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,8 @@ the release. * [quote] Updated open-telemetry/exporter-otlp to 1.2.1 which includes the fix for `IS_REMOTE` flag feature ([#2112](https://github.com/open-telemetry/opentelemetry-demo/pull/2112)) -* [load-generator] Change OpenFeature Evaluation to Remote Evaluation Protocol, based on [this issue in OpenFeature/python-sdk-contrib](https://github.com/open-feature/python-sdk-contrib/issues/198) +* [load-generator] Change OpenFeature Evaluation to Remote Evaluation Protocol,based on + ([this issue in OpenFeature/python-sdk-contrib](https://github.com/open-feature/python-sdk-contrib/issues/198)) ([#2114](https://github.com/open-telemetry/opentelemetry-demo/pull/2114)) * [flagd-ui] increase memory to 100MB ([#2120](https://github.com/open-telemetry/opentelemetry-demo/pull/2120)) diff --git a/dapr/components/cart-state-store.yaml b/dapr/components/cart-state-store.yaml index ef7369fc37..483bc199b9 100644 --- a/dapr/components/cart-state-store.yaml +++ b/dapr/components/cart-state-store.yaml @@ -9,4 +9,4 @@ spec: - name: redisHost value: valkey-cart:6379 - name: enableTLS - value: false \ No newline at end of file + value: false diff --git a/docker-compose.yml b/docker-compose.yml index 6516bbee73..3bed59d115 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -83,8 +83,15 @@ services: cart-dapr: image: "daprio/daprd:edge" container_name: cart-dapr - command: [ "./daprd", "-app-id", "cart", "-app-port", "${CART_PORT}", "-placement-host-address", "dapr-placement:50006", "-dapr-grpc-port", "50002", "-dapr-http-port", "3500", - "-resources-path", "/dapr/components", "-config", "/dapr/config.yaml"] + command: + - "./daprd" + - "-app-id cart" + - "-app-port ${CART_PORT}" + - "-placement-host-address dapr-placement:50006" + - "-dapr-grpc-port 50002" + - "-dapr-http-port 3500" + - "-resources-path /dapr/components" + - "-config /dapr/config.yaml" volumes: - "./dapr/:/dapr" depends_on: @@ -488,8 +495,15 @@ services: product-dapr: image: "daprio/daprd:edge" container_name: product-dapr - command: [ "./daprd","-app-id", "product-catalog", "-app-port", "${PRODUCT_CATALOG_PORT}", "-placement-host-address", "dapr-placement:50006", "-dapr-grpc-port", "50002", "-dapr-http-port", - "3500", "-resources-path", "/dapr/components", "-config", "/dapr/config.yaml" ] + command: + - "./daprd" + - "-app-id product-catalog" + - "-app-port ${PRODUCT_CATALOG_PORT}" + - "-placement-host-address dapr-placement:50006" + - "-dapr-grpc-port 50002" + - "-dapr-http-port 3500" + - "-resources-path /dapr/components" + - "-config /dapr/config.yaml" volumes: - "./dapr/:/dapr" depends_on: From 9c8c8ca188fc600bc96479452816e53d2bf31379 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Fri, 23 May 2025 18:57:26 +0200 Subject: [PATCH 52/60] resole the various checks in failure --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea0d851cce..ed8fadcbc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,7 @@ the release. * [quote] Updated open-telemetry/exporter-otlp to 1.2.1 which includes the fix for `IS_REMOTE` flag feature ([#2112](https://github.com/open-telemetry/opentelemetry-demo/pull/2112)) -* [load-generator] Change OpenFeature Evaluation to Remote Evaluation Protocol,based on +* [load-generator] Change OpenFeature Evaluation to Remote Evaluation Protocol, ([this issue in OpenFeature/python-sdk-contrib](https://github.com/open-feature/python-sdk-contrib/issues/198)) ([#2114](https://github.com/open-telemetry/opentelemetry-demo/pull/2114)) * [flagd-ui] increase memory to 100MB From 678b73d1795e86ca5c1c36088d6f51addfdab3a2 Mon Sep 17 00:00:00 2001 From: Juliano Costa Date: Mon, 26 May 2025 12:54:23 +0200 Subject: [PATCH 53/60] Fix product-catalog dockerfile --- src/product-catalog/Dockerfile | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/product-catalog/Dockerfile b/src/product-catalog/Dockerfile index d4c596dce3..e17af81720 100644 --- a/src/product-catalog/Dockerfile +++ b/src/product-catalog/Dockerfile @@ -1,19 +1,15 @@ # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 - - FROM golang:1.24-bookworm AS builder WORKDIR /usr/src/app/ -RUN --mount=type=cache,target=/go/pkg/mod/ \ - --mount=type=bind,source=./src/product-catalog/go.sum,target=go.sum \ - --mount=type=bind,source=./src/product-catalog/go.mod,target=go.mod \ - go mod download +COPY ./src/product-catalog/go.mod ./src/product-catalog/go.sum ./ + +RUN go mod download COPY ./src/product-catalog/genproto/oteldemo/ genproto/oteldemo/ -COPY ./src/product-catalog/products/ products/ COPY ./src/product-catalog/main.go main.go RUN CGO_ENABLED=0 GOOS=linux GO111MODULE=on go build -ldflags "-s -w" -o product-catalog main.go From 494f800c87a33c68dc61afdbabdcf509b6a43f79 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 26 May 2025 16:33:35 +0200 Subject: [PATCH 54/60] resolve docker-compose yamlint issue --- docker-compose.minimal.yml | 6 +++--- docker-compose.yml | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docker-compose.minimal.yml b/docker-compose.minimal.yml index ab66f616c9..e8e584856f 100644 --- a/docker-compose.minimal.yml +++ b/docker-compose.minimal.yml @@ -87,9 +87,9 @@ services: "-app-id", "cart", "-app-port", "${CART_PORT}", "-placement-host-address", "dapr-placement:50006", - "-components-path", "/components", "-components-path", "/components", + "-components-path", "/components", "-components-path", "/components", "-config", "/configuration/config.yaml" - ] + ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" @@ -450,7 +450,7 @@ services: "-placement-host-address", "dapr-placement:50006", "-resources-path", "/configuration/config.yaml", "-config", "/dapr/config.yaml" - ] + ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" diff --git a/docker-compose.yml b/docker-compose.yml index 9618af4dc4..b375c30f11 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -116,12 +116,12 @@ services: image: "daprio/daprd:edge" container_name: cart-dapr command: [ "./daprd", - "-app-id", "cart", - "-app-port", "${CART_PORT}", - "-placement-host-address", "dapr-placement:50006", - "-components-path", "/components", "-components-path", "/components", - "-config", "/configuration/config.yaml" - ] + "-app-id", "cart", + "-app-port", "${CART_PORT}", + "-placement-host-address", "dapr-placement:50006", + "-components-path", "/components", "-components-path", "/components", + "-config", "/configuration/config.yaml" + ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" @@ -531,12 +531,12 @@ services: image: "daprio/daprd:edge" container_name: product-dapr command: ["./daprd", - "-app-id", "product-catalog", - "-app-port", "${PRODUCT_CATALOG_PORT}", - "-placement-host-address", "dapr-placement:50006", - "-resources-path", "/configuration/config.yaml", - "-config", "/dapr/config.yaml" - ] + "-app-id", "product-catalog", + "-app-port", "${PRODUCT_CATALOG_PORT}", + "-placement-host-address", "dapr-placement:50006", + "-resources-path", "/configuration/config.yaml", + "-config", "/dapr/config.yaml" + ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" From 4f6f6d63c781249b363bcb5b5aecc7a862c6a162 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 26 May 2025 16:38:03 +0200 Subject: [PATCH 55/60] resolve docker-compose yamlint issue --- docker-compose.minimal.yml | 4 ++-- docker-compose.yml | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docker-compose.minimal.yml b/docker-compose.minimal.yml index e8e584856f..d5d8c5aa96 100644 --- a/docker-compose.minimal.yml +++ b/docker-compose.minimal.yml @@ -89,7 +89,7 @@ services: "-placement-host-address", "dapr-placement:50006", "-components-path", "/components", "-components-path", "/components", "-config", "/configuration/config.yaml" - ] + ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" @@ -450,7 +450,7 @@ services: "-placement-host-address", "dapr-placement:50006", "-resources-path", "/configuration/config.yaml", "-config", "/dapr/config.yaml" - ] + ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" diff --git a/docker-compose.yml b/docker-compose.yml index b375c30f11..c2a0bb9080 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -116,11 +116,11 @@ services: image: "daprio/daprd:edge" container_name: cart-dapr command: [ "./daprd", - "-app-id", "cart", - "-app-port", "${CART_PORT}", - "-placement-host-address", "dapr-placement:50006", - "-components-path", "/components", "-components-path", "/components", - "-config", "/configuration/config.yaml" + "-app-id", "cart", + "-app-port", "${CART_PORT}", + "-placement-host-address", "dapr-placement:50006", + "-components-path", "/components", "-components-path", "/components", + "-config", "/configuration/config.yaml" ] volumes: - "./src/dapr/components/:/components" @@ -530,12 +530,12 @@ services: product-dapr: image: "daprio/daprd:edge" container_name: product-dapr - command: ["./daprd", - "-app-id", "product-catalog", - "-app-port", "${PRODUCT_CATALOG_PORT}", - "-placement-host-address", "dapr-placement:50006", - "-resources-path", "/configuration/config.yaml", - "-config", "/dapr/config.yaml" + command: [ "./daprd", + "-app-id", "product-catalog", + "-app-port", "${PRODUCT_CATALOG_PORT}", + "-placement-host-address", "dapr-placement:50006", + "-resources-path", "/configuration/config.yaml", + "-config", "/dapr/config.yaml" ] volumes: - "./src/dapr/components/:/components" From 41031c2a6d834bf0e6fefe6d3014cabfd67fe564 Mon Sep 17 00:00:00 2001 From: Henrik Rexed Date: Mon, 26 May 2025 16:42:21 +0200 Subject: [PATCH 56/60] resolve docker-compose yamlint issue --- docker-compose.minimal.yml | 6 ++---- docker-compose.yml | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/docker-compose.minimal.yml b/docker-compose.minimal.yml index d5d8c5aa96..58621c2dbf 100644 --- a/docker-compose.minimal.yml +++ b/docker-compose.minimal.yml @@ -88,8 +88,7 @@ services: "-app-port", "${CART_PORT}", "-placement-host-address", "dapr-placement:50006", "-components-path", "/components", "-components-path", "/components", - "-config", "/configuration/config.yaml" - ] + "-config", "/configuration/config.yaml" ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" @@ -449,8 +448,7 @@ services: "-app-port", "${PRODUCT_CATALOG_PORT}", "-placement-host-address", "dapr-placement:50006", "-resources-path", "/configuration/config.yaml", - "-config", "/dapr/config.yaml" - ] + "-config", "/dapr/config.yaml" ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" diff --git a/docker-compose.yml b/docker-compose.yml index c2a0bb9080..26ac3c9aa5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -120,8 +120,7 @@ services: "-app-port", "${CART_PORT}", "-placement-host-address", "dapr-placement:50006", "-components-path", "/components", "-components-path", "/components", - "-config", "/configuration/config.yaml" - ] + "-config", "/configuration/config.yaml" ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" @@ -535,8 +534,7 @@ services: "-app-port", "${PRODUCT_CATALOG_PORT}", "-placement-host-address", "dapr-placement:50006", "-resources-path", "/configuration/config.yaml", - "-config", "/dapr/config.yaml" - ] + "-config", "/dapr/config.yaml" ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" From bec745cd2fb7260191b245b2d5de37006f040628 Mon Sep 17 00:00:00 2001 From: Juliano Costa Date: Wed, 25 Jun 2025 14:02:01 +0200 Subject: [PATCH 57/60] Sanity check --- docker-compose.minimal.yml | 20 ++++++++++++++------ docker-compose.yml | 20 ++++++++++++++------ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/docker-compose.minimal.yml b/docker-compose.minimal.yml index 7a5983cbf9..10fc6f9353 100644 --- a/docker-compose.minimal.yml +++ b/docker-compose.minimal.yml @@ -80,6 +80,7 @@ services: otel-collector: condition: service_started logging: *logging + cart-dapr: image: "daprio/daprd:edge" container_name: cart-dapr @@ -443,12 +444,19 @@ services: product-dapr: image: "daprio/daprd:edge" container_name: product-dapr - command: [ "./daprd", - "-app-id", "product-catalog", - "-app-port", "${PRODUCT_CATALOG_PORT}", - "-placement-host-address", "dapr-placement:50006", - "-resources-path", "/configuration/config.yaml", - "-config", "/dapr/config.yaml" ] + command: [ + "./daprd", + "-app-id", + "product-catalog", + "-app-port", + "${PRODUCT_CATALOG_PORT}", + "-placement-host-address", + "dapr-placement:50006", + "-resources-path", + "/configuration/config.yaml", + "-config", + "/dapr/config.yaml" + ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" diff --git a/docker-compose.yml b/docker-compose.yml index 9b4fa13665..227b906321 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -114,15 +114,23 @@ services: flagd: condition: service_started logging: *logging + cart-dapr: image: "daprio/daprd:edge" container_name: cart-dapr - command: [ "./daprd", - "-app-id", "cart", - "-app-port", "${CART_PORT}", - "-placement-host-address", "dapr-placement:50006", - "-components-path", "/components", "-components-path", "/components", - "-config", "/configuration/config.yaml" ] + command: [ + "./daprd", + "-app-id", + "product-catalog", + "-app-port", + "${PRODUCT_CATALOG_PORT}", + "-placement-host-address", + "dapr-placement:50006", + "-resources-path", + "/configuration/config.yaml", + "-config", + "/dapr/config.yaml" + ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" From ba74f2dbd4a923387eb0b0a50d71a06748392045 Mon Sep 17 00:00:00 2001 From: Juliano Costa Date: Wed, 25 Jun 2025 14:05:01 +0200 Subject: [PATCH 58/60] Add license --- src/dapr/components/cart-state-store.yaml | 3 +++ src/dapr/components/product-store.yaml | 3 +++ src/dapr/components/pubsub.yaml | 3 +++ src/dapr/config.yaml | 3 +++ 4 files changed, 12 insertions(+) diff --git a/src/dapr/components/cart-state-store.yaml b/src/dapr/components/cart-state-store.yaml index 483bc199b9..a3ee0ec025 100644 --- a/src/dapr/components/cart-state-store.yaml +++ b/src/dapr/components/cart-state-store.yaml @@ -1,3 +1,6 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + apiVersion: dapr.io/v1alpha1 kind: Component metadata: diff --git a/src/dapr/components/product-store.yaml b/src/dapr/components/product-store.yaml index bfffb91e2a..f8da8fb15c 100644 --- a/src/dapr/components/product-store.yaml +++ b/src/dapr/components/product-store.yaml @@ -1,3 +1,6 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + apiVersion: dapr.io/v1alpha1 kind: Component metadata: diff --git a/src/dapr/components/pubsub.yaml b/src/dapr/components/pubsub.yaml index b3a9a990a0..a95d763957 100644 --- a/src/dapr/components/pubsub.yaml +++ b/src/dapr/components/pubsub.yaml @@ -1,3 +1,6 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + apiVersion: dapr.io/v1alpha1 kind: Component metadata: diff --git a/src/dapr/config.yaml b/src/dapr/config.yaml index f43dab1c48..e70aed4982 100644 --- a/src/dapr/config.yaml +++ b/src/dapr/config.yaml @@ -1,3 +1,6 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + apiVersion: dapr.io/v1alpha1 kind: Configuration metadata: From 0a25bf2e2ea8273ad580f91fd7364008bbf46569 Mon Sep 17 00:00:00 2001 From: Juliano Costa Date: Wed, 25 Jun 2025 14:11:19 +0200 Subject: [PATCH 59/60] Sanity and license --- docker-compose.minimal.yml | 19 +++++++++++++------ docker-compose.yml | 21 ++++++++++++++------- src/postgresql/product/init.sql | 2 ++ 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/docker-compose.minimal.yml b/docker-compose.minimal.yml index 10fc6f9353..b646ba7715 100644 --- a/docker-compose.minimal.yml +++ b/docker-compose.minimal.yml @@ -84,12 +84,19 @@ services: cart-dapr: image: "daprio/daprd:edge" container_name: cart-dapr - command: [ "./daprd", - "-app-id", "cart", - "-app-port", "${CART_PORT}", - "-placement-host-address", "dapr-placement:50006", - "-components-path", "/components", "-components-path", "/components", - "-config", "/configuration/config.yaml" ] + command: [ + "./daprd", + "-app-id", + "cart", + "-app-port", + "${CART_PORT}", + "-placement-host-address", + "dapr-placement:50006", + "-components-path", + "/components", + "-config", + "/configuration/config.yaml" + ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" diff --git a/docker-compose.yml b/docker-compose.yml index 227b906321..57b22e11d5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -114,7 +114,7 @@ services: flagd: condition: service_started logging: *logging - + cart-dapr: image: "daprio/daprd:edge" container_name: cart-dapr @@ -539,12 +539,19 @@ services: product-dapr: image: "daprio/daprd:edge" container_name: product-dapr - command: [ "./daprd", - "-app-id", "product-catalog", - "-app-port", "${PRODUCT_CATALOG_PORT}", - "-placement-host-address", "dapr-placement:50006", - "-resources-path", "/configuration/config.yaml", - "-config", "/dapr/config.yaml" ] + command: [ + "./daprd", + "-app-id", + "product-catalog", + "-app-port", + "${PRODUCT_CATALOG_PORT}", + "-placement-host-address", + "dapr-placement:50006", + "-resources-path", + "/configuration/config.yaml", + "-config", + "/dapr/config.yaml" + ] volumes: - "./src/dapr/components/:/components" - "./src/dapr/:/configuration" diff --git a/src/postgresql/product/init.sql b/src/postgresql/product/init.sql index 2479a4b32a..6b40ee3853 100644 --- a/src/postgresql/product/init.sql +++ b/src/postgresql/product/init.sql @@ -1,3 +1,5 @@ +-- Copyright The OpenTelemetry Authors +-- SPDX-License-Identifier: Apache-2.0 DROP TABLE IF EXISTS "product"; DROP TABLE IF EXISTS "productstate"; From b64413092ffa71c884e0d062e46d19200dc1e31e Mon Sep 17 00:00:00 2001 From: Juliano Costa Date: Wed, 25 Jun 2025 14:13:59 +0200 Subject: [PATCH 60/60] Remove trailing space --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 57b22e11d5..03e16c2906 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -539,7 +539,7 @@ services: product-dapr: image: "daprio/daprd:edge" container_name: product-dapr - command: [ + command: [ "./daprd", "-app-id", "product-catalog",