Skip to content

Commit 4c597c8

Browse files
Introduce logging adapter
1 parent 03d8844 commit 4c597c8

2 files changed

Lines changed: 235 additions & 3 deletions

File tree

logging_adapter.go

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"log"
6+
"sync"
7+
"time"
8+
9+
"github.com/ory/fosite"
10+
"github.com/ory/fosite/handler/oauth2"
11+
"github.com/ory/fosite/handler/openid"
12+
"github.com/ory/fosite/handler/pkce"
13+
)
14+
15+
// LoggingAdapter wraps another StorageInterface and logs all operations.
16+
// fullStorage groups all interfaces required by fosite's Compose plus our
17+
// generic StorageInterface. Any real backend (memory or DB) should implement
18+
// all of them.
19+
type fullStorage interface {
20+
fosite.Storage
21+
openid.OpenIDConnectRequestStorage
22+
oauth2.CoreStorage
23+
oauth2.TokenRevocationStorage
24+
pkce.PKCERequestStorage
25+
StorageInterface
26+
}
27+
28+
// LoggingAdapter wraps another storage backend and records metrics while
29+
// delegating all operations to it.
30+
type LoggingAdapter struct {
31+
fullStorage
32+
mu sync.Mutex
33+
metrics map[string]int
34+
}
35+
36+
// NewLoggingAdapter creates a new adapter with the given backend.
37+
func NewLoggingAdapter(backend fullStorage) *LoggingAdapter {
38+
return &LoggingAdapter{fullStorage: backend, metrics: make(map[string]int)}
39+
}
40+
41+
func (l *LoggingAdapter) inc(key string) {
42+
l.mu.Lock()
43+
l.metrics[key]++
44+
l.mu.Unlock()
45+
}
46+
47+
// Metrics returns a copy of collected metrics.
48+
func (l *LoggingAdapter) Metrics() map[string]int {
49+
l.mu.Lock()
50+
defer l.mu.Unlock()
51+
copy := make(map[string]int, len(l.metrics))
52+
for k, v := range l.metrics {
53+
copy[k] = v
54+
}
55+
return copy
56+
}
57+
58+
func (l *LoggingAdapter) GetClient(ctx context.Context, id string) (fosite.Client, error) {
59+
c, err := l.fullStorage.GetClient(ctx, id)
60+
if err != nil {
61+
log.Printf("logging adapter: GetClient %s failed: %v", id, err)
62+
l.inc("GetClientError")
63+
} else {
64+
l.inc("GetClient")
65+
}
66+
return c, err
67+
}
68+
69+
func (l *LoggingAdapter) CreateClient(ctx context.Context, client fosite.Client) error {
70+
err := l.fullStorage.CreateClient(ctx, client)
71+
if err != nil {
72+
log.Printf("logging adapter: CreateClient %s failed: %v", client.GetID(), err)
73+
l.inc("CreateClientError")
74+
} else {
75+
l.inc("CreateClient")
76+
}
77+
return err
78+
}
79+
80+
func (l *LoggingAdapter) UpdateClient(ctx context.Context, client fosite.Client) error {
81+
err := l.fullStorage.UpdateClient(ctx, client)
82+
if err != nil {
83+
log.Printf("logging adapter: UpdateClient %s failed: %v", client.GetID(), err)
84+
l.inc("UpdateClientError")
85+
} else {
86+
l.inc("UpdateClient")
87+
}
88+
return err
89+
}
90+
91+
func (l *LoggingAdapter) DeleteClient(ctx context.Context, id string) error {
92+
err := l.fullStorage.DeleteClient(ctx, id)
93+
if err != nil {
94+
log.Printf("logging adapter: DeleteClient %s failed: %v", id, err)
95+
l.inc("DeleteClientError")
96+
} else {
97+
l.inc("DeleteClient")
98+
}
99+
return err
100+
}
101+
102+
func (l *LoggingAdapter) CreateToken(ctx context.Context, tokenType, signature, clientID string, data interface{}) error {
103+
err := l.fullStorage.CreateToken(ctx, tokenType, signature, clientID, data)
104+
if err != nil {
105+
log.Printf("logging adapter: CreateToken %s failed: %v", tokenType, err)
106+
l.inc("CreateTokenError")
107+
} else {
108+
l.inc("CreateToken")
109+
}
110+
return err
111+
}
112+
113+
func (l *LoggingAdapter) GetToken(ctx context.Context, tokenType, signature string) (interface{}, error) {
114+
v, err := l.fullStorage.GetToken(ctx, tokenType, signature)
115+
if err != nil {
116+
log.Printf("logging adapter: GetToken %s failed: %v", tokenType, err)
117+
l.inc("GetTokenError")
118+
} else {
119+
l.inc("GetToken")
120+
}
121+
return v, err
122+
}
123+
124+
func (l *LoggingAdapter) DeleteToken(ctx context.Context, tokenType, signature string) error {
125+
err := l.fullStorage.DeleteToken(ctx, tokenType, signature)
126+
if err != nil {
127+
log.Printf("logging adapter: DeleteToken %s failed: %v", tokenType, err)
128+
l.inc("DeleteTokenError")
129+
} else {
130+
l.inc("DeleteToken")
131+
}
132+
return err
133+
}
134+
135+
func (l *LoggingAdapter) RevokeToken(ctx context.Context, tokenType, signature string) error {
136+
err := l.fullStorage.RevokeToken(ctx, tokenType, signature)
137+
if err != nil {
138+
log.Printf("logging adapter: RevokeToken %s failed: %v", tokenType, err)
139+
l.inc("RevokeTokenError")
140+
} else {
141+
l.inc("RevokeToken")
142+
}
143+
return err
144+
}
145+
146+
func (l *LoggingAdapter) CreateSession(ctx context.Context, sessionType, id string, data interface{}) error {
147+
err := l.fullStorage.CreateSession(ctx, sessionType, id, data)
148+
if err != nil {
149+
log.Printf("logging adapter: CreateSession %s failed: %v", sessionType, err)
150+
l.inc("CreateSessionError")
151+
} else {
152+
l.inc("CreateSession")
153+
}
154+
return err
155+
}
156+
157+
func (l *LoggingAdapter) GetSession(ctx context.Context, sessionType, id string) (interface{}, error) {
158+
v, err := l.fullStorage.GetSession(ctx, sessionType, id)
159+
if err != nil {
160+
log.Printf("logging adapter: GetSession %s failed: %v", sessionType, err)
161+
l.inc("GetSessionError")
162+
} else {
163+
l.inc("GetSession")
164+
}
165+
return v, err
166+
}
167+
168+
func (l *LoggingAdapter) DeleteSession(ctx context.Context, sessionType, id string) error {
169+
err := l.fullStorage.DeleteSession(ctx, sessionType, id)
170+
if err != nil {
171+
log.Printf("logging adapter: DeleteSession %s failed: %v", sessionType, err)
172+
l.inc("DeleteSessionError")
173+
} else {
174+
l.inc("DeleteSession")
175+
}
176+
return err
177+
}
178+
179+
func (l *LoggingAdapter) ValidateJWT(ctx context.Context, jti string) error {
180+
err := l.fullStorage.ValidateJWT(ctx, jti)
181+
if err != nil {
182+
log.Printf("logging adapter: ValidateJWT failed: %v", err)
183+
l.inc("ValidateJWTError")
184+
} else {
185+
l.inc("ValidateJWT")
186+
}
187+
return err
188+
}
189+
190+
func (l *LoggingAdapter) MarkJWTAsUsed(ctx context.Context, jti string, exp time.Time) error {
191+
err := l.fullStorage.MarkJWTAsUsed(ctx, jti, exp)
192+
if err != nil {
193+
log.Printf("logging adapter: MarkJWTAsUsed failed: %v", err)
194+
l.inc("MarkJWTAsUsedError")
195+
} else {
196+
l.inc("MarkJWTAsUsed")
197+
}
198+
return err
199+
}
200+
201+
func (l *LoggingAdapter) GetPKCERequestSession(ctx context.Context, signature string, session fosite.Session) (fosite.Requester, error) {
202+
v, err := l.fullStorage.GetPKCERequestSession(ctx, signature, session)
203+
if err != nil {
204+
log.Printf("logging adapter: GetPKCERequestSession failed: %v", err)
205+
l.inc("GetPKCESessionError")
206+
} else {
207+
l.inc("GetPKCESession")
208+
}
209+
return v, err
210+
}
211+
212+
func (l *LoggingAdapter) CreatePKCERequestSession(ctx context.Context, signature string, requester fosite.Requester) error {
213+
err := l.fullStorage.CreatePKCERequestSession(ctx, signature, requester)
214+
if err != nil {
215+
log.Printf("logging adapter: CreatePKCERequestSession failed: %v", err)
216+
l.inc("CreatePKCESessionError")
217+
} else {
218+
l.inc("CreatePKCESession")
219+
}
220+
return err
221+
}
222+
223+
func (l *LoggingAdapter) DeletePKCERequestSession(ctx context.Context, signature string) error {
224+
err := l.fullStorage.DeletePKCERequestSession(ctx, signature)
225+
if err != nil {
226+
log.Printf("logging adapter: DeletePKCERequestSession failed: %v", err)
227+
l.inc("DeletePKCESessionError")
228+
} else {
229+
l.inc("DeletePKCESession")
230+
}
231+
return err
232+
}

main.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import (
1313
"github.com/ory/fosite/handler/openid"
1414
)
1515

16-
// For this example, we use an in-memory store.
17-
// In a real-world application, you would use a persistent store (e.g., SQL database).
18-
var store = NewInMemoryStore()
16+
// For this example, we use an in-memory store wrapped by a logging adapter.
17+
// This demonstrates how a new storage adapter can be integrated gradually.
18+
var store StorageInterface = NewLoggingAdapter(NewInMemoryStore())
1919

2020
// Fosite configuration using fosite.Config for v0.49.0+
2121
var fositeConfig = &fosite.Config{

0 commit comments

Comments
 (0)