Skip to content

Commit

Permalink
refactor to otel zapLog
Browse files Browse the repository at this point in the history
  • Loading branch information
cedi committed Jun 6, 2023
1 parent c242b66 commit ab9a6cc
Show file tree
Hide file tree
Showing 16 changed files with 86 additions and 94 deletions.
17 changes: 8 additions & 9 deletions controllers/redirect_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/cedi/urlshortener/pkg/observability"
redirectpkg "github.com/cedi/urlshortener/pkg/redirect"
"github.com/pkg/errors"
"github.com/uptrace/opentelemetry-go-extra/otelzap"
)

// RedirectReconciler reconciles a Redirect object
Expand All @@ -43,17 +44,15 @@ type RedirectReconciler struct {
rClient *redirectclient.RedirectClient

scheme *runtime.Scheme
zapLog *zap.Logger
tracer trace.Tracer
}

// NewRedirectReconciler returns a new RedirectReconciler
func NewRedirectReconciler(client client.Client, rClient *redirectclient.RedirectClient, scheme *runtime.Scheme, zapLog *zap.Logger, tracer trace.Tracer) *RedirectReconciler {
func NewRedirectReconciler(client client.Client, rClient *redirectclient.RedirectClient, scheme *runtime.Scheme, tracer trace.Tracer) *RedirectReconciler {
return &RedirectReconciler{
client: client,
rClient: rClient,
scheme: scheme,
zapLog: zapLog,
tracer: tracer,
}
}
Expand Down Expand Up @@ -86,7 +85,7 @@ func (r *RedirectReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c

span.SetAttributes(attribute.String("redirect", req.NamespacedName.String()))

log := r.zapLog.Sugar().With(zap.String("name", "reconciler"), zap.String("redirect", req.NamespacedName.String()))
log := otelzap.L().Sugar().With(zap.String("name", "reconciler"), zap.String("redirect", req.NamespacedName.String()))

// Monitor the number of redirects
if redirectList, err := r.rClient.List(ctx); redirectList != nil && err == nil {
Expand All @@ -100,19 +99,19 @@ func (r *RedirectReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
// Request object not found, could have been deleted after reconcile request.
// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
// Return and don't requeue
observability.RecordInfo(span, log, "Shortlink resource not found. Ignoring since object must be deleted")
observability.RecordInfo(ctx, span, log, "Shortlink resource not found. Ignoring since object must be deleted")
return ctrl.Result{}, nil
}

// Error reading the object - requeue the request.
observability.RecordError(span, log, err, "Failed to fetch Redirect resource")
observability.RecordError(ctx, span, log, err, "Failed to fetch Redirect resource")
return ctrl.Result{}, err
}

// Check if the ingress already exists, if not create a new one
ingress, err := r.upsertRedirectIngress(ctx, redirect)
if err != nil {
observability.RecordError(span, log, err, "Failed to upsert redirect ingress")
observability.RecordError(ctx, span, log, err, "Failed to upsert redirect ingress")
}

// Update the Redirect status with the ingress name and the target
Expand All @@ -123,7 +122,7 @@ func (r *RedirectReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
}

if err = r.client.List(ctx, ingressList, listOpts...); err != nil {
observability.RecordError(span, log, err, "Failed to list ingresses")
observability.RecordError(ctx, span, log, err, "Failed to list ingresses")
return ctrl.Result{}, err
}

Expand All @@ -132,7 +131,7 @@ func (r *RedirectReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
redirect.Status.Target = ingress.ObjectMeta.Annotations["nginx.ingress.kubernetes.io/permanent-redirect"]
err = r.client.Status().Update(ctx, redirect)
if err != nil {
observability.RecordError(span, log, err, "Failed to update Redirect status")
observability.RecordError(ctx, span, log, err, "Failed to update Redirect status")
return ctrl.Result{}, err
}

Expand Down
11 changes: 5 additions & 6 deletions controllers/shortlink_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,21 @@ import (
v1alpha1 "github.com/cedi/urlshortener/api/v1alpha1"
shortlinkclient "github.com/cedi/urlshortener/pkg/client"
"github.com/cedi/urlshortener/pkg/observability"
"github.com/uptrace/opentelemetry-go-extra/otelzap"
)

// ShortLinkReconciler reconciles a ShortLink object
type ShortLinkReconciler struct {
client *shortlinkclient.ShortlinkClient
scheme *runtime.Scheme
zapLog *zap.Logger
tracer trace.Tracer
}

// NewShortLinkReconciler returns a new ShortLinkReconciler
func NewShortLinkReconciler(client *shortlinkclient.ShortlinkClient, scheme *runtime.Scheme, zapLog *zap.Logger, tracer trace.Tracer) *ShortLinkReconciler {
func NewShortLinkReconciler(client *shortlinkclient.ShortlinkClient, scheme *runtime.Scheme, tracer trace.Tracer) *ShortLinkReconciler {
return &ShortLinkReconciler{
client: client,
scheme: scheme,
zapLog: zapLog,
tracer: tracer,
}
}
Expand Down Expand Up @@ -76,15 +75,15 @@ func (r *ShortLinkReconciler) Reconcile(ctx context.Context, req ctrl.Request) (

span.SetAttributes(attribute.String("shortlink", req.Name))

log := r.zapLog.Sugar().With(zap.String("name", "reconciler"), zap.String("shortlink", req.NamespacedName.String()))
log := otelzap.L().Sugar().With(zap.String("name", "reconciler"), zap.String("shortlink", req.NamespacedName.String()))

// Get ShortLink from etcd
shortlink, err := r.client.GetNamespaced(ctx, req.NamespacedName)
if err != nil || shortlink == nil {
if errors.IsNotFound(err) {
observability.RecordInfo(span, log, "Shortlink resource not found. Ignoring since object must be deleted")
observability.RecordInfo(ctx, span, log, "Shortlink resource not found. Ignoring since object must be deleted")
} else {
observability.RecordError(span, log, err, "Failed to fetch ShortLink resource")
observability.RecordError(ctx, span, log, err, "Failed to fetch ShortLink resource")
}
}

Expand Down
46 changes: 21 additions & 25 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (

"github.com/gin-gonic/gin"
"github.com/go-logr/zapr"
"github.com/uptrace/opentelemetry-go-extra/otelzap"

v1alpha1 "github.com/cedi/urlshortener/api/v1alpha1"
"github.com/cedi/urlshortener/controllers"
Expand Down Expand Up @@ -89,24 +90,24 @@ func main() {
flag.Parse()

// Initialize Logging
zapLog, otelLogger, undo := observability.InitLogging(debug)
otelLogger, undo := observability.InitLogging(debug)
defer otelLogger.Sync()
defer undo()

ctrl.SetLogger(zapr.NewLogger(zapLog))
ctrl.SetLogger(zapr.NewLogger(otelzap.L().Logger))

// Initialize Tracing (OpenTelemetry)
traceProvider, tracer, err := observability.InitTracer(serviceName, serviceVersion)
if err != nil {
zapLog.Sugar().Errorw("failed initializing tracing",
otelzap.L().Sugar().Errorw("failed initializing tracing",
zap.Error(err),
)
os.Exit(1)
}

defer func() {
if err := traceProvider.Shutdown(context.Background()); err != nil {
zapLog.Sugar().Errorw("Error shutting down tracer provider",
otelzap.L().Sugar().Errorw("Error shutting down tracer provider",
zap.Error(err),
)
}
Expand All @@ -121,7 +122,7 @@ func main() {
namespaceByte, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
if err != nil {
span.RecordError(err)
zapLog.Sugar().Errorw("Error shutting down tracer provider",
otelzap.L().Sugar().Errorw("Error shutting down tracer provider",
zap.Error(err),
)
os.Exit(1)
Expand All @@ -145,34 +146,31 @@ func main() {

if err != nil {
span.RecordError(err)
zapLog.Sugar().Errorw("unable to start urlshortener",
otelzap.L().Sugar().Errorw("unable to start urlshortener",
zap.Error(err),
)
os.Exit(1)
}

sClient := shortlinkClient.NewShortlinkClient(
mgr.GetClient(),
&ctrl.Log,
tracer,
)

rClient := shortlinkClient.NewRedirectClient(
mgr.GetClient(),
&ctrl.Log,
tracer,
)

shortlinkReconciler := controllers.NewShortLinkReconciler(
sClient,
mgr.GetScheme(),
zapLog,
tracer,
)

if err = shortlinkReconciler.SetupWithManager(mgr); err != nil {
span.RecordError(err)
zapLog.Sugar().Errorw("unable to create controller",
otelzap.L().Sugar().Errorw("unable to create controller",
zap.Error(err),
zap.String("controller", "ShortLink"),
)
Expand All @@ -183,13 +181,12 @@ func main() {
mgr.GetClient(),
rClient,
mgr.GetScheme(),
zapLog,
tracer,
)

if err = redirectReconciler.SetupWithManager(mgr); err != nil {
span.RecordError(err)
zapLog.Sugar().Errorw("unable to create controller",
otelzap.L().Sugar().Errorw("unable to create controller",
zap.Error(err),
zap.String("controller", "Redirect"),
)
Expand All @@ -200,61 +197,60 @@ func main() {
span.End()

if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
zapLog.Sugar().Errorw("unable to set up health check",
otelzap.L().Sugar().Errorw("unable to set up health check",
zap.Error(err),
)
os.Exit(1)
}

if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
zapLog.Sugar().Errorw("unable to set up ready check",
otelzap.L().Sugar().Errorw("unable to set up ready check",
zap.Error(err),
)
os.Exit(1)
}

// run our urlshortener mgr in a separate go routine
go func() {
zapLog.Info("starting urlshortener")
otelzap.L().Info("starting urlshortener")

if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
zapLog.Sugar().Errorw("unable starting urlshortener",
otelzap.L().Sugar().Errorw("unable starting urlshortener",
zap.Error(err),
)
os.Exit(1)
}
}()

shortlinkController := apiController.NewShortlinkController(
zapLog,
tracer,
sClient,
)

// Init Gin Framework
gin.SetMode(gin.ReleaseMode)
r, srv := router.NewGinGonicHTTPServer(bindAddr, zapLog, serviceName)
r, srv := router.NewGinGonicHTTPServer(bindAddr, serviceName)

zapLog.Info("Load API routes")
otelzap.L().Info("Load API routes")
router.Load(r, shortlinkController)

// run our gin server mgr in a separate go routine
go func() {
if err := srv.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) {
zapLog.Sugar().Errorw("failed to listen and serve",
otelzap.L().Sugar().Errorw("failed to listen and serve",
zap.Error(err),
)
}
}()

handleShutdown(srv, zapLog)
handleShutdown(srv)

zapLog.Info("Server exiting")
otelzap.L().Info("Server exiting")
}

// handleShutdown waits for interrupt signal and then tries to gracefully
// shutdown the server with a timeout of 5 seconds.
func handleShutdown(srv *http.Server, zapLog *zap.Logger) {
func handleShutdown(srv *http.Server) {
quit := make(chan os.Signal, 1)

signal.Notify(
Expand All @@ -266,7 +262,7 @@ func handleShutdown(srv *http.Server, zapLog *zap.Logger) {

// wait (and block) until shutdown signal is received
<-quit
zapLog.Info("Shutting down server...")
otelzap.L().Info("Shutting down server...")

// The context is used to inform the server it has 5 seconds to finish
// the request it is currently handling
Expand All @@ -277,7 +273,7 @@ func handleShutdown(srv *http.Server, zapLog *zap.Logger) {
// then srv.Shutdown(ctx) will return an error, causing us to force
// the shutdown
if err := srv.Shutdown(ctx); err != nil {
zapLog.Sugar().Errorw("Server forced to shutdown",
otelzap.L().Sugar().Errorw("Server forced to shutdown",
zap.Error(err),
)
os.Exit(1)
Expand Down
5 changes: 1 addition & 4 deletions pkg/client/authenticated_shortlink_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,19 @@ import (

"github.com/cedi/urlshortener/api/v1alpha1"
"github.com/cedi/urlshortener/pkg/model"
"go.uber.org/zap"

"github.com/pkg/errors"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)

type ShortlinkClientAuth struct {
zapLog *zap.Logger
tracer trace.Tracer
client *ShortlinkClient
}

func NewAuthenticatedShortlinkClient(zapLog *zap.Logger, tracer trace.Tracer, client *ShortlinkClient) *ShortlinkClientAuth {
func NewAuthenticatedShortlinkClient(tracer trace.Tracer, client *ShortlinkClient) *ShortlinkClientAuth {
return &ShortlinkClientAuth{
zapLog: zapLog,
tracer: tracer,
client: client,
}
Expand Down
5 changes: 1 addition & 4 deletions pkg/client/redirect_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"os"

"github.com/cedi/urlshortener/api/v1alpha1"
"github.com/go-logr/logr"
"github.com/pkg/errors"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
Expand All @@ -18,15 +17,13 @@ import (
// RedirectClient is a Kubernetes client for easy CRUD operations
type RedirectClient struct {
client client.Client
log *logr.Logger
tracer trace.Tracer
}

// NewRedirectClient creates a new Redirect Client
func NewRedirectClient(client client.Client, log *logr.Logger, tracer trace.Tracer) *RedirectClient {
func NewRedirectClient(client client.Client, tracer trace.Tracer) *RedirectClient {
return &RedirectClient{
client: client,
log: log,
tracer: tracer,
}
}
Expand Down
5 changes: 1 addition & 4 deletions pkg/client/shortlink_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"os"

"github.com/cedi/urlshortener/api/v1alpha1"
"github.com/go-logr/logr"
"github.com/pkg/errors"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
Expand All @@ -16,15 +15,13 @@ import (
// ShortlinkClient is a Kubernetes client for easy CRUD operations
type ShortlinkClient struct {
client client.Client
log *logr.Logger
tracer trace.Tracer
}

// NewShortlinkClient creates a new shortlink Client
func NewShortlinkClient(client client.Client, log *logr.Logger, tracer trace.Tracer) *ShortlinkClient {
func NewShortlinkClient(client client.Client, tracer trace.Tracer) *ShortlinkClient {
return &ShortlinkClient{
client: client,
log: log,
tracer: tracer,
}
}
Expand Down
Loading

0 comments on commit ab9a6cc

Please sign in to comment.