diff --git a/CHANGELOG.md b/CHANGELOG.md index 096d0132b1..1fb98ba6d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,8 @@ release. ([#935](https://github.com/open-telemetry/opentelemetry-demo/pull/935)) * [cartservice] update service to .NET 7 ([#942](https://github.com/open-telemetry/opentelemetry-demo/pull/942)) +* Introduce minimal mode to run demo + ([#872](https://github.com/open-telemetry/opentelemetry-demo/pull/872)) * [frontendproxy]Envoy expose a route for the collector to route frontend spans ([#938](https://github.com/open-telemetry/opentelemetry-demo/pull/938)) diff --git a/Makefile b/Makefile index 620b01b18c..81d0aaa71f 100644 --- a/Makefile +++ b/Makefile @@ -107,3 +107,30 @@ generate-kubernetes-manifests: echo "# SPDX-License-Identifier: Apache-2.0" >> kubernetes/opentelemetry-demo.yaml echo "# This file is generated by 'make generate-kubernetes-manifests'" >> kubernetes/opentelemetry-demo.yaml helm template opentelemetry-demo open-telemetry/opentelemetry-demo --namespace otel-demo | sed '/helm.sh\/chart\:/d' | sed '/helm.sh\/hook/d' | sed '/managed-by\: Helm/d' >> kubernetes/opentelemetry-demo.yaml + +.PHONY: start +start: + docker compose up --force-recreate --remove-orphans --detach + @echo "" + @echo "OpenTelemetry Demo is running." + @echo "Go to http://localhost:8080 for the demo UI." + @echo "Go to http://localhost:8080/jaeger/ui for the Jaeger UI." + @echo "Go to http://localhost:8080/grafana/ for the Grafana UI." + @echo "Go to http://localhost:8080/loadgen/ for the Load Generator UI." + @echo "Go to http://localhost:8080/feature/ for the Feature Flag UI." + +.PHONY: start-minimal +start-minimal: + docker compose -f docker-compose.minimal.yml up --force-recreate --remove-orphans --detach + @echo "" + @echo "OpenTelemetry Demo in minimal mode is running." + @echo "Go to http://localhost:8080 for the demo UI." + @echo "Go to http://localhost:8080/jaeger/ui for the Jaeger UI." + @echo "Go to http://localhost:8080/grafana/ for the Grafana UI." + @echo "Go to http://localhost:8080/loadgen/ for the Load Generator UI." + +.PHONY: stop +stop: + docker compose down --remove-orphans --volumes + @echo "" + @echo "OpenTelemetry Demo is stopped." diff --git a/docker-compose.minimal.yml b/docker-compose.minimal.yml new file mode 100644 index 0000000000..79d39e4d00 --- /dev/null +++ b/docker-compose.minimal.yml @@ -0,0 +1,544 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +version: '3.9' +x-default-logging: &logging + driver: "json-file" + options: + max-size: "5m" + max-file: "2" + +networks: + default: + name: opentelemetry-demo + driver: bridge + +services: + # ****************** + # Core Demo Services + # ****************** + + # AdService + adservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-adservice + container_name: ad-service + build: + context: ./ + dockerfile: ./src/adservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-adservice + deploy: + resources: + limits: + memory: 300M + restart: unless-stopped + ports: + - "${AD_SERVICE_PORT}" + environment: + - AD_SERVICE_PORT + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_LOGS_EXPORTER=otlp + - OTEL_SERVICE_NAME=adservice + depends_on: + otelcol: + condition: service_started + logging: *logging + + # Cart service + cartservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-cartservice + container_name: cart-service + build: + context: ./ + dockerfile: ./src/cartservice/src/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-cartservice + deploy: + resources: + limits: + memory: 160M + restart: unless-stopped + ports: + - "${CART_SERVICE_PORT}" + environment: + - CART_SERVICE_PORT + - REDIS_ADDR + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=cartservice + - ASPNETCORE_URLS=http://*:${CART_SERVICE_PORT} + depends_on: + redis-cart: + condition: service_started + otelcol: + condition: service_started + logging: *logging + + # Checkout service + checkoutservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-checkoutservice + container_name: checkout-service + build: + context: ./ + dockerfile: ./src/checkoutservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-checkoutservice + deploy: + resources: + limits: + memory: 20M + restart: unless-stopped + ports: + - "${CHECKOUT_SERVICE_PORT}" + environment: + - CHECKOUT_SERVICE_PORT + - CART_SERVICE_ADDR + - CURRENCY_SERVICE_ADDR + - EMAIL_SERVICE_ADDR + - PAYMENT_SERVICE_ADDR + - PRODUCT_CATALOG_SERVICE_ADDR + - SHIPPING_SERVICE_ADDR + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=checkoutservice + depends_on: + cartservice: + condition: service_started + currencyservice: + condition: service_started + emailservice: + condition: service_started + paymentservice: + condition: service_started + productcatalogservice: + condition: service_started + shippingservice: + condition: service_started + otelcol: + condition: service_started + logging: *logging + + # Currency service + currencyservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-currencyservice + container_name: currency-service + build: + context: ./src/currencyservice + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-currencyservice + args: + - GRPC_VERSION=1.46.0 + - OPENTELEMETRY_VERSION=1.5.0 + deploy: + resources: + limits: + memory: 20M + restart: unless-stopped + ports: + - "${CURRENCY_SERVICE_PORT}" + environment: + - CURRENCY_SERVICE_PORT + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_RESOURCE_ATTRIBUTES=${OTEL_RESOURCE_ATTRIBUTES},service.name=currencyservice # The C++ SDK does not support OTEL_SERVICE_NAME + depends_on: + otelcol: + condition: service_started + logging: *logging + + # Email service + emailservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-emailservice + container_name: email-service + build: + context: ./src/emailservice + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-emailservice + deploy: + resources: + limits: + memory: 100M + restart: unless-stopped + ports: + - "${EMAIL_SERVICE_PORT}" + environment: + - APP_ENV=production + - EMAIL_SERVICE_PORT + - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://${OTEL_COLLECTOR_HOST}:4318/v1/traces + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=emailservice + depends_on: + otelcol: + condition: service_started + logging: *logging + + # Frontend + frontend: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-frontend + container_name: frontend + build: + context: ./ + dockerfile: ./src/frontend/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-frontend + deploy: + resources: + limits: + memory: 200M + restart: unless-stopped + ports: + - "${FRONTEND_PORT}" + environment: + - PORT=${FRONTEND_PORT} + - FRONTEND_ADDR + - AD_SERVICE_ADDR + - CART_SERVICE_ADDR + - CHECKOUT_SERVICE_ADDR + - CURRENCY_SERVICE_ADDR + - PRODUCT_CATALOG_SERVICE_ADDR + - RECOMMENDATION_SERVICE_ADDR + - SHIPPING_SERVICE_ADDR + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_RESOURCE_ATTRIBUTES=${OTEL_RESOURCE_ATTRIBUTES} + - ENV_PLATFORM + - OTEL_SERVICE_NAME=frontend + - PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE + - WEB_OTEL_SERVICE_NAME=frontend-web + depends_on: + adservice: + condition: service_started + cartservice: + condition: service_started + checkoutservice: + condition: service_started + currencyservice: + condition: service_started + productcatalogservice: + condition: service_started + quoteservice: + condition: service_started + recommendationservice: + condition: service_started + shippingservice: + condition: service_started + otelcol: + condition: service_started + logging: *logging + + # Frontend Proxy (Envoy) + frontendproxy: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-frontendproxy + container_name: frontend-proxy + build: + context: ./ + dockerfile: src/frontendproxy/Dockerfile + deploy: + resources: + limits: + memory: 50M + ports: + - "${ENVOY_PORT}:${ENVOY_PORT}" + - 10000:10000 + environment: + - FRONTEND_PORT + - FRONTEND_HOST + - FEATURE_FLAG_SERVICE_PORT + - FEATURE_FLAG_SERVICE_HOST + - LOCUST_WEB_HOST + - LOCUST_WEB_PORT + - GRAFANA_SERVICE_PORT + - GRAFANA_SERVICE_HOST + - JAEGER_SERVICE_PORT + - JAEGER_SERVICE_HOST + - OTEL_COLLECTOR_HOST + - OTEL_COLLECTOR_PORT + - ENVOY_PORT + depends_on: + frontend: + condition: service_started + loadgenerator: + condition: service_started + jaeger: + condition: service_started + grafana: + condition: service_started + + # Load Generator + loadgenerator: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-loadgenerator + container_name: load-generator + build: + context: ./ + dockerfile: ./src/loadgenerator/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-loadgenerator + deploy: + resources: + limits: + memory: 120M + restart: unless-stopped + ports: + - "${LOCUST_WEB_PORT}" + environment: + - LOCUST_WEB_PORT + - LOCUST_USERS + - LOCUST_HOST + - LOCUST_HEADLESS + - LOCUST_AUTOSTART + - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://${OTEL_COLLECTOR_HOST}:4318/v1/traces + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=loadgenerator + - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python + depends_on: + frontend: + condition: service_started + logging: *logging + + # Payment service + paymentservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-paymentservice + container_name: payment-service + build: + context: ./ + dockerfile: ./src/paymentservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-paymentservice + deploy: + resources: + limits: + memory: 120M + restart: unless-stopped + ports: + - "${PAYMENT_SERVICE_PORT}" + environment: + - PAYMENT_SERVICE_PORT + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=paymentservice + depends_on: + otelcol: + condition: service_started + logging: *logging + + # Product Catalog service + productcatalogservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-productcatalogservice + container_name: product-catalog-service + build: + context: ./ + dockerfile: ./src/productcatalogservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-productcatalogservice + deploy: + resources: + limits: + memory: 20M + restart: unless-stopped + ports: + - "${PRODUCT_CATALOG_SERVICE_PORT}" + environment: + - PRODUCT_CATALOG_SERVICE_PORT + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=productcatalogservice + depends_on: + otelcol: + condition: service_started + logging: *logging + + # Quote service + quoteservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-quoteservice + container_name: quote-service + build: + context: ./ + dockerfile: ./src/quoteservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-quoteservice + deploy: + resources: + limits: + memory: 40M + restart: unless-stopped + ports: + - "${QUOTE_SERVICE_PORT}" + environment: + - OTEL_EXPORTER_OTLP_ENDPOINT=http://${OTEL_COLLECTOR_HOST}:4318 + - OTEL_PHP_AUTOLOAD_ENABLED=true + - QUOTE_SERVICE_PORT + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=quoteservice + depends_on: + otelcol: + condition: service_started + logging: *logging + + # Recommendation service + recommendationservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-recommendationservice + container_name: recommendation-service + build: + context: ./ + dockerfile: ./src/recommendationservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-recommendationservice + deploy: + resources: + limits: + memory: 50M + restart: unless-stopped + ports: + - "${RECOMMENDATION_SERVICE_PORT}" + environment: + - RECOMMENDATION_SERVICE_PORT + - PRODUCT_CATALOG_SERVICE_ADDR + - OTEL_PYTHON_LOG_CORRELATION=true + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=recommendationservice + - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python + depends_on: + productcatalogservice: + condition: service_started + otelcol: + condition: service_started + logging: *logging + + # Shipping service + shippingservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-shippingservice + container_name: shipping-service + build: + context: ./ + dockerfile: ./src/shippingservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-shippingservice + deploy: + resources: + limits: + memory: 20M + restart: unless-stopped + ports: + - "${SHIPPING_SERVICE_PORT}" + environment: + - SHIPPING_SERVICE_PORT + - QUOTE_SERVICE_ADDR + - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://${OTEL_COLLECTOR_HOST}:4317/v1/traces + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=shippingservice + depends_on: + otelcol: + condition: service_started + logging: *logging + + # ****************** + # Dependent Services + # ****************** + # Redis used by Cart service + redis-cart: + image: redis:alpine + container_name: redis-cart + user: redis + deploy: + resources: + limits: + memory: 20M + restart: unless-stopped + ports: + - "${REDIS_PORT}" + logging: *logging + + + # ******************** + # Telemetry Components + # ******************** + # Jaeger + jaeger: + image: jaegertracing/all-in-one + container_name: jaeger + command: + - "--memory.max-traces" + - "10000" + - "--query.base-path" + - "/jaeger/ui" + - "--prometheus.server-url" + - "http://${PROMETHEUS_ADDR}" + deploy: + resources: + limits: + memory: 300M + restart: unless-stopped + ports: + - "${JAEGER_SERVICE_PORT}" # Jaeger UI + - "4317" # OTLP gRPC default port + environment: + - COLLECTOR_OTLP_ENABLED=true + - METRICS_STORAGE_TYPE=prometheus + logging: *logging + + # Grafana + grafana: + image: grafana/grafana:9.4.7 + container_name: grafana + deploy: + resources: + limits: + memory: 100M + volumes: + - ./src/grafana/grafana.ini:/etc/grafana/grafana.ini + - ./src/grafana/provisioning/:/etc/grafana/provisioning/ + ports: + - "${GRAFANA_SERVICE_PORT}" + logging: *logging + + # OpenTelemetry Collector + otelcol: + image: otel/opentelemetry-collector-contrib:0.76.1 + container_name: otel-col + deploy: + resources: + limits: + memory: 125M + restart: unless-stopped + command: [ "--config=/etc/otelcol-config.yml", "--config=/etc/otelcol-observability.yml", "--config=/etc/otelcol-config-extras.yml" ] + volumes: + - ./src/otelcollector/otelcol-config.yml:/etc/otelcol-config.yml + - ./src/otelcollector/otelcol-observability.yml:/etc/otelcol-observability.yml + - ./src/otelcollector/otelcol-config-extras.yml:/etc/otelcol-config-extras.yml + ports: + - "4317" # OTLP over gRPC receiver + - "4318:4318" # OTLP over HTTP receiver + - "9464" # Prometheus exporter + - "8888" # metrics endpoint + depends_on: + - jaeger + logging: *logging + + # Prometheus + prometheus: + image: quay.io/prometheus/prometheus:v2.43.0 + container_name: prometheus + command: + - --web.console.templates=/etc/prometheus/consoles + - --web.console.libraries=/etc/prometheus/console_libraries + - --storage.tsdb.retention.time=1h + - --config.file=/etc/prometheus/prometheus-config.yaml + - --storage.tsdb.path=/prometheus + - --web.enable-lifecycle + - --web.route-prefix=/ + - --enable-feature=exemplar-storage + volumes: + - ./src/prometheus/prometheus-config.yaml:/etc/prometheus/prometheus-config.yaml + deploy: + resources: + limits: + memory: 300M + ports: + - "${PROMETHEUS_SERVICE_PORT}:${PROMETHEUS_SERVICE_PORT}" + logging: *logging diff --git a/docker-compose.yml b/docker-compose.yml index e7ff7f92b0..f0df3807ac 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,6 @@ # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 - version: '3.9' x-default-logging: &logging driver: "json-file" @@ -70,7 +69,8 @@ services: - OTEL_LOGS_EXPORTER=otlp - OTEL_SERVICE_NAME=adservice depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # Cart service @@ -91,15 +91,16 @@ services: - "${CART_SERVICE_PORT}" environment: - CART_SERVICE_PORT - - FEATURE_FLAG_GRPC_SERVICE_ADDR - REDIS_ADDR - OTEL_EXPORTER_OTLP_ENDPOINT - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=cartservice - ASPNETCORE_URLS=http://*:${CART_SERVICE_PORT} depends_on: - - redis-cart - - otelcol + redis-cart: + condition: service_started + otelcol: + condition: service_started logging: *logging # Checkout service @@ -173,7 +174,8 @@ services: - OTEL_EXPORTER_OTLP_ENDPOINT - OTEL_RESOURCE_ATTRIBUTES=${OTEL_RESOURCE_ATTRIBUTES},service.name=currencyservice # The C++ SDK does not support OTEL_SERVICE_NAME depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # Email service @@ -198,7 +200,8 @@ services: - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=emailservice depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # Feature Flag service @@ -293,15 +296,24 @@ services: - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE - WEB_OTEL_SERVICE_NAME=frontend-web depends_on: - - adservice - - cartservice - - checkoutservice - - currencyservice - - otelcol - - productcatalogservice - - quoteservice - - recommendationservice - - shippingservice + adservice: + condition: service_started + cartservice: + condition: service_started + checkoutservice: + condition: service_started + currencyservice: + condition: service_started + productcatalogservice: + condition: service_started + quoteservice: + condition: service_started + recommendationservice: + condition: service_started + shippingservice: + condition: service_started + otelcol: + condition: service_started logging: *logging # Frontend Proxy (Envoy) @@ -334,10 +346,16 @@ services: - OTEL_COLLECTOR_PORT_HTTP - ENVOY_PORT depends_on: - - frontend - - featureflagservice - - loadgenerator - - grafana + frontend: + condition: service_started + featureflagservice: + condition: service_started + loadgenerator: + condition: service_started + jaeger: + condition: service_started + grafana: + condition: service_started # Load Generator loadgenerator: @@ -366,7 +384,8 @@ services: - OTEL_SERVICE_NAME=loadgenerator - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python depends_on: - - frontend + frontend: + condition: service_started logging: *logging # Payment service @@ -392,7 +411,8 @@ services: - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=paymentservice depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # Product Catalog service @@ -419,7 +439,8 @@ services: - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=productcatalogservice depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # Quote service @@ -445,7 +466,8 @@ services: - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=quoteservice depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # Recommendation service @@ -475,9 +497,12 @@ services: - OTEL_SERVICE_NAME=recommendationservice - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python depends_on: - - productcatalogservice - - otelcol - - featureflagservice + featureflagservice: + condition: service_started + productcatalogservice: + condition: service_started + otelcol: + condition: service_started logging: *logging # Shipping service @@ -503,7 +528,8 @@ services: - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=shippingservice depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # ****************** @@ -625,9 +651,10 @@ services: limits: memory: 125M restart: unless-stopped - command: [ "--config=/etc/otelcol-config.yml", "--config=/etc/otelcol-config-extras.yml" ] + command: [ "--config=/etc/otelcol-config.yml", "--config=/etc/otelcol-observability.yml", "--config=/etc/otelcol-config-extras.yml" ] volumes: - ./src/otelcollector/otelcol-config.yml:/etc/otelcol-config.yml + - ./src/otelcollector/otelcol-observability.yml:/etc/otelcol-observability.yml - ./src/otelcollector/otelcol-config-extras.yml:/etc/otelcol-config-extras.yml ports: - "4317" # OTLP over gRPC receiver diff --git a/src/adservice/src/main/java/oteldemo/AdService.java b/src/adservice/src/main/java/oteldemo/AdService.java index baa4e9f2e8..549c84ffa6 100644 --- a/src/adservice/src/main/java/oteldemo/AdService.java +++ b/src/adservice/src/main/java/oteldemo/AdService.java @@ -74,13 +74,12 @@ private void start() throws IOException { String featureFlagServiceAddr = Optional.ofNullable(System.getenv("FEATURE_FLAG_GRPC_SERVICE_ADDR")) - .orElseThrow( - () -> - new IllegalStateException( - "environment vars: FEATURE_FLAG_GRPC_SERVICE_ADDR must not be null")); - FeatureFlagServiceBlockingStub featureFlagServiceStub = - oteldemo.FeatureFlagServiceGrpc.newBlockingStub( - ManagedChannelBuilder.forTarget(featureFlagServiceAddr).usePlaintext().build()); + .orElse(""); + FeatureFlagServiceBlockingStub featureFlagServiceStub = null; + if (!featureFlagServiceAddr.isEmpty()) { + featureFlagServiceStub = oteldemo.FeatureFlagServiceGrpc.newBlockingStub( + ManagedChannelBuilder.forTarget(featureFlagServiceAddr).usePlaintext().build()); + } server = ServerBuilder.forPort(port) @@ -195,6 +194,10 @@ public void getAds(AdRequest req, StreamObserver responseObserver) { } boolean checkAdFailure() { + if (featureFlagServiceStub == null) { + return false; + } + // Flip a coin and fail 1/10th of the time if feature flag is enabled if (random.nextInt(10) != 1) { return false; diff --git a/src/cartservice/src/featureflags/FeatureFlagHelper.cs b/src/cartservice/src/featureflags/FeatureFlagHelper.cs index af9cf3d291..7256d8dcb2 100644 --- a/src/cartservice/src/featureflags/FeatureFlagHelper.cs +++ b/src/cartservice/src/featureflags/FeatureFlagHelper.cs @@ -13,13 +13,23 @@ public class FeatureFlagHelper public FeatureFlagHelper() { - var featureFlagServiceUri = new Uri($"http://{Environment.GetEnvironmentVariable("FEATURE_FLAG_GRPC_SERVICE_ADDR")}"); - var channel = Grpc.Net.Client.GrpcChannel.ForAddress(featureFlagServiceUri); - _featureFlagServiceClient = new FeatureFlagService.FeatureFlagServiceClient(channel); + var featureFlagServiceAddress = Environment.GetEnvironmentVariable("FEATURE_FLAG_GRPC_SERVICE_ADDR"); + if (string.IsNullOrEmpty(featureFlagServiceAddress)) + { + _featureFlagServiceClient = null; + } else { + var featureFlagServiceUri = new Uri($"http://{Environment.GetEnvironmentVariable("FEATURE_FLAG_GRPC_SERVICE_ADDR")}"); + var channel = Grpc.Net.Client.GrpcChannel.ForAddress(featureFlagServiceUri); + _featureFlagServiceClient = new FeatureFlagService.FeatureFlagServiceClient(channel); + } } public async Task GenerateCartError() { + if (_featureFlagServiceClient == null) + { + return false; + } if (Random.Next(10) != 1) { return false; diff --git a/src/checkoutservice/main.go b/src/checkoutservice/main.go index 5f0ebe704d..af4953df73 100644 --- a/src/checkoutservice/main.go +++ b/src/checkoutservice/main.go @@ -159,11 +159,13 @@ func main() { mustMapEnv(&svc.currencySvcAddr, "CURRENCY_SERVICE_ADDR") mustMapEnv(&svc.emailSvcAddr, "EMAIL_SERVICE_ADDR") mustMapEnv(&svc.paymentSvcAddr, "PAYMENT_SERVICE_ADDR") - mustMapEnv(&svc.kafkaBrokerSvcAddr, "KAFKA_SERVICE_ADDR") + svc.kafkaBrokerSvcAddr = os.Getenv("KAFKA_SERVICE_ADDR") - svc.KafkaProducerClient, err = kafka.CreateKafkaProducer([]string{svc.kafkaBrokerSvcAddr}, log) - 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) @@ -277,7 +279,10 @@ func (cs *checkoutService) PlaceOrder(ctx context.Context, req *pb.PlaceOrderReq log.Infof("order confirmation email sent to %q", req.Email) } - cs.sendToPostProcessor(ctx, orderResult) + // send to kafka only if kafka broker address is set + if cs.kafkaBrokerSvcAddr != "" { + cs.sendToPostProcessor(ctx, orderResult) + } resp := &pb.PlaceOrderResponse{Order: orderResult} return resp, nil diff --git a/src/otelcollector/otelcol-config.yml b/src/otelcollector/otelcol-config.yml index 6e91cce050..27a6f20a63 100644 --- a/src/otelcollector/otelcol-config.yml +++ b/src/otelcollector/otelcol-config.yml @@ -13,16 +13,7 @@ receivers: - "https://*" exporters: - otlp: - endpoint: "jaeger:4317" - tls: - insecure: true logging: - prometheus: - endpoint: "otelcol:9464" - resource_to_telemetry_conversion: - enabled: true - enable_open_metrics: true processors: batch: @@ -41,11 +32,11 @@ service: traces: receivers: [otlp] processors: [batch] - exporters: [otlp, logging, spanmetrics] + exporters: [logging, spanmetrics] metrics: receivers: [otlp, spanmetrics] processors: [filter, batch] - exporters: [prometheus, logging] + exporters: [logging] logs: receivers: [otlp] processors: [batch] diff --git a/src/otelcollector/otelcol-observability.yml b/src/otelcollector/otelcol-observability.yml new file mode 100644 index 0000000000..9b7ebd7e2f --- /dev/null +++ b/src/otelcollector/otelcol-observability.yml @@ -0,0 +1,21 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + + +exporters: + otlp: + endpoint: "jaeger:4317" + tls: + insecure: true + prometheus: + endpoint: "otelcol:9464" + resource_to_telemetry_conversion: + enabled: true + enable_open_metrics: true + +service: + pipelines: + traces: + exporters: [otlp, logging, spanmetrics] + metrics: + exporters: [prometheus, logging] diff --git a/src/productcatalogservice/main.go b/src/productcatalogservice/main.go index 51bd43420c..c372772011 100644 --- a/src/productcatalogservice/main.go +++ b/src/productcatalogservice/main.go @@ -126,7 +126,7 @@ func main() { svc := &productCatalog{} var port string mustMapEnv(&port, "PRODUCT_CATALOG_SERVICE_PORT") - mustMapEnv(&svc.featureFlagSvcAddr, "FEATURE_FLAG_GRPC_SERVICE_ADDR") + svc.featureFlagSvcAddr = os.Getenv("FEATURE_FLAG_GRPC_SERVICE_ADDR") log.Infof("ProductCatalogService gRPC server started on port: %s", port) @@ -245,7 +245,7 @@ func (p *productCatalog) SearchProducts(ctx context.Context, req *pb.SearchProdu } func (p *productCatalog) checkProductFailure(ctx context.Context, id string) bool { - if id != "OLJCESPC7Z" { + if id != "OLJCESPC7Z" || p.featureFlagSvcAddr == "" { return false } diff --git a/src/recommendationservice/recommendation_server.py b/src/recommendationservice/recommendation_server.py index e996193bf0..88f03f368c 100644 --- a/src/recommendationservice/recommendation_server.py +++ b/src/recommendationservice/recommendation_server.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 #!/usr/bin/python @@ -34,6 +33,7 @@ cached_ids = [] first_run = True + class RecommendationService(demo_pb2_grpc.RecommendationServiceServicer): def ListRecommendations(self, request, context): prod_list = get_product_list(request.product_ids) @@ -107,16 +107,21 @@ def get_product_list(request_product_ids): return prod_list + def must_map_env(key: str): value = os.environ.get(key) if value is None: raise Exception(f'{key} environment variable must be set') return value + def check_feature_flag(flag_name: str): + if feature_flag_stub is None: + return False flag = feature_flag_stub.GetFlag(demo_pb2.GetFlagRequest(name=flag_name)).flag return flag.enabled + if __name__ == "__main__": service_name = must_map_env('OTEL_SERVICE_NAME') @@ -143,11 +148,14 @@ def check_feature_flag(flag_name: str): logger.addHandler(handler) catalog_addr = must_map_env('PRODUCT_CATALOG_SERVICE_ADDR') - ff_addr = must_map_env('FEATURE_FLAG_GRPC_SERVICE_ADDR') pc_channel = grpc.insecure_channel(catalog_addr) - ff_channel = grpc.insecure_channel(ff_addr) product_catalog_stub = demo_pb2_grpc.ProductCatalogServiceStub(pc_channel) - feature_flag_stub = demo_pb2_grpc.FeatureFlagServiceStub(ff_channel) + + ff_addr = os.environ.get('FEATURE_FLAG_GRPC_SERVICE_ADDR') + feature_flag_stub = None + if ff_addr is not None: + ff_channel = grpc.insecure_channel(ff_addr) + feature_flag_stub = demo_pb2_grpc.FeatureFlagServiceStub(ff_channel) # Create gRPC server server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))