Merge pull request #46585 from cpuguy83/fix_etwlogs
Revert "daemon/logger/etwlogs: rewrite to use go-winio/pkg/etw"
This commit is contained in:
commit
d7caea206e
1 changed files with 39 additions and 31 deletions
|
@ -14,12 +14,11 @@ package etwlogs // import "github.com/docker/docker/daemon/logger/etwlogs"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/Microsoft/go-winio/pkg/etw"
|
|
||||||
"github.com/Microsoft/go-winio/pkg/guid"
|
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/docker/docker/daemon/logger"
|
"github.com/docker/docker/daemon/logger"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
|
@ -34,21 +33,18 @@ type etwLogs struct {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
name = "etwlogs"
|
name = "etwlogs"
|
||||||
providerGUID = `a3693192-9ed6-46d2-a981-f8226c8363bd`
|
|
||||||
win32CallSuccess = 0
|
win32CallSuccess = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
modAdvapi32 = windows.NewLazySystemDLL("Advapi32.dll")
|
modAdvapi32 = windows.NewLazySystemDLL("Advapi32.dll")
|
||||||
|
procEventRegister = modAdvapi32.NewProc("EventRegister")
|
||||||
procEventWriteString = modAdvapi32.NewProc("EventWriteString")
|
procEventWriteString = modAdvapi32.NewProc("EventWriteString")
|
||||||
|
procEventUnregister = modAdvapi32.NewProc("EventUnregister")
|
||||||
)
|
)
|
||||||
|
var providerHandle windows.Handle
|
||||||
var (
|
var refCount int
|
||||||
providerHandle windows.Handle
|
var mu sync.Mutex
|
||||||
mu sync.Mutex
|
|
||||||
refCount int
|
|
||||||
provider *etw.Provider
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
providerHandle = windows.InvalidHandle
|
providerHandle = windows.InvalidHandle
|
||||||
|
@ -74,7 +70,12 @@ func New(info logger.Info) (logger.Logger, error) {
|
||||||
|
|
||||||
// Log logs the message to the ETW stream.
|
// Log logs the message to the ETW stream.
|
||||||
func (etwLogger *etwLogs) Log(msg *logger.Message) error {
|
func (etwLogger *etwLogs) Log(msg *logger.Message) error {
|
||||||
// TODO(thaJeztah): log structured events instead and use provider.WriteEvent().
|
if providerHandle == windows.InvalidHandle {
|
||||||
|
// This should never be hit, if it is, it indicates a programming error.
|
||||||
|
errorMessage := "ETWLogs cannot log the message, because the event provider has not been registered."
|
||||||
|
log.G(context.TODO()).Error(errorMessage)
|
||||||
|
return errors.New(errorMessage)
|
||||||
|
}
|
||||||
m := createLogMessage(etwLogger, msg)
|
m := createLogMessage(etwLogger, msg)
|
||||||
logger.PutMessage(msg)
|
logger.PutMessage(msg)
|
||||||
return callEventWriteString(m)
|
return callEventWriteString(m)
|
||||||
|
@ -105,8 +106,7 @@ func registerETWProvider() error {
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
if refCount == 0 {
|
if refCount == 0 {
|
||||||
var err error
|
var err error
|
||||||
provider, err = callEventRegister()
|
if err = callEventRegister(); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,43 +119,51 @@ func unregisterETWProvider() {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
if refCount == 1 {
|
if refCount == 1 {
|
||||||
if err := callEventUnregister(); err != nil {
|
if callEventUnregister() {
|
||||||
// Not returning an error if EventUnregister fails, because etwLogs will continue to work
|
refCount--
|
||||||
return
|
providerHandle = windows.InvalidHandle
|
||||||
}
|
}
|
||||||
refCount--
|
// Not returning an error if EventUnregister fails, because etwLogs will continue to work
|
||||||
provider = nil
|
|
||||||
providerHandle = windows.InvalidHandle
|
|
||||||
} else {
|
} else {
|
||||||
refCount--
|
refCount--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func callEventRegister() (*etw.Provider, error) {
|
func callEventRegister() error {
|
||||||
providerID, _ := guid.FromString(providerGUID)
|
// The provider's GUID is {a3693192-9ed6-46d2-a981-f8226c8363bd}
|
||||||
p, err := etw.NewProviderWithOptions("", etw.WithID(providerID))
|
guid := windows.GUID{
|
||||||
if err != nil {
|
Data1: 0xa3693192,
|
||||||
log.G(context.TODO()).WithError(err).Error("Failed to register ETW provider")
|
Data2: 0x9ed6,
|
||||||
return nil, fmt.Errorf("failed to register ETW provider: %v", err)
|
Data3: 0x46d2,
|
||||||
|
Data4: [8]byte{0xa9, 0x81, 0xf8, 0x22, 0x6c, 0x83, 0x63, 0xbd},
|
||||||
}
|
}
|
||||||
return p, nil
|
|
||||||
|
ret, _, _ := procEventRegister.Call(uintptr(unsafe.Pointer(&guid)), 0, 0, uintptr(unsafe.Pointer(&providerHandle)))
|
||||||
|
if ret != win32CallSuccess {
|
||||||
|
errorMessage := fmt.Sprintf("Failed to register ETW provider. Error: %d", ret)
|
||||||
|
log.G(context.TODO()).Error(errorMessage)
|
||||||
|
return errors.New(errorMessage)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(thaJeztah): port this function to github.com/Microsoft/go-winio/pkg/etw.
|
|
||||||
func callEventWriteString(message string) error {
|
func callEventWriteString(message string) error {
|
||||||
utf16message, err := windows.UTF16FromString(message)
|
utf16message, err := windows.UTF16FromString(message)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ret, _, _ := procEventWriteString.Call(uintptr(providerHandle), 0, 0, uintptr(unsafe.Pointer(&utf16message[0])))
|
ret, _, _ := procEventWriteString.Call(uintptr(providerHandle), 0, 0, uintptr(unsafe.Pointer(&utf16message[0])))
|
||||||
if ret != win32CallSuccess {
|
if ret != win32CallSuccess {
|
||||||
log.G(context.TODO()).WithError(err).Error("ETWLogs provider failed to log message")
|
errorMessage := fmt.Sprintf("ETWLogs provider failed to log message. Error: %d", ret)
|
||||||
return fmt.Errorf("ETWLogs provider failed to log message: %v", err)
|
log.G(context.TODO()).Error(errorMessage)
|
||||||
|
return errors.New(errorMessage)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func callEventUnregister() error {
|
func callEventUnregister() bool {
|
||||||
return provider.Close()
|
ret, _, _ := procEventUnregister.Call(uintptr(providerHandle))
|
||||||
|
return ret == win32CallSuccess
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue