주요 콘텐츠로 건너뛰기

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()의 마지막 매개변수를 통해 적절한 로거를 사용할 수 있습니다. 이 방법을 사용하여 강제자를 초기화하는 경우, 로거의 enabled 필드의 우선 순위가 더 높기 때문에 enabled 매개변수를 사용할 필요가 없습니다.

// 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)

지원되는 로거들

우리는 정보를 로그에 기록하는 데 도움이 될 몇 가지 로거를 제공합니다.

로거저자설명
기본 로거 (내장)Casbingolang 로그를 사용하는 기본 로거입니다.
Zap 로거Casbinzap를 사용하여 json 인코딩 로그를 제공하며, 자신만의 zap-logger로 더 많은 것을 사용자 정의할 수 있습니다.

로거 작성 방법

로거는 Logger 인터페이스를 구현해야 합니다.

방법유형설명
EnableLog()필수메시지를 출력할지 여부를 제어합니다.
IsEnabled()필수현재 로거의 활성화 상태를 표시합니다.
LogModel()필수모델과 관련된 로그 정보.
LogEnforce()필수강제 실행과 관련된 로그 정보.
LogRole()필수역할과 관련된 로그 정보.
LogPolicy()필수정책과 관련된 로그 정보.

Enforcer.SetLogger()에 사용자 정의 logger를 전달할 수 있습니다.

다음은 Golang에 대한 로거를 사용자 정의하는 방법의 예입니다:

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을 사용할 때 오류 또는 패닉이 발생할 수 있습니다:

  1. 모델 파일 (.conf)의 구문이 잘못되었습니다.
  2. 정책 파일 (.csv)의 구문이 잘못되었습니다.
  3. 저장소 어댑터에서의 사용자 정의 오류, 예를 들어, MySQL이 연결에 실패한 경우.
  4. Casbin의 버그.

오류 또는 패닉에 대해 알아야 할 주요 함수는 다섯 가지입니다:

함수오류 발생 시 동작
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")