聊聊dubbo-go的AccessLogFilter

/ golang / 没有评论 / 70浏览

本文主要研究一下dubbo-go的AccessLogFilter

AccessLogFilter

dubbo-go-v1.4.2/filter/filter_impl/access_log_filter.go

type AccessLogFilter struct {
	logChan chan AccessLogData
}

Invoke

dubbo-go-v1.4.2/filter/filter_impl/access_log_filter.go

func (ef *AccessLogFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
	accessLog := invoker.GetUrl().GetParam(constant.ACCESS_LOG_KEY, "")
	if len(accessLog) > 0 {
		accessLogData := AccessLogData{data: ef.buildAccessLogData(invoker, invocation), accessLog: accessLog}
		ef.logIntoChannel(accessLogData)
	}
	return invoker.Invoke(ctx, invocation)
}

logIntoChannel

dubbo-go-v1.4.2/filter/filter_impl/access_log_filter.go

func (ef *AccessLogFilter) logIntoChannel(accessLogData AccessLogData) {
	select {
	case ef.logChan <- accessLogData:
		return
	default:
		logger.Warn("The channel is full and the access logIntoChannel data will be dropped")
		return
	}
}

buildAccessLogData

dubbo-go-v1.4.2/filter/filter_impl/access_log_filter.go

func (ef *AccessLogFilter) buildAccessLogData(_ protocol.Invoker, invocation protocol.Invocation) map[string]string {
	dataMap := make(map[string]string, 16)
	attachments := invocation.Attachments()
	dataMap[constant.INTERFACE_KEY] = attachments[constant.INTERFACE_KEY]
	dataMap[constant.METHOD_KEY] = invocation.MethodName()
	dataMap[constant.VERSION_KEY] = attachments[constant.VERSION_KEY]
	dataMap[constant.GROUP_KEY] = attachments[constant.GROUP_KEY]
	dataMap[constant.TIMESTAMP_KEY] = time.Now().Format(MessageDateLayout)
	dataMap[constant.LOCAL_ADDR], _ = attachments[constant.LOCAL_ADDR]
	dataMap[constant.REMOTE_ADDR], _ = attachments[constant.REMOTE_ADDR]

	if len(invocation.Arguments()) > 0 {
		builder := strings.Builder{}
		// todo(after the paramTypes were set to the invocation. we should change this implementation)
		typeBuilder := strings.Builder{}

		builder.WriteString(reflect.ValueOf(invocation.Arguments()[0]).String())
		typeBuilder.WriteString(reflect.TypeOf(invocation.Arguments()[0]).Name())
		for idx := 1; idx < len(invocation.Arguments()); idx++ {
			arg := invocation.Arguments()[idx]
			builder.WriteString(",")
			builder.WriteString(reflect.ValueOf(arg).String())

			typeBuilder.WriteString(",")
			typeBuilder.WriteString(reflect.TypeOf(arg).Name())
		}
		dataMap[Arguments] = builder.String()
		dataMap[Types] = typeBuilder.String()
	}

	return dataMap
}

writeLogToFile

dubbo-go-v1.4.2/filter/filter_impl/access_log_filter.go

func (ef *AccessLogFilter) writeLogToFile(data AccessLogData) {
	accessLog := data.accessLog
	if isDefault(accessLog) {
		logger.Info(data.toLogMessage())
		return
	}

	logFile, err := ef.openLogFile(accessLog)
	if err != nil {
		logger.Warnf("Can not open the access log file: %s, %v", accessLog, err)
		return
	}
	logger.Debugf("Append log to %s", accessLog)
	message := data.toLogMessage()
	message = message + "\n"
	_, err = logFile.WriteString(message)
	if err != nil {
		logger.Warnf("Can not write the log into access log file: %s, %v", accessLog, err)
	}
}

GetAccessLogFilter

dubbo-go-v1.4.2/filter/filter_impl/access_log_filter.go

func GetAccessLogFilter() filter.Filter {
	accessLogFilter := &AccessLogFilter{logChan: make(chan AccessLogData, LogMaxBuffer)}
	go func() {
		for accessLogData := range accessLogFilter.logChan {
			accessLogFilter.writeLogToFile(accessLogData)
		}
	}()
	return accessLogFilter
}

小结

AccessLogFilter定义了AccessLogData类型的chan;Invoke方法首先通过invoker.GetUrl().GetParam获取constant.ACCESS_LOG_KEY配置,若accessLog有值,则通过ef.buildAccessLogData构建accessLogData,然后执行ef.logIntoChannel(accessLogData),最后执行invoker.Invoke(ctx, invocation)

doc