Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[checkout] - add manual tracing instrumentation #164

47 changes: 46 additions & 1 deletion src/checkoutservice/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ import (
"context"
"encoding/json"
"fmt"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"net"
"net/http"
"os"
"strconv"
"time"

"github.com/google/uuid"
Expand All @@ -48,6 +51,7 @@ const (
)

var log *logrus.Logger
var tracer trace.Tracer

func init() {
log = logrus.New()
Expand Down Expand Up @@ -99,6 +103,8 @@ func main() {
}
}()

tracer = tp.Tracer("checkoutservice")

svc := new(checkoutService)
mustMapEnv(&svc.shippingSvcAddr, "SHIPPING_SERVICE_ADDR")
mustMapEnv(&svc.productCatalogSvcAddr, "PRODUCT_CATALOG_SERVICE_ADDR")
Expand Down Expand Up @@ -142,8 +148,20 @@ func (cs *checkoutService) Watch(req *healthpb.HealthCheckRequest, ws healthpb.H
}

func (cs *checkoutService) PlaceOrder(ctx context.Context, req *pb.PlaceOrderRequest) (*pb.PlaceOrderResponse, error) {
span := trace.SpanFromContext(ctx)
span.SetAttributes(
attribute.String("app.user.id", req.UserId),
attribute.String("app.user.currency", req.UserCurrency),
)
log.Infof("[PlaceOrder] user_id=%q user_currency=%q", req.UserId, req.UserCurrency)

var err error
defer func() {
if err != nil {
span.AddEvent("error", trace.WithAttributes(attribute.String("exception.message", err.Error())))
}
}()

orderID, err := uuid.NewUUID()
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to generate order uuid")
Expand All @@ -153,6 +171,7 @@ func (cs *checkoutService) PlaceOrder(ctx context.Context, req *pb.PlaceOrderReq
if err != nil {
return nil, status.Errorf(codes.Internal, err.Error())
}
span.AddEvent("prepared")
puckpuck marked this conversation as resolved.
Show resolved Hide resolved

total := &pb.Money{CurrencyCode: req.UserCurrency,
Units: 0,
Expand All @@ -168,11 +187,14 @@ func (cs *checkoutService) PlaceOrder(ctx context.Context, req *pb.PlaceOrderReq
return nil, status.Errorf(codes.Internal, "failed to charge card: %+v", err)
}
log.Infof("payment went through (transaction_id: %s)", txID)
span.AddEvent("charged", trace.WithAttributes(attribute.String("app.order.transaction.id", txID)))

shippingTrackingID, err := cs.shipOrder(ctx, req.Address, prep.cartItems)
if err != nil {
return nil, status.Errorf(codes.Unavailable, "shipping error: %+v", err)
}
shippingTrackingAttribute := attribute.String("app.order.tracking.id", shippingTrackingID)
span.AddEvent("shipped", trace.WithAttributes(shippingTrackingAttribute))

_ = cs.emptyUserCart(ctx, req.UserId)

Expand All @@ -184,6 +206,17 @@ func (cs *checkoutService) PlaceOrder(ctx context.Context, req *pb.PlaceOrderReq
Items: prep.orderItems,
}

shippingCostFloat, _ := strconv.ParseFloat(fmt.Sprintf("%d.%02d", prep.shippingCostLocalized.GetUnits(), prep.shippingCostLocalized.GetNanos()/1000000000), 64)
totalPriceFloat, _ := strconv.ParseFloat(fmt.Sprintf("%d.%02d", total.GetUnits(), total.GetNanos()/1000000000), 64)

span.SetAttributes(
attribute.String("app.order.id", orderID.String()),
shippingTrackingAttribute,
attribute.Float64("app.order.shipping.cost", shippingCostFloat),
puckpuck marked this conversation as resolved.
Show resolved Hide resolved
attribute.Float64("app.order.total.cost", totalPriceFloat),
attribute.Int("app.order.items.count", len(prep.orderItems)),
)

if err := cs.sendOrderConfirmation(ctx, req.Email, orderResult); err != nil {
log.Warnf("failed to send order confirmation to %q: %+v", req.Email, err)
} else {
Expand All @@ -200,6 +233,10 @@ type orderPrep struct {
}

func (cs *checkoutService) prepareOrderItemsAndShippingQuoteFromCart(ctx context.Context, userID, userCurrency string, address *pb.Address) (orderPrep, error) {

ctx, span := tracer.Start(ctx, "prepareOrderItemsAndShippingQuoteFromCart")
defer span.End()

var out orderPrep
cartItems, err := cs.getUserCart(ctx, userID)
if err != nil {
Expand All @@ -221,6 +258,14 @@ func (cs *checkoutService) prepareOrderItemsAndShippingQuoteFromCart(ctx context
out.shippingCostLocalized = shippingPrice
out.cartItems = cartItems
out.orderItems = orderItems

shippingCostFloat, _ := strconv.ParseFloat(fmt.Sprintf("%d.%02d", shippingPrice.GetUnits(), shippingPrice.GetNanos()/1000000000), 64)

span.SetAttributes(
attribute.Float64("app.order.shipping.cost", shippingCostFloat),
attribute.Int("app.cart.items.count", len(cartItems)),
attribute.Int("app.order.items.count", len(orderItems)),
)
return out, nil
}

Expand Down Expand Up @@ -308,7 +353,7 @@ func (cs *checkoutService) convertCurrency(ctx context.Context, from *pb.Money,
return nil, fmt.Errorf("could not connect currency service: %+v", err)
}
defer conn.Close()
result, err := pb.NewCurrencyServiceClient(conn).Convert(context.TODO(), &pb.CurrencyConversionRequest{
result, err := pb.NewCurrencyServiceClient(conn).Convert(ctx, &pb.CurrencyConversionRequest{
From: from,
ToCode: toCurrency})
if err != nil {
Expand Down