Log & Error Handling
日志记录
Casbin默认使用内置的log
将日志打印到控制台,如:
2017/07/15 19:43:56 [Request: alice, data1, read ---> true]
默认情况下不启用日志记录。 您可以通过Enforcer.EnableLog()
或NewEnforcer()
的最后一个参数来切换它。
我们已经支持在Golang中记录模型,执行请求,角色和策略的日志。 您可以为Casbin定义自己的日志。
如果您正在使用Python,pycasbin利用默认的Python日志记录机制。 pycasbin包调用logging.getLogger()
来设置记录器。 除了在父应用程序中初始化记录器外,不需要其他特殊的日志记录配置。 如果在父应用程序中没有初始化日志记录,您将看不到来自pycasbin的任何日志消息。 同时,当您在pycasbin中启用日志时,它将使用默认的日志配置。 对于其他pycasbin扩展,如果您是Django用户,可以参考Django日志文档。 对于其他Python用户,您应参考Python日志文档来配置记录器。
为不同的执行器使用不同的记录器
每个执行器都可以有自己的记录器来记录信息,并且可以在运行时更改。
您可以通过NewEnforcer()
的最后一个参数使用适当的记录器。 如果您正在以这种方式初始化执行器,您不需要使用启用参数,因为记录器中启用字段的优先级更高。
// 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)
支持的记录器
我们提供了一些记录器来帮助您记录信息。
- Go
- PHP
日志记录器 | 作者 | 描述 |
---|---|---|
psr3-bridge logger | Casbin | 提供一个符合PSR-3的桥接。 |
如何编写日志记录器
您的日志记录器应实现Logger接口。
方法 | 类型 | 描述 |
---|---|---|
EnableLog() | 必需 | 控制是否打印消息。 |
IsEnabled() | 必需 | 显示当前日志记录器的启用状态。 |
LogModel() | 必需 | 记录与模型相关的信息。 |
LogEnforce() | 必需 | 记录与执行相关的信息。 |
LogRole() | 必需 | 记录与角色相关的信息。 |
LogPolicy() | 必需 | 记录与策略相关的信息。 |
你可以将你的自定义 logger
传递给 Enforcer.SetLogger()
。
这是一个如何为Golang自定义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)
}
错误处理
当你使用Casbin时,可能会因为以下原因出现错误或panic:
- 模型文件(.conf)中的语法无效。
- 策略文件(.csv)中的语法无效。
- 来自存储适配器的自定义错误,例如,MySQL无法连接。
- Casbin的bug。
你可能需要注意的五个主要函数,用于处理错误或panic:
函数 | 错误行为 |
---|---|
NewEnforcer() | 返回一个错误 |
LoadModel() | 返回一个错误 |
LoadPolicy() | 返回一个错误 |
SavePolicy() | 返回一个错误 |
Enforce() | 返回一个错误 |
NewEnforcer()
内部调用了 LoadModel()
和 LoadPolicy()
。 所以当你使用 NewEnforcer()
时,你不需要调用后两者。
启用和禁用
可以通过 Enforcer.EnableEnforce()
函数禁用执行器。 当它被禁用时,Enforcer.Enforce()
将始终返回 true
。 其他操作,如添加或删除策略,不受影响。 这是一个例子:
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")