Skip to content

Commit 61c876f

Browse files
committed
feat: add DefaultLogger (#1648)
1 parent 6b688f0 commit 61c876f

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed

log/default_logger.go

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// Copyright 2026 The casbin Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package log
16+
17+
import (
18+
"fmt"
19+
"io"
20+
"os"
21+
"strings"
22+
"time"
23+
)
24+
25+
// DefaultLogger is the default implementation of the Logger interface.
26+
type DefaultLogger struct {
27+
output io.Writer
28+
eventTypes map[EventType]bool
29+
logCallback func(entry *LogEntry) error
30+
}
31+
32+
// NewDefaultLogger creates a new DefaultLogger instance.
33+
// If no output is set via SetOutput, it defaults to os.Stdout.
34+
func NewDefaultLogger() *DefaultLogger {
35+
return &DefaultLogger{
36+
output: os.Stdout,
37+
eventTypes: make(map[EventType]bool),
38+
}
39+
}
40+
41+
// SetOutput sets the output destination for the logger.
42+
// It can be set to a buffer or any io.Writer.
43+
func (l *DefaultLogger) SetOutput(w io.Writer) {
44+
if w != nil {
45+
l.output = w
46+
}
47+
}
48+
49+
// SetEventTypes sets the event types that should be logged.
50+
// Only events matching these types will have IsActive set to true.
51+
func (l *DefaultLogger) SetEventTypes(eventTypes []EventType) error {
52+
l.eventTypes = make(map[EventType]bool)
53+
for _, et := range eventTypes {
54+
l.eventTypes[et] = true
55+
}
56+
return nil
57+
}
58+
59+
// OnBeforeEvent is called before an event occurs.
60+
// It sets the StartTime and determines if the event should be active based on configured event types.
61+
func (l *DefaultLogger) OnBeforeEvent(entry *LogEntry) error {
62+
if entry == nil {
63+
return fmt.Errorf("log entry is nil")
64+
}
65+
66+
entry.StartTime = time.Now()
67+
68+
// Set IsActive based on whether this event type is enabled
69+
// If no event types are configured, all events are considered active
70+
if len(l.eventTypes) == 0 {
71+
entry.IsActive = true
72+
} else {
73+
entry.IsActive = l.eventTypes[entry.EventType]
74+
}
75+
76+
return nil
77+
}
78+
79+
// OnAfterEvent is called after an event completes.
80+
// It calculates the duration, logs the entry if active, and calls the user callback if set.
81+
func (l *DefaultLogger) OnAfterEvent(entry *LogEntry) error {
82+
if entry == nil {
83+
return fmt.Errorf("log entry is nil")
84+
}
85+
86+
entry.EndTime = time.Now()
87+
entry.Duration = entry.EndTime.Sub(entry.StartTime)
88+
89+
// Only log if the event is active
90+
if entry.IsActive && l.output != nil {
91+
if err := l.writeLog(entry); err != nil {
92+
return err
93+
}
94+
}
95+
96+
// Call user-provided callback if set
97+
if l.logCallback != nil {
98+
if err := l.logCallback(entry); err != nil {
99+
return err
100+
}
101+
}
102+
103+
return nil
104+
}
105+
106+
// SetLogCallback sets a user-provided callback function.
107+
// The callback is called at the end of OnAfterEvent.
108+
func (l *DefaultLogger) SetLogCallback(callback func(entry *LogEntry) error) error {
109+
l.logCallback = callback
110+
return nil
111+
}
112+
113+
// writeLog writes the log entry to the configured output.
114+
func (l *DefaultLogger) writeLog(entry *LogEntry) error {
115+
var logMessage string
116+
117+
switch entry.EventType {
118+
case EventEnforce:
119+
logMessage = fmt.Sprintf("[%s] Enforce: subject=%s, object=%s, action=%s, domain=%s, allowed=%v, duration=%v\n",
120+
entry.EventType, entry.Subject, entry.Object, entry.Action, entry.Domain, entry.Allowed, entry.Duration)
121+
case EventAddPolicy, EventRemovePolicy:
122+
logMessage = fmt.Sprintf("[%s] RuleCount=%d, duration=%v\n",
123+
entry.EventType, entry.RuleCount, entry.Duration)
124+
case EventLoadPolicy, EventSavePolicy:
125+
logMessage = fmt.Sprintf("[%s] RuleCount=%d, duration=%v\n",
126+
entry.EventType, entry.RuleCount, entry.Duration)
127+
default:
128+
logMessage = fmt.Sprintf("[%s] duration=%v\n",
129+
entry.EventType, entry.Duration)
130+
}
131+
132+
if entry.Error != nil {
133+
logMessage = strings.TrimSuffix(logMessage, "\n")
134+
logMessage = fmt.Sprintf("%s Error: %v\n", logMessage, entry.Error)
135+
}
136+
137+
_, err := l.output.Write([]byte(logMessage))
138+
return err
139+
}

0 commit comments

Comments
 (0)