add retries for stackdriver exporters in go

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
Ahmet Alp Balkan 2018-07-13 15:44:56 -07:00
parent d01f525453
commit d08a58cc21
4 changed files with 96 additions and 61 deletions

View file

@ -6,6 +6,7 @@ import (
"log" "log"
"net" "net"
"os" "os"
"time"
"github.com/google/uuid" "github.com/google/uuid"
"go.opencensus.io/exporter/stackdriver" "go.opencensus.io/exporter/stackdriver"
@ -39,7 +40,7 @@ func main() {
port = os.Getenv("PORT") port = os.Getenv("PORT")
} }
initTracing() go initTracing()
svc := new(checkoutService) svc := new(checkoutService)
mustMapEnv(&svc.shippingSvcAddr, "SHIPPING_SERVICE_ADDR") mustMapEnv(&svc.shippingSvcAddr, "SHIPPING_SERVICE_ADDR")
@ -62,15 +63,23 @@ func main() {
} }
func initTracing() { func initTracing() {
exporter, err := stackdriver.NewExporter(stackdriver.Options{}) // TODO(ahmetb) this method is duplicated in other microservices using Go
if err != nil { // since they are not sharing packages.
log.Printf("failed to initialize stackdriver exporter: %+v", err) for i := 1; i <= 3; i++ {
log.Println("skipping uploading traces to stackdriver") exporter, err := stackdriver.NewExporter(stackdriver.Options{})
} else { if err != nil {
trace.RegisterExporter(exporter) log.Printf("info: failed to initialize stackdriver exporter: %+v", err)
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) } else {
log.Println("registered stackdriver tracing") trace.RegisterExporter(exporter)
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
log.Print("registered stackdriver tracing")
return
}
d := time.Second * 10 * time.Duration(i)
log.Printf("sleeping %v to retry initializing stackdriver exporter", d)
time.Sleep(d)
} }
log.Printf("warning: could not initialize stackdriver exporter after retrying, giving up")
} }
func mustMapEnv(target *string, envKey string) { func mustMapEnv(target *string, envKey string) {

View file

@ -3,7 +3,6 @@ package main
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"net/http" "net/http"
"os" "os"
"time" "time"
@ -67,7 +66,7 @@ func main() {
log.Level = logrus.DebugLevel log.Level = logrus.DebugLevel
log.Formatter = &logrus.TextFormatter{} log.Formatter = &logrus.TextFormatter{}
initTracing() go initTracing(log)
srvPort := port srvPort := port
if os.Getenv("PORT") != "" { if os.Getenv("PORT") != "" {
@ -111,16 +110,25 @@ func main() {
log.Fatal(http.ListenAndServe(addr+":"+srvPort, handler)) log.Fatal(http.ListenAndServe(addr+":"+srvPort, handler))
} }
func initTracing() { func initTracing(log logrus.FieldLogger) {
exporter, err := stackdriver.NewExporter(stackdriver.Options{}) // TODO(ahmetb) this method is duplicated in other microservices using Go
if err != nil { // since they are not sharing packages.
log.Printf("failed to initialize stackdriver exporter: %+v", err) for i := 1; i <= 3; i++ {
log.Println("skipping uploading traces to stackdriver") log = log.WithField("retry", i)
} else { exporter, err := stackdriver.NewExporter(stackdriver.Options{})
trace.RegisterExporter(exporter) if err != nil {
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) log.Warnf("failed to initialize stackdriver exporter: %+v", err)
log.Println("registered stackdriver tracing") } else {
trace.RegisterExporter(exporter)
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
log.Info("registered stackdriver tracing")
return
}
d := time.Second * 20 * time.Duration(i)
log.Debugf("sleeping %v to retry initializing stackdriver exporter", d)
time.Sleep(d)
} }
log.Warn("could not initialize stackdriver exporter after retrying, giving up")
} }
func mustMapEnv(target *string, envKey string) { func mustMapEnv(target *string, envKey string) {

View file

@ -7,6 +7,7 @@ import (
"log" "log"
"net" "net"
"strings" "strings"
"time"
pb "./genproto" pb "./genproto"
"go.opencensus.io/exporter/stackdriver" "go.opencensus.io/exporter/stackdriver"
@ -88,7 +89,7 @@ var catalog = []*pb.Product{
func main() { func main() {
flag.Parse() flag.Parse()
initTracing() go initTracing()
log.Printf("starting grpc server at :%d", *port) log.Printf("starting grpc server at :%d", *port)
run(*port) run(*port)
@ -107,15 +108,23 @@ func run(port int) string {
} }
func initTracing() { func initTracing() {
exporter, err := stackdriver.NewExporter(stackdriver.Options{}) // TODO(ahmetb) this method is duplicated in other microservices using Go
if err != nil { // since they are not sharing packages.
log.Printf("failed to initialize stackdriver exporter: %+v", err) for i := 1; i <= 3; i++ {
log.Println("skipping uploading traces to stackdriver") exporter, err := stackdriver.NewExporter(stackdriver.Options{})
} else { if err != nil {
trace.RegisterExporter(exporter) log.Printf("info: failed to initialize stackdriver exporter: %+v", err)
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) } else {
log.Println("registered stackdriver") trace.RegisterExporter(exporter)
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
log.Print("registered stackdriver tracing")
return
}
d := time.Second * 10 * time.Duration(i)
log.Printf("sleeping %v to retry initializing stackdriver exporter", d)
time.Sleep(d)
} }
log.Printf("warning: could not initialize stackdriver exporter after retrying, giving up")
} }
type productCatalog struct{} type productCatalog struct{}

View file

@ -5,6 +5,7 @@ import (
"log" "log"
"net" "net"
"os" "os"
"time"
"go.opencensus.io/exporter/stackdriver" "go.opencensus.io/exporter/stackdriver"
"go.opencensus.io/plugin/ocgrpc" "go.opencensus.io/plugin/ocgrpc"
@ -20,6 +21,30 @@ const (
defaultPort = "50051" defaultPort = "50051"
) )
func main() {
port := defaultPort
if value, ok := os.LookupEnv("APP_PORT"); ok {
port = value
}
port = fmt.Sprintf(":%s", port)
go initTracing()
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer(grpc.StatsHandler(&ocgrpc.ServerHandler{}))
pb.RegisterShippingServiceServer(s, &server{})
log.Printf("Shipping Service listening on port %s", port)
// Register reflection service on gRPC server.
reflection.Register(s)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
// server controls RPC service responses. // server controls RPC service responses.
type server struct{} type server struct{}
@ -62,38 +87,22 @@ func (s *server) ShipOrder(ctx context.Context, in *pb.ShipOrderRequest) (*pb.Sh
}, nil }, nil
} }
func main() {
port := defaultPort
if value, ok := os.LookupEnv("APP_PORT"); ok {
port = value
}
port = fmt.Sprintf(":%s", port)
initTracing()
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer(grpc.StatsHandler(&ocgrpc.ServerHandler{}))
pb.RegisterShippingServiceServer(s, &server{})
log.Printf("Shipping Service listening on port %s", port)
// Register reflection service on gRPC server.
reflection.Register(s)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
func initTracing() { func initTracing() {
exporter, err := stackdriver.NewExporter(stackdriver.Options{}) // TODO(ahmetb) this method is duplicated in other microservices using Go
if err != nil { // since they are not sharing packages.
log.Printf("failed to initialize stackdriver exporter: %+v", err) for i := 1; i <= 3; i++ {
log.Println("skipping uploading traces to stackdriver") exporter, err := stackdriver.NewExporter(stackdriver.Options{})
} else { if err != nil {
trace.RegisterExporter(exporter) log.Printf("info: failed to initialize stackdriver exporter: %+v", err)
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) } else {
log.Println("registered stackdriver tracing") trace.RegisterExporter(exporter)
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
log.Print("registered stackdriver tracing")
return
}
d := time.Second * 10 * time.Duration(i)
log.Printf("sleeping %v to retry initializing stackdriver exporter", d)
time.Sleep(d)
} }
log.Printf("warning: could not initialize stackdriver exporter after retrying, giving up")
} }