diff --git a/CHANGELOG.md b/CHANGELOG.md index aa92cd0745..4991a0810a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,8 @@ significant modifications will be credited to OpenTelemetry Authors. ([#290](https://github.com/open-telemetry/opentelemetry-demo/pull/290)) * Added Frontend [Cypress](https://www.cypress.io/) E2E tests ([#298](https://github.com/open-telemetry/opentelemetry-demo/pull/298)) +* Add HEALTHCHECK to all services +([#296](https://github.com/open-telemetry/opentelemetry-demo/pull/296)) * Added baggage support in CurrencyService ([#281](https://github.com/open-telemetry/opentelemetry-demo/pull/281)) * Added error for a specific product based on a feature flag diff --git a/docker-compose.yml b/docker-compose.yml index b12d61810a..2c83e09541 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -147,6 +147,8 @@ services: depends_on: - otelcol logging: *logging + healthcheck: + test: curl -s --fail ${EMAIL_SERVICE_ADDR}/_healthz || exit 1 # Frontend frontend: @@ -182,6 +184,8 @@ services: - recommendationservice - shippingservice logging: *logging + healthcheck: + test: curl -s --fail ${FRONTEND_ADDR}/api/health || exit 1 # Frontend Tests frontendTests: diff --git a/src/adservice/Dockerfile b/src/adservice/Dockerfile index cb847defd0..e6908e1461 100644 --- a/src/adservice/Dockerfile +++ b/src/adservice/Dockerfile @@ -29,9 +29,11 @@ FROM openjdk:18-slim ARG version=1.16.0 WORKDIR /usr/src/app/ +COPY --from=includer --chmod=755 /grpc_health_probe /include/ COPY --from=builder /usr/src/app/ ./ ADD https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v$version/opentelemetry-javaagent.jar /app/opentelemetry-javaagent.jar ENV JAVA_TOOL_OPTIONS=-javaagent:/app/opentelemetry-javaagent.jar +HEALTHCHECK CMD /include/grpc_health_probe -addr :${AD_SERVICE_PORT} EXPOSE ${AD_SERVICE_PORT} ENTRYPOINT [ "./build/install/hipstershop/bin/AdService" ] diff --git a/src/cartservice/src/Dockerfile b/src/cartservice/src/Dockerfile index b76af3a281..6ce43b724a 100644 --- a/src/cartservice/src/Dockerfile +++ b/src/cartservice/src/Dockerfile @@ -29,7 +29,10 @@ RUN dotnet publish ./src/cartservice.csproj -p:PublishSingleFile=true -r linux-m FROM mcr.microsoft.com/dotnet/runtime-deps:6.0.5-alpine3.15-amd64 WORKDIR /usr/src/app/ + +COPY --from=includer --chmod=755 /grpc_health_probe /include/ COPY --from=builder /cartservice/ ./ +HEALTHCHECK CMD /include/grpc_health_probe -addr :${CART_SERVICE_PORT} EXPOSE ${CART_SERVICE_PORT} ENTRYPOINT [ "./cartservice" ] diff --git a/src/checkoutservice/Dockerfile b/src/checkoutservice/Dockerfile index 421a150947..f89e0aaeff 100644 --- a/src/checkoutservice/Dockerfile +++ b/src/checkoutservice/Dockerfile @@ -34,6 +34,8 @@ FROM alpine WORKDIR /usr/src/app/ COPY --from=builder /go/bin/checkoutservice/ ./ +COPY --from=includer --chmod=755 /grpc_health_probe /include/ +HEALTHCHECK CMD /include/grpc_health_probe -addr :${CHECKOUT_SERVICE_PORT} EXPOSE ${CHECKOUT_SERVICE_PORT} ENTRYPOINT [ "./checkoutservice" ] diff --git a/src/checkoutservice/main.go b/src/checkoutservice/main.go index 352bd28f5d..d2125837fc 100644 --- a/src/checkoutservice/main.go +++ b/src/checkoutservice/main.go @@ -43,7 +43,8 @@ import ( pb "github.com/open-telemetry/opentelemetry-demo/src/checkoutservice/genproto/hipstershop" money "github.com/open-telemetry/opentelemetry-demo/src/checkoutservice/money" - healthpb "google.golang.org/grpc/health/grpc_health_v1" + "google.golang.org/grpc/health" + "google.golang.org/grpc/health/grpc_health_v1" ) const ( @@ -125,7 +126,7 @@ func main() { grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor()), ) pb.RegisterCheckoutServiceServer(srv, svc) - healthpb.RegisterHealthServer(srv, svc) + grpc_health_v1.RegisterHealthServer(srv, health.NewServer()) log.Infof("starting to listen on tcp: %q", lis.Addr().String()) err = srv.Serve(lis) log.Fatal(err) @@ -139,14 +140,6 @@ func mustMapEnv(target *string, envKey string) { *target = v } -func (cs *checkoutService) Check(ctx context.Context, req *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) { - return &healthpb.HealthCheckResponse{Status: healthpb.HealthCheckResponse_SERVING}, nil -} - -func (cs *checkoutService) Watch(req *healthpb.HealthCheckRequest, ws healthpb.Health_WatchServer) error { - return status.Errorf(codes.Unimplemented, "health check via Watch not implemented") -} - func (cs *checkoutService) PlaceOrder(ctx context.Context, req *pb.PlaceOrderRequest) (*pb.PlaceOrderResponse, error) { span := trace.SpanFromContext(ctx) span.SetAttributes( diff --git a/src/currencyservice/Dockerfile b/src/currencyservice/Dockerfile index 5a3684e580..a36aa61cb7 100644 --- a/src/currencyservice/Dockerfile +++ b/src/currencyservice/Dockerfile @@ -50,10 +50,13 @@ RUN git clone https://github.com/open-telemetry/opentelemetry-cpp \ && cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DWITH_OTLP=ON \ && make -j install && cd ../.. && rm -rf opentelemetry-cpp +COPY --from=includer --chmod=755 /grpc_health_probe /include/ COPY . /currencyservice RUN cd /currencyservice \ && mkdir -p build && cd build \ && cmake .. && make -j install -ENTRYPOINT /usr/local/bin/currencyservice ${CURRENCY_SERVICE_PORT} +HEALTHCHECK CMD /include/grpc_health_probe -addr :${CURRENCY_SERVICE_PORT} +EXPOSE ${CURRENCY_SERVICE_PORT} +ENTRYPOINT [ "/usr/local/bin/currencyservice" ] diff --git a/src/currencyservice/src/server.cpp b/src/currencyservice/src/server.cpp index 38420e45b4..5bd7035273 100644 --- a/src/currencyservice/src/server.cpp +++ b/src/currencyservice/src/server.cpp @@ -276,12 +276,7 @@ void RunServer(uint16_t port) int main(int argc, char **argv) { - if (argc < 2) { - std::cout << "Usage: currencyservice "; - return 0; - } - - uint16_t port = atoi(argv[1]); + uint16_t port = atoi(std::getenv("CURRENCY_SERVICE_PORT")); std::cout << "Port: " << port << "\n"; diff --git a/src/emailservice/Dockerfile b/src/emailservice/Dockerfile index 1b6d1d8cd4..774765424f 100644 --- a/src/emailservice/Dockerfile +++ b/src/emailservice/Dockerfile @@ -14,7 +14,7 @@ FROM ruby:3.1.2-slim -RUN apt-get update -y && apt-get install -y build-essential +RUN apt-get update -y && apt-get install -y build-essential curl COPY Gemfile* ./ diff --git a/src/emailservice/email_server.rb b/src/emailservice/email_server.rb index 1c4df4e9ff..ce0d26b29b 100644 --- a/src/emailservice/email_server.rb +++ b/src/emailservice/email_server.rb @@ -12,6 +12,10 @@ c.use "OpenTelemetry::Instrumentation::Sinatra" end +get "/_healthz" do + "ok" +end + post "/send_order_confirmation" do data = JSON.parse(request.body.read, object_class: OpenStruct) diff --git a/src/frontend/Dockerfile b/src/frontend/Dockerfile index 327a399033..c3f6f9e560 100644 --- a/src/frontend/Dockerfile +++ b/src/frontend/Dockerfile @@ -6,6 +6,8 @@ WORKDIR /app COPY ./src/frontend/package*.json ./ RUN npm ci +# ----------------------------------------------------------------------------- + FROM node:16-alpine AS builder RUN apk add --no-cache libc6-compat protoc WORKDIR /app @@ -16,9 +18,11 @@ COPY ./src/frontend . RUN npm run grpc:generate RUN npm run build +# ----------------------------------------------------------------------------- + FROM node:16-alpine AS runner WORKDIR /app -RUN apk add --no-cache protoc +RUN apk add --no-cache protoc curl ENV NODE_ENV=production @@ -29,6 +33,7 @@ COPY --from=builder /app/next.config.js ./ COPY --from=builder /app/utils/telemetry/Instrumentation.js ./ COPY --from=builder /app/public ./public COPY --from=builder /app/package.json ./package.json + COPY --from=deps /app/node_modules ./node_modules COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ @@ -38,5 +43,4 @@ USER nextjs ENV PORT 8080 EXPOSE ${PORT} - CMD ["npm", "start"] diff --git a/src/frontend/pages/api/health.ts b/src/frontend/pages/api/health.ts new file mode 100644 index 0000000000..1c4d09d1c5 --- /dev/null +++ b/src/frontend/pages/api/health.ts @@ -0,0 +1,7 @@ +import type { NextApiRequest, NextApiResponse } from 'next'; + +type TResponse = string; + +export default function handler(_: NextApiRequest, res: NextApiResponse) { + return res.status(200).send("ok") +} diff --git a/src/includer/Dockerfile b/src/includer/Dockerfile new file mode 100644 index 0000000000..f6985b1a0b --- /dev/null +++ b/src/includer/Dockerfile @@ -0,0 +1,3 @@ +FROM alpine + +ADD https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/v0.4.11/grpc_health_probe-linux-amd64 /grpc_health_probe diff --git a/src/paymentservice/Dockerfile b/src/paymentservice/Dockerfile index 6c03e62579..8bff19cd74 100644 --- a/src/paymentservice/Dockerfile +++ b/src/paymentservice/Dockerfile @@ -28,9 +28,11 @@ USER node WORKDIR /usr/src/app/ ENV NODE_ENV production +COPY --from=includer --chmod=755 /grpc_health_probe /include/ COPY --chown=node:node --from=build /usr/src/app/node_modules/ ./node_modules/ COPY ./src/paymentservice/ ./ COPY ./pb/demo.proto ./ +HEALTHCHECK CMD /include/grpc_health_probe -addr :${PAYMENT_SERVICE_PORT} EXPOSE ${PAYMENT_SERVICE_PORT} ENTRYPOINT [ "node", "--require", "./tracing.js", "./index.js" ] diff --git a/src/productcatalogservice/Dockerfile b/src/productcatalogservice/Dockerfile index dc470ee6a4..29cff34fff 100644 --- a/src/productcatalogservice/Dockerfile +++ b/src/productcatalogservice/Dockerfile @@ -32,12 +32,14 @@ RUN go build -o /go/bin/productcatalogservice/ ./ # ----------------------------------------------------------------------------- -FROM alpine AS release +FROM alpine WORKDIR /usr/src/app/ +COPY --from=includer --chmod=755 /grpc_health_probe /include/ COPY ./src/productcatalogservice/products.json ./ COPY --from=builder /go/bin/productcatalogservice/ ./ -EXPOSE ${PRODUCT_SERVICE_PORT} +HEALTHCHECK CMD /include/grpc_health_probe -addr :${PRODUCT_CATALOG_SERVICE_PORT} +EXPOSE ${PRODUCT_CATALOG_SERVICE_PORT} ENTRYPOINT [ "./productcatalogservice" ] diff --git a/src/productcatalogservice/server.go b/src/productcatalogservice/server.go index 70b2285741..fc2f77032e 100644 --- a/src/productcatalogservice/server.go +++ b/src/productcatalogservice/server.go @@ -29,7 +29,8 @@ import ( "time" pb "github.com/opentelemetry/opentelemetry-demo/src/productcatalogservice/genproto/hipstershop" - healthpb "google.golang.org/grpc/health/grpc_health_v1" + "google.golang.org/grpc/health" + "google.golang.org/grpc/health/grpc_health_v1" "github.com/sirupsen/logrus" @@ -154,7 +155,7 @@ func run(port string) string { mustMapEnv(&svc.featureFlagSvcAddr, "FEATURE_FLAG_GRPC_SERVICE_ADDR") pb.RegisterProductCatalogServiceServer(srv, svc) - healthpb.RegisterHealthServer(srv, svc) + grpc_health_v1.RegisterHealthServer(srv, health.NewServer()) go srv.Serve(l) return l.Addr().String() } @@ -198,14 +199,6 @@ func mustMapEnv(target *string, envKey string) { *target = v } -func (p *productCatalog) Check(ctx context.Context, req *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) { - return &healthpb.HealthCheckResponse{Status: healthpb.HealthCheckResponse_SERVING}, nil -} - -func (p *productCatalog) Watch(req *healthpb.HealthCheckRequest, ws healthpb.Health_WatchServer) error { - return status.Errorf(codes.Unimplemented, "health check via Watch not implemented") -} - func (p *productCatalog) ListProducts(ctx context.Context, req *pb.Empty) (*pb.ListProductsResponse, error) { span := trace.SpanFromContext(ctx) diff --git a/src/recommendationservice/Dockerfile b/src/recommendationservice/Dockerfile index bcc139d87c..988ffe8447 100644 --- a/src/recommendationservice/Dockerfile +++ b/src/recommendationservice/Dockerfile @@ -16,15 +16,15 @@ FROM python:3.10-slim WORKDIR /usr/src/app/ +COPY --from=includer --chmod=0755 /grpc_health_probe /include/ COPY ./src/recommendationservice/ ./ COPY ./pb/ ./proto/ RUN pip install --upgrade pip RUN pip install -r ./requirements.txt - -# add files into working directory RUN python -m pip install grpcio-tools RUN python -m grpc_tools.protoc -I=./proto/ --python_out=./ --grpc_python_out=./ ./proto/demo.proto +HEALTHCHECK CMD /include/grpc_health_probe -addr :${RECOMMENDATION_SERVICE_PORT} EXPOSE ${RECOMMENDATION_SERVICE_PORT} ENTRYPOINT [ "opentelemetry-instrument", "python", "recommendation_server.py" ] diff --git a/src/shippingservice/Dockerfile b/src/shippingservice/Dockerfile index e198fee9b6..06fe7d9a62 100644 --- a/src/shippingservice/Dockerfile +++ b/src/shippingservice/Dockerfile @@ -9,13 +9,15 @@ COPY ./src/shippingservice/ /app/ COPY ./pb/ /app/proto/ RUN cargo build -r --features="dockerproto" -FROM alpine as release +# ----------------------------------------------------------------------------- + +FROM alpine RUN apk add --no-cache ca-certificates -RUN GRPC_HEALTH_PROBE_VERSION=v0.4.7 && \ - wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ - chmod +x /bin/grpc_health_probe + WORKDIR /app +COPY --from=includer --chmod=0755 /grpc_health_probe /include/ COPY --from=builder /app/target/release/shippingservice /shippingservice +HEALTHCHECK CMD /include/grpc_health_probe -addr :${SHIPPING_SERVICE_PORT} EXPOSE ${SHIPPING_SERVICE_PORT} ENTRYPOINT ["/shippingservice"]