跳转至主要内容

日志 & 错误处理

日志

Cabin默认使用内置的 log 来将日志输出到控制台,如:

2017/07/15 19:43:56 [Request: alice, data1, read ---> true]

日志记录不是默认启用的。 您可以通过调用 Enforcer.EnableLog()NewEnforcer()函数中的最后一个参数来切换它。

备注

我们已经支持日志模型、强制请求、角色、Golang策略。 您可以定义您自己的日志来记录Casbin。 如果您正在使用 Python, pycasbin 会影响默认的 Python 日志机制。 Pycasbin 软件包调用logging.getLogger()来设置日志。 除了初始化父应用程序中的日志记录器外,不需要特殊配置的日志。 如果父应用程序内没有输入日志,您将不会看到来自pycasbin的日志消息。

对不同的执行器使用不同的记录器

每个执行器都可以有自己的记录器来记录信息,并且可以在运行时进行更改。

而且你可以通过 NewEnterer()的最后一个参数使用一个适当的日志。 如果您使用这种方式来初始化您的执行器,由于日志中启用的字段的优先级更高,您不需要使用启用参数。

// 设置默认记录器作为执行器e1的记录器。
//此操作也可以被视为在运行时更改e1的记录器。
e1.SetLogger(&Log.DefaultLogger{})

// 设置另一个记录器作为执行器e2的日志记录器。
e2.SetLogger(&YouOwnLogger)

// 初始化执行器e3时设置您的记录器。
e3, _ := casbin.NewEnforcer("examples/rbac_model.conf", a, logger)

支持的记录器

我们提供了一些记录器来帮助您记录信息。

记录器作者描述
Defatule logger (内置)Casbin默认使用golang日志。
Zap loggerCasbin使用 zap,提供json 编码日志,您可以使用自己的 zap-logger 自定义更多信息。

如何编写一个记录器

您的记录器应该实现 Logger 接口。

接口名实现要素描述
EnableLog()必须控制是否打印消息。
IsEnabled()必须显示当前日志启用的状态。
LogModel()必须与模型相关的日志信息。
LogEnforce()必须与执行器相关的日志信息。
LogRole()必须与角色相关的日志信息。
LogPolicy()必须与策略相关的日志信息。

您可以将您的自定义 记录器 传给 Enforcer.SetLogger()函数。

这是一个关于如何自定义Golang日志的示例:

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

// 默认日志是使用golang日志的日志实现的。
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时可能会由于以下原因发生错误或恐慌:

  1. Model文件 (. conf) 中的语法有误。
  2. 策略文件(.csv)中语法有误。
  3. 来adapter的自定义错误信息(譬如连接MySQL失败)。
  4. Casbin的bug。

您可能需要五个主要功能来处理错误或恐慌:

Function异常时表现
NewEnforcer()返回error
LoadModel()返回error
LoadPolicy()返回error
SavePolicy()返回error
Enforce()返回error
备注

NewEnforcer()通过内部调用LoadModel()LoadPolicy()。 所以当您使用NewEnforcer()函数时不需要再去调用这两个函数。

启用 & 禁用

可以通过 Encer.EnableEnforcece() 函数禁用执行器。 当它被禁用时, Enforcer.Enforce() 将总是返回 true。 诸如添加或删除政策之类的其他操作将不受影响。 下面是一个示例:

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

// 将会返回false
// 默认情况下enforcer是启用的
e.Enforce("non-authorized-user", "data1", "read")

// 在运行时禁用enforcer
e.EnableEnforce(false)

// 对任何请求都返回true
e.Enforce("non-authorized-user", "data1", "read")

// 打开enforcer
e.EnableEnforce(true)

// 将会返回false
e.Enforce("non-authorized-user", "data1", "read")