From c0edd07cb0c787fb39f555806ea03d8b788d40d9 Mon Sep 17 00:00:00 2001 From: Wagner Abrantes <51835962+wagnerdevocelot@users.noreply.github.com> Date: Sun, 13 Jul 2025 20:37:55 -0300 Subject: [PATCH 1/3] Introduce logging adapter --- logging_adapter.go | 232 +++++++++++++++++++++++++++++++++++++++++++++ main.go | 6 +- 2 files changed, 235 insertions(+), 3 deletions(-) create mode 100644 logging_adapter.go diff --git a/logging_adapter.go b/logging_adapter.go new file mode 100644 index 0000000..c7a6046 --- /dev/null +++ b/logging_adapter.go @@ -0,0 +1,232 @@ +package main + +import ( + "context" + "log" + "sync" + "time" + + "github.com/ory/fosite" + "github.com/ory/fosite/handler/oauth2" + "github.com/ory/fosite/handler/openid" + "github.com/ory/fosite/handler/pkce" +) + +// LoggingAdapter wraps another StorageInterface and logs all operations. +// fullStorage groups all interfaces required by fosite's Compose plus our +// generic StorageInterface. Any real backend (memory or DB) should implement +// all of them. +type fullStorage interface { + fosite.Storage + openid.OpenIDConnectRequestStorage + oauth2.CoreStorage + oauth2.TokenRevocationStorage + pkce.PKCERequestStorage + StorageInterface +} + +// LoggingAdapter wraps another storage backend and records metrics while +// delegating all operations to it. +type LoggingAdapter struct { + fullStorage + mu sync.Mutex + metrics map[string]int +} + +// NewLoggingAdapter creates a new adapter with the given backend. +func NewLoggingAdapter(backend fullStorage) *LoggingAdapter { + return &LoggingAdapter{fullStorage: backend, metrics: make(map[string]int)} +} + +func (l *LoggingAdapter) inc(key string) { + l.mu.Lock() + l.metrics[key]++ + l.mu.Unlock() +} + +// Metrics returns a copy of collected metrics. +func (l *LoggingAdapter) Metrics() map[string]int { + l.mu.Lock() + defer l.mu.Unlock() + copy := make(map[string]int, len(l.metrics)) + for k, v := range l.metrics { + copy[k] = v + } + return copy +} + +func (l *LoggingAdapter) GetClient(ctx context.Context, id string) (fosite.Client, error) { + c, err := l.fullStorage.GetClient(ctx, id) + if err != nil { + log.Printf("logging adapter: GetClient %s failed: %v", id, err) + l.inc("GetClientError") + } else { + l.inc("GetClient") + } + return c, err +} + +func (l *LoggingAdapter) CreateClient(ctx context.Context, client fosite.Client) error { + err := l.fullStorage.CreateClient(ctx, client) + if err != nil { + log.Printf("logging adapter: CreateClient %s failed: %v", client.GetID(), err) + l.inc("CreateClientError") + } else { + l.inc("CreateClient") + } + return err +} + +func (l *LoggingAdapter) UpdateClient(ctx context.Context, client fosite.Client) error { + err := l.fullStorage.UpdateClient(ctx, client) + if err != nil { + log.Printf("logging adapter: UpdateClient %s failed: %v", client.GetID(), err) + l.inc("UpdateClientError") + } else { + l.inc("UpdateClient") + } + return err +} + +func (l *LoggingAdapter) DeleteClient(ctx context.Context, id string) error { + err := l.fullStorage.DeleteClient(ctx, id) + if err != nil { + log.Printf("logging adapter: DeleteClient %s failed: %v", id, err) + l.inc("DeleteClientError") + } else { + l.inc("DeleteClient") + } + return err +} + +func (l *LoggingAdapter) CreateToken(ctx context.Context, tokenType, signature, clientID string, data interface{}) error { + err := l.fullStorage.CreateToken(ctx, tokenType, signature, clientID, data) + if err != nil { + log.Printf("logging adapter: CreateToken %s failed: %v", tokenType, err) + l.inc("CreateTokenError") + } else { + l.inc("CreateToken") + } + return err +} + +func (l *LoggingAdapter) GetToken(ctx context.Context, tokenType, signature string) (interface{}, error) { + v, err := l.fullStorage.GetToken(ctx, tokenType, signature) + if err != nil { + log.Printf("logging adapter: GetToken %s failed: %v", tokenType, err) + l.inc("GetTokenError") + } else { + l.inc("GetToken") + } + return v, err +} + +func (l *LoggingAdapter) DeleteToken(ctx context.Context, tokenType, signature string) error { + err := l.fullStorage.DeleteToken(ctx, tokenType, signature) + if err != nil { + log.Printf("logging adapter: DeleteToken %s failed: %v", tokenType, err) + l.inc("DeleteTokenError") + } else { + l.inc("DeleteToken") + } + return err +} + +func (l *LoggingAdapter) RevokeToken(ctx context.Context, tokenType, signature string) error { + err := l.fullStorage.RevokeToken(ctx, tokenType, signature) + if err != nil { + log.Printf("logging adapter: RevokeToken %s failed: %v", tokenType, err) + l.inc("RevokeTokenError") + } else { + l.inc("RevokeToken") + } + return err +} + +func (l *LoggingAdapter) CreateSession(ctx context.Context, sessionType, id string, data interface{}) error { + err := l.fullStorage.CreateSession(ctx, sessionType, id, data) + if err != nil { + log.Printf("logging adapter: CreateSession %s failed: %v", sessionType, err) + l.inc("CreateSessionError") + } else { + l.inc("CreateSession") + } + return err +} + +func (l *LoggingAdapter) GetSession(ctx context.Context, sessionType, id string) (interface{}, error) { + v, err := l.fullStorage.GetSession(ctx, sessionType, id) + if err != nil { + log.Printf("logging adapter: GetSession %s failed: %v", sessionType, err) + l.inc("GetSessionError") + } else { + l.inc("GetSession") + } + return v, err +} + +func (l *LoggingAdapter) DeleteSession(ctx context.Context, sessionType, id string) error { + err := l.fullStorage.DeleteSession(ctx, sessionType, id) + if err != nil { + log.Printf("logging adapter: DeleteSession %s failed: %v", sessionType, err) + l.inc("DeleteSessionError") + } else { + l.inc("DeleteSession") + } + return err +} + +func (l *LoggingAdapter) ValidateJWT(ctx context.Context, jti string) error { + err := l.fullStorage.ValidateJWT(ctx, jti) + if err != nil { + log.Printf("logging adapter: ValidateJWT failed: %v", err) + l.inc("ValidateJWTError") + } else { + l.inc("ValidateJWT") + } + return err +} + +func (l *LoggingAdapter) MarkJWTAsUsed(ctx context.Context, jti string, exp time.Time) error { + err := l.fullStorage.MarkJWTAsUsed(ctx, jti, exp) + if err != nil { + log.Printf("logging adapter: MarkJWTAsUsed failed: %v", err) + l.inc("MarkJWTAsUsedError") + } else { + l.inc("MarkJWTAsUsed") + } + return err +} + +func (l *LoggingAdapter) GetPKCERequestSession(ctx context.Context, signature string, session fosite.Session) (fosite.Requester, error) { + v, err := l.fullStorage.GetPKCERequestSession(ctx, signature, session) + if err != nil { + log.Printf("logging adapter: GetPKCERequestSession failed: %v", err) + l.inc("GetPKCESessionError") + } else { + l.inc("GetPKCESession") + } + return v, err +} + +func (l *LoggingAdapter) CreatePKCERequestSession(ctx context.Context, signature string, requester fosite.Requester) error { + err := l.fullStorage.CreatePKCERequestSession(ctx, signature, requester) + if err != nil { + log.Printf("logging adapter: CreatePKCERequestSession failed: %v", err) + l.inc("CreatePKCESessionError") + } else { + l.inc("CreatePKCESession") + } + return err +} + +func (l *LoggingAdapter) DeletePKCERequestSession(ctx context.Context, signature string) error { + err := l.fullStorage.DeletePKCERequestSession(ctx, signature) + if err != nil { + log.Printf("logging adapter: DeletePKCERequestSession failed: %v", err) + l.inc("DeletePKCESessionError") + } else { + l.inc("DeletePKCESession") + } + return err +} diff --git a/main.go b/main.go index 401206a..3062ea8 100644 --- a/main.go +++ b/main.go @@ -13,9 +13,9 @@ import ( "github.com/ory/fosite/handler/openid" ) -// For this example, we use an in-memory store. -// In a real-world application, you would use a persistent store (e.g., SQL database). -var store = NewInMemoryStore() +// For this example, we use an in-memory store wrapped by a logging adapter. +// This demonstrates how a new storage adapter can be integrated gradually. +var store StorageInterface = NewLoggingAdapter(NewInMemoryStore()) // Fosite configuration using fosite.Config for v0.49.0+ var fositeConfig = &fosite.Config{ From ef5d4599ec00a17f50b65eb68361c737f568e0fa Mon Sep 17 00:00:00 2001 From: Wagner Abrantes <51835962+wagnerdevocelot@users.noreply.github.com> Date: Sun, 13 Jul 2025 21:04:16 -0300 Subject: [PATCH 2/3] Update logging_adapter.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- logging_adapter.go | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/logging_adapter.go b/logging_adapter.go index c7a6046..6dc24b8 100644 --- a/logging_adapter.go +++ b/logging_adapter.go @@ -56,24 +56,30 @@ func (l *LoggingAdapter) Metrics() map[string]int { } func (l *LoggingAdapter) GetClient(ctx context.Context, id string) (fosite.Client, error) { - c, err := l.fullStorage.GetClient(ctx, id) - if err != nil { - log.Printf("logging adapter: GetClient %s failed: %v", id, err) - l.inc("GetClientError") - } else { - l.inc("GetClient") + operation := func() (interface{}, error) { + return l.fullStorage.GetClient(ctx, id) } - return c, err + result, err := l.logAndIncrementMetrics( + ctx, + operation, + "GetClient", + "GetClientError", + "logging adapter: GetClient %s failed: %v", + ) + return result.(fosite.Client), err } func (l *LoggingAdapter) CreateClient(ctx context.Context, client fosite.Client) error { - err := l.fullStorage.CreateClient(ctx, client) - if err != nil { - log.Printf("logging adapter: CreateClient %s failed: %v", client.GetID(), err) - l.inc("CreateClientError") - } else { - l.inc("CreateClient") - } + operation := func() (interface{}, error) { + return nil, l.fullStorage.CreateClient(ctx, client) + } + _, err := l.logAndIncrementMetrics( + ctx, + operation, + "CreateClient", + "CreateClientError", + "logging adapter: CreateClient %s failed: %v", + ) return err } From f77acefd3a0f715a1bfb8dafda1f4b658d3eeff5 Mon Sep 17 00:00:00 2001 From: Wagner Abrantes <51835962+wagnerdevocelot@users.noreply.github.com> Date: Sun, 13 Jul 2025 21:04:23 -0300 Subject: [PATCH 3/3] Update logging_adapter.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- logging_adapter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logging_adapter.go b/logging_adapter.go index 6dc24b8..9d7c4c4 100644 --- a/logging_adapter.go +++ b/logging_adapter.go @@ -108,7 +108,7 @@ func (l *LoggingAdapter) DeleteClient(ctx context.Context, id string) error { func (l *LoggingAdapter) CreateToken(ctx context.Context, tokenType, signature, clientID string, data interface{}) error { err := l.fullStorage.CreateToken(ctx, tokenType, signature, clientID, data) if err != nil { - log.Printf("logging adapter: CreateToken %s failed: %v", tokenType, err) + log.Printf("logging adapter: CreateToken %s failed (signature: %s, clientID: %s): %v", tokenType, signature, clientID, err) l.inc("CreateTokenError") } else { l.inc("CreateToken")