diff --git a/src/backend/backend.code-workspace b/src/backend/backend.code-workspace index a340cf6d7..e1e1f34e1 100644 --- a/src/backend/backend.code-workspace +++ b/src/backend/backend.code-workspace @@ -47,7 +47,7 @@ "path": "./load-tests" }, { - "name": "deployment-manifests", + "name": "k8s-manifests", "path": "../../manifests" }, { diff --git a/src/backend/docker/docker-compose.override.yml b/src/backend/docker/docker-compose.override.yml index dcf72ae9c..69f3e7d30 100755 --- a/src/backend/docker/docker-compose.override.yml +++ b/src/backend/docker/docker-compose.override.yml @@ -27,6 +27,7 @@ services: environment: - ENABLE_TEST_CARDS=false - OTEL_EXPORTER_OTLP_ENDPOINT=otel-collector:4317 + - BASE_PATH=/payment checkout-api: environment: diff --git a/src/backend/docker/docker-compose.traefik.yml b/src/backend/docker/docker-compose.traefik.yml index 57ae1b233..44f4fe0e7 100644 --- a/src/backend/docker/docker-compose.traefik.yml +++ b/src/backend/docker/docker-compose.traefik.yml @@ -5,7 +5,7 @@ services: image: "traefik:v3.0" container_name: "traefik" command: - # - "--log.level=DEBUG" + - "--log.level=DEBUG" - "--api.insecure=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" diff --git a/src/backend/docker/docker-compose.yml b/src/backend/docker/docker-compose.yml index 05eee0efe..23e18c086 100644 --- a/src/backend/docker/docker-compose.yml +++ b/src/backend/docker/docker-compose.yml @@ -36,6 +36,8 @@ services: depends_on: - redis restart: always + ports: + - 5200 order-api: image: restaurant/order-api @@ -57,6 +59,7 @@ services: build: ./services/payment-api ports: - 8083:8080 + - 8980:8980 # dashboard-app: # image: restaurant/dashboard-app diff --git a/src/backend/services/cart-api/Dockerfile b/src/backend/services/cart-api/Dockerfile index cc2644b5a..20199486c 100644 --- a/src/backend/services/cart-api/Dockerfile +++ b/src/backend/services/cart-api/Dockerfile @@ -1,5 +1,5 @@ #build stage -FROM golang:1.19-alpine AS builder +FROM golang:1.22-alpine AS builder RUN apk add --no-cache git diff --git a/src/backend/services/cart-api/go.mod b/src/backend/services/cart-api/go.mod index 5458f1b3b..3a5d06f0e 100644 --- a/src/backend/services/cart-api/go.mod +++ b/src/backend/services/cart-api/go.mod @@ -1,5 +1,7 @@ module github.com/jurabek/cart-api +go 1.22 + require ( github.com/gin-gonic/gin v1.9.1 github.com/gomodule/redigo v2.0.0+incompatible @@ -96,5 +98,3 @@ require ( google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v3 v3.0.1 // indirect ) - -go 1.19 diff --git a/src/backend/services/cart-api/go.sum b/src/backend/services/cart-api/go.sum index 0483d0034..86922e452 100644 --- a/src/backend/services/cart-api/go.sum +++ b/src/backend/services/cart-api/go.sum @@ -1,5 +1,7 @@ cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= github.com/IBM/sarama v1.42.1 h1:wugyWa15TDEHh2kvq2gAy1IHLjEjuYOYgXz/ruC/OSQ= github.com/IBM/sarama v1.42.1/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= @@ -24,6 +26,7 @@ github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLI github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -39,10 +42,13 @@ github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1 github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= +github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= @@ -61,6 +67,7 @@ github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUue github.com/go-openapi/swag v0.22.7 h1:JWrc1uc/P9cSomxfnsFSVWoE1FW6bNbrVPmpQYpCcR8= github.com/go-openapi/swag v0.22.7/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -71,6 +78,7 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= @@ -80,6 +88,7 @@ github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNu github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -118,7 +127,9 @@ github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/4 github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -151,6 +162,7 @@ github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnA github.com/redis/go-redis/v9 v9.0.5 h1:CuQcn5HIEeK7BgElubPP8CGtE0KakrnbBSTLjathl5o= github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -183,6 +195,7 @@ go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0. go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= go.opentelemetry.io/contrib/propagators/b3 v1.22.0 h1:Okbgv0pWHMQq+mF7H2o1mucJ5PvxKFq2c8cyqoXfeaQ= +go.opentelemetry.io/contrib/propagators/b3 v1.22.0/go.mod h1:N3z0ycFRhsVZ+tG/uavMxHvOvFE95QM6gwW1zSqT9dQ= go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= @@ -198,6 +211,7 @@ go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40 go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= @@ -208,6 +222,7 @@ golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -217,9 +232,11 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -248,7 +265,9 @@ golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= @@ -261,6 +280,7 @@ google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7 google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/src/backend/services/checkout-api/src/cart/cartService.ts b/src/backend/services/checkout-api/src/cart/cartService.ts index fea31b178..1653de845 100644 --- a/src/backend/services/checkout-api/src/cart/cartService.ts +++ b/src/backend/services/checkout-api/src/cart/cartService.ts @@ -1,9 +1,9 @@ -import { config } from '../config'; +import { config } from '../config/config'; import * as grpc from '@grpc/grpc-js' import * as protoLoader from '@grpc/proto-loader' import { ProtoGrpcType } from '../gen/cart'; import path from 'path' -import { logger } from '../logger'; +import { logger } from '../utils/logger'; import { GetCartRequest } from '../gen/cart/GetCartRequest'; import { GetCartResponse__Output } from '../gen/cart/GetCartResponse'; diff --git a/src/backend/services/checkout-api/src/checkout/checkout.ts b/src/backend/services/checkout-api/src/checkout/checkout.ts index 8982ac03b..ee0db9b11 100644 --- a/src/backend/services/checkout-api/src/checkout/checkout.ts +++ b/src/backend/services/checkout-api/src/checkout/checkout.ts @@ -1,7 +1,7 @@ import { randomUUID } from "crypto"; -import { CartItem, CheckoutEvent, UserCheckoutReq } from "../model"; +import { CartItem, CheckoutEvent, UserCheckoutReq } from "../models/model"; import getCustomerCartItems from "../cart/cartService"; -import { logger } from "../logger"; +import { logger } from "../utils/logger"; import checkoutPublisher from "../messagging/publisher"; import { trace, context, ROOT_CONTEXT, SpanStatusCode } from "@opentelemetry/api"; import { pay } from "../payment/paymentService"; diff --git a/src/backend/services/checkout-api/src/config.spec.ts b/src/backend/services/checkout-api/src/config/config.spec.ts similarity index 100% rename from src/backend/services/checkout-api/src/config.spec.ts rename to src/backend/services/checkout-api/src/config/config.spec.ts diff --git a/src/backend/services/checkout-api/src/config.ts b/src/backend/services/checkout-api/src/config/config.ts similarity index 100% rename from src/backend/services/checkout-api/src/config.ts rename to src/backend/services/checkout-api/src/config/config.ts diff --git a/src/backend/services/checkout-api/src/index.ts b/src/backend/services/checkout-api/src/index.ts index 9121269c2..f7e132910 100644 --- a/src/backend/services/checkout-api/src/index.ts +++ b/src/backend/services/checkout-api/src/index.ts @@ -1,10 +1,10 @@ -import { OpenTelemetry } from './tracer'; +import { OpenTelemetry } from './instrumentation'; const otel = OpenTelemetry('checkout-api') otel.start(); -import router from './routes'; -import { logger } from './logger'; -import { config } from './config'; +import router from './routes/routes'; +import { logger } from './utils/logger'; +import { config } from './config/config'; import express from 'express'; const app = express(); diff --git a/src/backend/services/checkout-api/src/tracer.ts b/src/backend/services/checkout-api/src/instrumentation.ts similarity index 100% rename from src/backend/services/checkout-api/src/tracer.ts rename to src/backend/services/checkout-api/src/instrumentation.ts diff --git a/src/backend/services/checkout-api/src/messagging/publisher.ts b/src/backend/services/checkout-api/src/messagging/publisher.ts index d52c70401..da8acb3d5 100644 --- a/src/backend/services/checkout-api/src/messagging/publisher.ts +++ b/src/backend/services/checkout-api/src/messagging/publisher.ts @@ -1,6 +1,6 @@ import { Kafka, Producer, ProducerRecord } from 'kafkajs' -import { config } from '../config' -import { logger } from '../logger' +import { config } from '../config/config' +import { logger } from '../utils/logger' export class Publisher { private producer: Producer diff --git a/src/backend/services/checkout-api/src/model.ts b/src/backend/services/checkout-api/src/models/model.ts similarity index 100% rename from src/backend/services/checkout-api/src/model.ts rename to src/backend/services/checkout-api/src/models/model.ts diff --git a/src/backend/services/checkout-api/src/payment/paymentService.spec.ts b/src/backend/services/checkout-api/src/payment/paymentService.spec.ts index 77f96e796..acdbd4503 100644 --- a/src/backend/services/checkout-api/src/payment/paymentService.spec.ts +++ b/src/backend/services/checkout-api/src/payment/paymentService.spec.ts @@ -2,7 +2,7 @@ import sinon from 'sinon'; import { expect } from "chai"; import type * as grpc from '@grpc/grpc-js' import { paymentService, pay } from "./paymentService"; -import { CartItem, UserCheckoutReq } from "../model"; +import { CartItem, UserCheckoutReq } from "../models/model"; import { PaymentResponse } from '../gen/payment/PaymentResponse'; import { PaymentRequest } from '../gen/payment/PaymentRequest'; diff --git a/src/backend/services/checkout-api/src/payment/paymentService.ts b/src/backend/services/checkout-api/src/payment/paymentService.ts index 1aa755106..428e37058 100644 --- a/src/backend/services/checkout-api/src/payment/paymentService.ts +++ b/src/backend/services/checkout-api/src/payment/paymentService.ts @@ -1,9 +1,9 @@ -import { config } from '../config'; +import { config } from '../config/config'; import * as grpc from '@grpc/grpc-js' import * as protoLoader from '@grpc/proto-loader' import { ProtoGrpcType } from '../gen/payments'; import path from 'path' -import { UserCheckoutReq } from '../model'; +import { UserCheckoutReq } from '../models/model'; import { PaymentResponse__Output } from '../gen/payment/PaymentResponse'; import { PaymentRequest } from '../gen/payment/PaymentRequest'; import { CartItem } from '../gen/cart/CartItem'; diff --git a/src/backend/services/checkout-api/src/routes.ts b/src/backend/services/checkout-api/src/routes/routes.ts similarity index 82% rename from src/backend/services/checkout-api/src/routes.ts rename to src/backend/services/checkout-api/src/routes/routes.ts index 9c1c91adb..7b482e591 100644 --- a/src/backend/services/checkout-api/src/routes.ts +++ b/src/backend/services/checkout-api/src/routes/routes.ts @@ -1,6 +1,6 @@ import express, { Request, Response } from "express"; -import { UserCheckoutReq, UserCheckoutSchema } from "./model"; -import Checkout from "./checkout/checkout"; +import { UserCheckoutReq, UserCheckoutSchema } from "../models/model"; +import Checkout from "../checkout/checkout"; const router = express.Router(); diff --git a/src/backend/services/checkout-api/src/logger.ts b/src/backend/services/checkout-api/src/utils/logger.ts similarity index 100% rename from src/backend/services/checkout-api/src/logger.ts rename to src/backend/services/checkout-api/src/utils/logger.ts diff --git a/src/backend/services/payment-api/Dockerfile b/src/backend/services/payment-api/Dockerfile index 8926ae3fe..067e495aa 100644 --- a/src/backend/services/payment-api/Dockerfile +++ b/src/backend/services/payment-api/Dockerfile @@ -1,5 +1,5 @@ #build stage -FROM golang:1.21-alpine AS builder +FROM golang:1.22-alpine AS builder RUN apk add --no-cache git @@ -22,5 +22,4 @@ RUN apk --no-cache add ca-certificates COPY --from=builder /src ./ CMD ["./payment-api"] -LABEL Name=payment-api Version=0.0.1 -EXPOSE 8080 \ No newline at end of file +LABEL Name=payment-api Version=0.0.1 \ No newline at end of file diff --git a/src/backend/services/payment-api/instrumentation/instrumentation.go b/src/backend/services/payment-api/instrumentation/instrumentation.go new file mode 100644 index 000000000..77d0ad877 --- /dev/null +++ b/src/backend/services/payment-api/instrumentation/instrumentation.go @@ -0,0 +1,120 @@ +package instrumentation + +import ( + "context" + "fmt" + "os" + "time" + + "github.com/rs/zerolog/log" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.17.0" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +type CloseFunc func() + +func StartOTEL(ctx context.Context) (CloseFunc, error) { + res, err := resource.New(ctx, + resource.WithAttributes( + // the service name used to display traces in backends + semconv.ServiceName("payment-api"), + semconv.ServiceVersion("v1"), + ), + ) + if err != nil { + return nil, fmt.Errorf("failed to create resource: %w", err) + } + + ctx, cancel := context.WithTimeout(ctx, time.Second) + defer cancel() + + otelExportEndpoint := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") + if otelExportEndpoint == "" { + otelExportEndpoint = "localhost:4317" + } + conn, err := grpc.DialContext(ctx, otelExportEndpoint, + // Note the use of insecure transport here. TLS is recommended in production. + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithBlock(), + ) + if err != nil { + return nil, fmt.Errorf("failed to create gRPC connection to collector: %w", err) + } + + meterProvider, err := setupMeterProvider(ctx, conn, res) + if err != nil { + return nil, err + } + + traceProvider, err := setupTraceProvider(ctx, conn, res) + if err != nil { + return nil, err + } + + closeFunc := func() { + // Handle shutdown properly so nothing leaks. + if meterErr := meterProvider.Shutdown(ctx ); meterErr != nil { + log.Error().Msg(meterErr.Error()) + } + + if tpErr := traceProvider.Shutdown(ctx); tpErr != nil { + log.Error().Err(tpErr) + } + + if connErr := conn.Close(); connErr != nil { + log.Error().Err(connErr) + } + } + + return closeFunc, nil +} + +func setupMeterProvider(ctx context.Context, conn *grpc.ClientConn, res *resource.Resource) (*metric.MeterProvider, error) { + // Create a meter provider. + // You can pass this instance directly to your instrumented code if it + // accepts a MeterProvider instance. + metricExporter, err := otlpmetricgrpc.New(ctx, otlpmetricgrpc.WithGRPCConn(conn)) + if err != nil { + return nil, err + } + + meterProvider := metric.NewMeterProvider( + metric.WithResource(res), + metric.WithReader(metric.NewPeriodicReader(metricExporter, + // Default is 1m. Set to 3s for demonstrative purposes. + metric.WithInterval(10*time.Second))), + ) + + // Register as global meter provider so that it can be used via otel.Meter + // and accessed using otel.GetMeterProvider. + // Most instrumentation libraries use the global meter provider as default. + // If the global meter provider is not set then a no-op implementation + // is used, which fails to generate data. + otel.SetMeterProvider(meterProvider) + return meterProvider, nil +} + +func setupTraceProvider(ctx context.Context, conn *grpc.ClientConn, res *resource.Resource) (*sdktrace.TracerProvider, error) { + // Set up a trace exporter + traceExporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithGRPCConn(conn)) + if err != nil { + return nil, fmt.Errorf("failed to create trace exporter: %w", err) + } + + tp := sdktrace.NewTracerProvider( + sdktrace.WithSampler(sdktrace.AlwaysSample()), + sdktrace.WithResource(res), + sdktrace.WithBatcher(traceExporter), + ) + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) + return tp, nil +} diff --git a/src/backend/services/payment-api/main.go b/src/backend/services/payment-api/main.go index d125a7e8d..fb44fa64f 100644 --- a/src/backend/services/payment-api/main.go +++ b/src/backend/services/payment-api/main.go @@ -2,41 +2,33 @@ package main import ( "context" - "fmt" "net" + "net/http" "os" "strconv" - "time" grpcsvc "github.com/chayxana/payment-api/grpc" + "github.com/chayxana/payment-api/handlers" + "github.com/chayxana/payment-api/instrumentation" v1 "github.com/chayxana/payment-api/pb/v1" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" - "go.opentelemetry.io/otel/propagation" - "go.opentelemetry.io/otel/sdk/resource" - sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.17.0" - + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/reflection" ) func main() { zerolog.TimeFieldFormat = zerolog.TimeFormatUnix - tp, err := initTracer() + ctx := context.Background() + + closeFunc, err := instrumentation.StartOTEL(ctx) if err != nil { log.Fatal().Err(err) } - defer func() { - if err := tp.Shutdown(context.Background()); err != nil { - log.Error().Err(err) - } - }() + defer closeFunc() lis, err := net.Listen("tcp", ":8080") if err != nil { @@ -57,59 +49,37 @@ func main() { v1.RegisterPaymentServiceServer(s, grpcsvc.NewPaymentServiceGrpc(enableTestCards)) log.Info().Msg("Starting gRPC server on port 8080...") - if err := s.Serve(lis); err != nil { - log.Fatal().Err(err) - } -} + go func() { + if err := s.Serve(lis); err != nil { + log.Fatal().Err(err) + } + }() -func initTracer() (*sdktrace.TracerProvider, error) { - ctx := context.Background() + paymentMethodsHandler := &handlers.PaymentMethodsHandler{} - res, err := resource.New(ctx, - resource.WithAttributes( - // the service name used to display traces in backends - semconv.ServiceName("payment-api"), - ), - ) - if err != nil { - return nil, fmt.Errorf("failed to create resource: %w", err) - } + mux := http.NewServeMux() + mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { + _, err := w.Write([]byte("healthy")) + if err != nil { + log.Error().Err(err) + return + } + w.WriteHeader(http.StatusOK) + }) - // If the OpenTelemetry Collector is running on a local cluster (minikube or - // microk8s), it should be accessible through the NodePort service at the - // `localhost:30080` endpoint. Otherwise, replace `localhost` with the - // endpoint of your cluster. If you run the app inside k8s, then you can - // probably connect directly to the service through dns. - ctx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - - otelExportEndpoint := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") - if otelExportEndpoint == "" { - otelExportEndpoint = "localhost:4317" - } - conn, err := grpc.DialContext(ctx, otelExportEndpoint, - // Note the use of insecure transport here. TLS is recommended in production. - grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithBlock(), - ) - if err != nil { - return nil, fmt.Errorf("failed to create gRPC connection to collector: %w", err) - } + basePath, _ := os.LookupEnv("BASE_PATH") - // Set up a trace exporter - traceExporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithGRPCConn(conn)) - if err != nil { - return nil, fmt.Errorf("failed to create trace exporter: %w", err) - } + mux.HandleFunc(basePath + "/api/v1/paymentMethods", paymentMethodsHandler.GetPaymentMethods) + mux.HandleFunc(basePath + "/api/v1/paymentMethod/{id}", paymentMethodsHandler.GetPaymentMethod) + log.Info().Msg("http server listening 8980...") - tp := sdktrace.NewTracerProvider( - sdktrace.WithSampler(sdktrace.AlwaysSample()), - sdktrace.WithResource(res), - sdktrace.WithBatcher(traceExporter), + otelMux := otelhttp.NewHandler(mux, "server", + otelhttp.WithMessageEvents(otelhttp.ReadEvents, otelhttp.WriteEvents), ) - otel.SetTracerProvider(tp) - otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) - return tp, nil + + if err := http.ListenAndServe(":8980", otelMux); err != nil { + log.Fatal().Err(err) + } } func getenvBool(key string) (bool, error) {