日志 & 错误处理
发布者:admin 发表于:416天前 阅读数:609 评论:0

日志 & 错误处理

日志

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

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

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

NOTE 我们已经支持日志模型、强制请求、角色、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 logger Casbin 使用 zap,提供json 编码日志,您可以使用自己的 zap-logger 自定义更多信息。

[]()如何编写一个记录器您的记录器应该实现 Logger 接口。

您可以将您的自定义 logger 传给 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时可能会由于以下原因发生错误:

Model文件 (. conf) 中的语法有误。

policy文件 (. csv) 中的语法有误。

来adapter的自定义错误信息(譬如连接MySQL失败)。

Casbin的bug。

您需要注意以下五个主要函数出现的error:

函数 异常时行为
NewEnforcer() 返回error
LoadModel() 返回error
LoadPolicy() 返回error
SavePolicy() 返回error
Enforce() 返回error

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

启用 & 禁用

通过调用Enforcer.EnableEnforce()方法,我们可以禁用Enforcer。 当它被禁用时, Enforcer.Enforce() 将总是返回 true。 但是其他操作 (例如添加或删除policy) 不受影响。 以下为一些示例:

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

// 将返回假。
// 默认情况下执行器是启用的。
e.Enforce("non-authorized-user", "data1", "read")

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

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

// 再次启用执行器。
e.EnableEnforce(true)

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