Skip to content

Commit

Permalink
Prometheus metrics (#133)
Browse files Browse the repository at this point in the history
Closes #113 and #112.
  • Loading branch information
trstringer authored Mar 24, 2024
1 parent 4f878a5 commit bd830f8
Show file tree
Hide file tree
Showing 16 changed files with 423 additions and 314 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ install-app-local: create-namespace-app build-images push-images
helm upgrade -n app --install otel-shopping-cart ./charts/otel-shopping-cart

.PHONY: build-images
build-images: build-collector
build-images:
docker build -t $(CART_IMAGE_REPO):$(IMAGE_TAG) -f ./dockerfiles/Dockerfile.cart .
docker build -t $(DATASEED_IMAGE_REPO):$(IMAGE_TAG) -f ./dockerfiles/Dockerfile.dataseed .
docker build -t $(INTERRUPTER_IMAGE_REPO):$(IMAGE_TAG) -f ./dockerfiles/Dockerfile.interrupter .
Expand Down
3 changes: 3 additions & 0 deletions charts/otel-shopping-cart/templates/cart-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ kind: Service
apiVersion: v1
metadata:
name: {{ .Values.cart.serviceName }}
labels:
app: cart
spec:
selector:
app: {{ .Values.cart.serviceName }}
ports:
- port: {{ .Values.cart.port }}
name: http
targetPort: {{ .Values.cart.port }}
12 changes: 12 additions & 0 deletions charts/otel-shopping-cart/templates/cart-servicemonitor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ .Values.cart.serviceName }}
labels:
release: prometheus
spec:
endpoints:
- port: http
selector:
matchLabels:
app: cart
3 changes: 3 additions & 0 deletions charts/otel-shopping-cart/templates/user-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ kind: Service
apiVersion: v1
metadata:
name: {{ .Values.user.serviceName }}
labels:
app: user
spec:
selector:
app: {{ .Values.user.serviceName }}
ports:
- port: {{ .Values.user.port }}
name: http
targetPort: {{ .Values.user.port }}
12 changes: 12 additions & 0 deletions charts/otel-shopping-cart/templates/user-servicemonitor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ .Values.user.serviceName }}
labels:
release: prometheus
spec:
endpoints:
- port: http
selector:
matchLabels:
app: user
21 changes: 19 additions & 2 deletions cmd/cart/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import (
"io"
"net/http"
"os"
"strconv"
"strings"

"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/spf13/cobra"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel"
Expand All @@ -20,6 +22,7 @@ import (
"go.opentelemetry.io/otel/trace"

"github.com/trstringer/otel-shopping-cart/pkg/cart"
"github.com/trstringer/otel-shopping-cart/pkg/dbmanager"
"github.com/trstringer/otel-shopping-cart/pkg/telemetry"
"github.com/trstringer/otel-shopping-cart/pkg/users"
)
Expand Down Expand Up @@ -127,12 +130,14 @@ func validateParams() {
}

func userCart(w http.ResponseWriter, r *http.Request) {
httpRequest.Inc()
ctx, span := otel.Tracer(telemetry.TelemetryLibrary).Start(r.Context(), "get_user_cart")
defer span.End()

if r.Method != http.MethodGet && r.Method != http.MethodPost {
err := fmt.Errorf("unsupported request method: %s", r.Method)
userRequestError(ctx, w, err, http.StatusBadRequest, true)
httpResponses.WithLabelValues(strconv.Itoa(http.StatusBadRequest)).Inc()
return
}

Expand All @@ -145,6 +150,7 @@ func userCart(w http.ResponseWriter, r *http.Request) {
http.StatusInternalServerError,
true,
)
httpResponses.WithLabelValues(strconv.Itoa(http.StatusInternalServerError)).Inc()
fmt.Printf("error creating baggage member: %v\n", err)
return
}
Expand All @@ -158,6 +164,7 @@ func userCart(w http.ResponseWriter, r *http.Request) {
http.StatusInternalServerError,
true,
)
httpResponses.WithLabelValues(strconv.Itoa(http.StatusInternalServerError)).Inc()
fmt.Printf("error creating baggage: %v\n", err)
return
}
Expand All @@ -167,7 +174,7 @@ func userCart(w http.ResponseWriter, r *http.Request) {
fmt.Printf("Received cart request for %s\n", userName)
span.SetAttributes(attribute.String("user.name", userName))

cartManager := cart.NewDBManager(
cartManager := dbmanager.NewDBManager(
dbSQLAddress,
"otel_shopping_cart",
dbSQLUser,
Expand All @@ -183,6 +190,7 @@ func userCart(w http.ResponseWriter, r *http.Request) {
http.StatusInternalServerError,
true,
)
httpResponses.WithLabelValues(strconv.Itoa(http.StatusInternalServerError)).Inc()
fmt.Printf("error getting user: %v\n", err)
return
}
Expand All @@ -195,6 +203,7 @@ func userCart(w http.ResponseWriter, r *http.Request) {
http.StatusInternalServerError,
true,
)
httpResponses.WithLabelValues(strconv.Itoa(http.StatusInternalServerError)).Inc()
fmt.Printf("error getting user cart: %v\n", err)
return
}
Expand All @@ -209,6 +218,7 @@ func userCart(w http.ResponseWriter, r *http.Request) {
http.StatusInternalServerError,
true,
)
httpResponses.WithLabelValues(strconv.Itoa(http.StatusInternalServerError)).Inc()
fmt.Printf("error reading body data: %v\n", err)
return
}
Expand All @@ -221,6 +231,7 @@ func userCart(w http.ResponseWriter, r *http.Request) {
http.StatusInternalServerError,
true,
)
httpResponses.WithLabelValues(strconv.Itoa(http.StatusInternalServerError)).Inc()
fmt.Printf("error unmarshalling data: %v\n", err)
return
}
Expand All @@ -232,6 +243,7 @@ func userCart(w http.ResponseWriter, r *http.Request) {
http.StatusInternalServerError,
true,
)
httpResponses.WithLabelValues(strconv.Itoa(http.StatusInternalServerError)).Inc()
fmt.Printf("error adding item to cart: %v\n", err)
return
}
Expand All @@ -245,6 +257,7 @@ func userCart(w http.ResponseWriter, r *http.Request) {
http.StatusInternalServerError,
true,
)
httpResponses.WithLabelValues(strconv.Itoa(http.StatusInternalServerError)).Inc()
fmt.Printf("error getting user cart: %v\n", err)
return
}
Expand All @@ -259,10 +272,12 @@ func userCart(w http.ResponseWriter, r *http.Request) {
http.StatusInternalServerError,
true,
)
httpResponses.WithLabelValues(strconv.Itoa(http.StatusInternalServerError)).Inc()
fmt.Printf("error marshalling cart: %v\n", err)
return
}

httpResponses.WithLabelValues(strconv.Itoa(http.StatusOK)).Inc()
w.Write([]byte(jsonCart))
}

Expand Down Expand Up @@ -357,14 +372,16 @@ func userRequestError(ctx context.Context, w http.ResponseWriter, err error, htt
}

func runServer() {
http.Handle("/metrics", promhttp.Handler())
http.Handle(
fmt.Sprintf("/%s/", rootPath),
otelhttp.NewHandler(
http.HandlerFunc(userCart),
"http_user_cart",
otelhttp.WithTracerProvider(otel.GetTracerProvider()),
otelhttp.WithPropagators(otel.GetTextMapPropagator()),
))
),
)

addr := fmt.Sprintf(":%d", port)
fmt.Printf("Running server on %s\n", addr)
Expand Down
20 changes: 20 additions & 0 deletions cmd/cart/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package main

import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)

var (
httpRequest = promauto.NewCounter(prometheus.CounterOpts{
Name: "cart_http_request",
Help: "HTTP request",
})
httpResponses = promauto.NewCounterVec(
prometheus.CounterOpts{
Name: "cart_http_response",
Help: "HTTP response",
},
[]string{"status"},
)
)
4 changes: 2 additions & 2 deletions cmd/interrupter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

"github.com/spf13/cobra"

"github.com/trstringer/otel-shopping-cart/pkg/users"
"github.com/trstringer/otel-shopping-cart/pkg/dbmanager"
)

var (
Expand All @@ -23,7 +23,7 @@ var rootCmd = &cobra.Command{
Short: "Service interrupter",
Long: `Interrupt service and cause quality issues.`,
Run: func(cmd *cobra.Command, args []string) {
dbm := users.NewDBManager(dbSQLAddress, "otel_shopping_cart", dbSQLUser, os.Getenv("DB_PASSWORD"))
dbm := dbmanager.NewDBManager(dbSQLAddress, "otel_shopping_cart", dbSQLUser, os.Getenv("DB_PASSWORD"))
users, err := dbm.GetAllUsers()
if err != nil {
fmt.Printf("Error getting users: %v\n", err)
Expand Down
16 changes: 13 additions & 3 deletions cmd/users/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (
"fmt"
"net/http"
"os"
"strconv"
"strings"

"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/spf13/cobra"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel"
Expand All @@ -16,6 +18,7 @@ import (
"go.opentelemetry.io/otel/propagation"
sdktrace "go.opentelemetry.io/otel/sdk/trace"

"github.com/trstringer/otel-shopping-cart/pkg/dbmanager"
"github.com/trstringer/otel-shopping-cart/pkg/telemetry"
"github.com/trstringer/otel-shopping-cart/pkg/users"
)
Expand Down Expand Up @@ -108,7 +111,8 @@ func validateParams() {
}

func allUsers(w http.ResponseWriter, r *http.Request) {
userManager := users.NewDBManager(
httpRequest.Inc()
userManager := dbmanager.NewDBManager(
dbSQLAddress,
"otel_shopping_cart",
dbSQLUser,
Expand All @@ -119,20 +123,23 @@ func allUsers(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadRequest)
fmt.Printf("error retrieving all users: %v\n", err)
w.Write([]byte(fmt.Sprintf("error retrieving all users: %v", err)))
httpResponses.WithLabelValues(strconv.Itoa(http.StatusBadRequest)).Inc()
return
}
userData, err := json.Marshal(allUsers)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Printf("error marshalling all users: %v\n", err)
w.Write([]byte(fmt.Sprintf("error marshalling all users: %v", err)))
httpResponses.WithLabelValues(strconv.Itoa(http.StatusBadRequest)).Inc()
return
}

w.Write([]byte(userData))
}

func user(w http.ResponseWriter, r *http.Request) {
httpRequest.Inc()
ctx := r.Context()
ctx, span := otel.Tracer(telemetry.TelemetryLibrary).Start(ctx, "get_user")
defer span.End()
Expand All @@ -146,7 +153,7 @@ func user(w http.ResponseWriter, r *http.Request) {
userName := strings.TrimPrefix(r.URL.Path, fmt.Sprintf("/%s/", rootPath))
fmt.Printf("Received user request for %q\n", userName)

userManager := users.NewDBManager(
userManager := dbmanager.NewDBManager(
dbSQLAddress,
"otel_shopping_cart",
dbSQLUser,
Expand All @@ -158,6 +165,7 @@ func user(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadRequest)
fmt.Printf("error retrieving user: %v\n", err)
w.Write([]byte(fmt.Sprintf("error retrieving user: %v", err)))
httpResponses.WithLabelValues(strconv.Itoa(http.StatusBadRequest)).Inc()
return
}

Expand All @@ -167,9 +175,11 @@ func user(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
fmt.Printf("error retrieving user: %v\n", err)
w.Write([]byte(fmt.Sprintf("error marshalling user data: %v", err)))
httpResponses.WithLabelValues(strconv.Itoa(http.StatusInternalServerError)).Inc()
return
}

httpResponses.WithLabelValues(strconv.Itoa(http.StatusOK)).Inc()
w.Write([]byte(userData))
}

Expand All @@ -178,8 +188,8 @@ func getUser(ctx context.Context, userManager users.Manager, userName string) (*
}

func runServer() {
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc(fmt.Sprintf("/%s", rootPath), allUsers)

http.Handle(
fmt.Sprintf("/%s/", rootPath),
otelhttp.NewHandler(
Expand Down
20 changes: 20 additions & 0 deletions cmd/users/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package main

import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)

var (
httpRequest = promauto.NewCounter(prometheus.CounterOpts{
Name: "users_http_request",
Help: "HTTP request",
})
httpResponses = promauto.NewCounterVec(
prometheus.CounterOpts{
Name: "users_http_response",
Help: "HTTP response",
},
[]string{"status"},
)
)
6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.20

require (
github.com/lib/pq v1.10.9
github.com/prometheus/client_golang v1.19.0
github.com/spf13/cobra v1.8.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0
go.opentelemetry.io/otel v1.24.0
Expand All @@ -15,13 +16,18 @@ require (
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
Expand Down
Loading

0 comments on commit bd830f8

Please sign in to comment.