ข้ามไปยังเนื้อหาหลัก

Logging & Error Handling

การบันทึก

Casbin can log requests, model load, and policy changes. Logging is off by default. Turn it on with Enforcer.EnableLog() or via the logger parameter to NewEnforcer(). Example output:

2017/07/15 19:43:56 [Request: alice, data1, read ---> true]
หมายเหตุ

Go: You can plug in a custom logger; Casbin logs models, requests, roles, and policies through it.

หมายเหตุ

Python: PyCasbin uses the standard logging module. Configure your app’s logging as usual; PyCasbin uses logging.getLogger(). Optional logging_config is documented in pycasbin/util/log.py. See Python logging and Django logging for setup.

Configure Separate Loggers for Different Enforcers

Each enforcer can have its own logger, and loggers can be changed at runtime.

You can specify a logger using the last parameter of NewEnforcer(). When using this method, the logger's enabled field takes precedence over the enforcer's enabled parameter.

// Set a default logger as enforcer e1's logger.
// This operation can also be seen as changing the logger of e1 at runtime.
e1.SetLogger(&Log.DefaultLogger{})

// Set another logger as enforcer e2's logger.
e2.SetLogger(&YouOwnLogger)

// Set your logger when initializing enforcer e3.
e3, _ := casbin.NewEnforcer("examples/rbac_model.conf", a, logger)

Supported Loggers

Casbin provides several logger implementations:

LoggerAuthorDescription
Default logger (built-in)CasbinThe default logger using Go's standard log package.
Zap loggerCasbinUses zap for JSON-encoded logs with additional customization options via zap-logger.

Implementing Custom Loggers

Custom loggers must implement the Logger interface.

MethodTypeDescription
EnableLog()mandatoryControls whether messages are printed.
IsEnabled()mandatoryReturns the current logger's enabled status.
LogModel()mandatoryLogs model-related information.
LogEnforce()mandatoryLogs enforcement-related information.
LogRole()mandatoryLogs role-related information.
LogPolicy()mandatoryLogs policy-related information.

Pass your custom logger to Enforcer.SetLogger().

Here's a Go example of implementing a custom logger:

import (
"fmt"
"log"
"strings"
)

// DefaultLogger is the implementation for a Logger using golang log.
type DefaultLogger struct {
enabled bool
}

func (l *DefaultLogger) EnableLog(enable bool) {
l.enabled = enable
}

func (l *DefaultLogger) IsEnabled() bool {
return l.enabled
}

func (l *DefaultLogger) LogModel(model [][]string) {
if !l.enabled {
return
}
var str strings.Builder
str.WriteString("Model: ")
for _, v := range model {
str.WriteString(fmt.Sprintf("%v\n", v))
}

log.Println(str.String())
}

func (l *DefaultLogger) LogEnforce(matcher string, request []interface{}, result bool, explains [][]string) {
if !l.enabled {
return
}

var reqStr strings.Builder
reqStr.WriteString("Request: ")
for i, rval := range request {
if i != len(request)-1 {
reqStr.WriteString(fmt.Sprintf("%v, ", rval))
} else {
reqStr.WriteString(fmt.Sprintf("%v", rval))
}
}
reqStr.WriteString(fmt.Sprintf(" ---> %t\n", result))

reqStr.WriteString("Hit Policy: ")
for i, pval := range explains {
if i != len(explains)-1 {
reqStr.WriteString(fmt.Sprintf("%v, ", pval))
} else {
reqStr.WriteString(fmt.Sprintf("%v \n", pval))
}
}

log.Println(reqStr.String())
}

func (l *DefaultLogger) LogPolicy(policy map[string][][]string) {
if !l.enabled {
return
}

var str strings.Builder
str.WriteString("Policy: ")
for k, v := range policy {
str.WriteString(fmt.Sprintf("%s : %v\n", k, v))
}

log.Println(str.String())
}

func (l *DefaultLogger) LogRole(roles []string) {
if !l.enabled {
return
}

log.Println("Roles: ", roles)
}

Error Handling

Errors or panics can occur in Casbin for several reasons:

  1. Invalid syntax in the model file (.conf)
  2. Invalid syntax in the policy file (.csv)
  3. Custom errors from storage adapters (e.g., MySQL connection failures)
  4. Casbin bugs

Five primary functions may produce errors or panics:

FunctionBehavior on Error
NewEnforcer()Returns an error
LoadModel()Returns an error
LoadPolicy()Returns an error
SavePolicy()Returns an error
Enforce()Returns an error
หมายเหตุ

NewEnforcer() calls both LoadModel() and LoadPolicy() internally, so you don't need to call them separately when using NewEnforcer().

Enabling and Disabling Enforcement

You can disable the enforcer using Enforcer.EnableEnforce(). When disabled, Enforcer.Enforce() always returns true. Other operations like policy management remain unaffected. Example:

e := casbin.NewEnforcer("examples/basic_model.conf", "examples/basic_policy.csv")

// Will return false.
// By default, the enforcer is enabled.
e.Enforce("non-authorized-user", "data1", "read")

// Disable the enforcer at runtime.
e.EnableEnforce(false)

// Will return true for any request.
e.Enforce("non-authorized-user", "data1", "read")

// Enable the enforcer again.
e.EnableEnforce(true)

// Will return false.
e.Enforce("non-authorized-user", "data1", "read")