Skip to content

V3: Change design of tarantool.Logger #504

@tulzke

Description

@tulzke

The current design does not allow writing a logger without understanding the internal structure of the SDK. In practice, it ends up being a copy-paste of the default logger with minor modifications.

The issue is that the type of v changes depending on the event. This is highly implicit and leaves a lot of room for failure when performing type assertions.
The problem can be seen here:

go-tarantool/connection.go

Lines 90 to 127 in aff7842

func (d defaultLogger) Report(event ConnLogKind, conn *Connection, v ...interface{}) {
switch event {
case LogReconnectFailed:
reconnects := v[0].(uint)
err := v[1].(error)
addr := conn.Addr()
if addr == nil {
log.Printf("tarantool: connect (%d/%d) failed: %s",
reconnects, conn.opts.MaxReconnects, err)
} else {
log.Printf("tarantool: reconnect (%d/%d) to %s failed: %s",
reconnects, conn.opts.MaxReconnects, addr, err)
}
case LogLastReconnectFailed:
err := v[0].(error)
addr := conn.Addr()
if addr == nil {
log.Printf("tarantool: last connect failed: %s, giving it up",
err)
} else {
log.Printf("tarantool: last reconnect to %s failed: %s, giving it up",
addr, err)
}
case LogUnexpectedResultId:
header := v[0].(Header)
log.Printf("tarantool: connection %s got unexpected request ID (%d) in response "+
"(probably cancelled request)",
conn.Addr(), header.RequestId)
case LogWatchEventReadFailed:
err := v[0].(error)
log.Printf("tarantool: unable to parse watch event: %s", err)
case LogBoxSessionPushUnsupported:
header := v[0].(Header)
log.Printf("tarantool: unsupported box.session.push() for request %d", header.RequestId)
default:
args := append([]interface{}{"tarantool: unexpected event ", event, conn}, v...)
log.Print(args...)
}

My suggestion is that all additional context should be included directly in the event. This can be implemented using an interface and exported structures that implement it:

type ConnEvent interface {
    // some methods here
}

// implementation of ConnEvent
type LogReconnectFailed struct {
    Reconnects        uint
    MaxReconnects uint
    Error                    error
}

type Logger interface {
    Report(event ConnEvent, conn *Connection)
}

type defaultLogger struct{}

fun (defaultLogger) Report(event ConnEvent, conn *Connection) {
    switch v := event.(type){
    case LogReconnectFailed:
      // log error
    }
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Status

In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions