1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/daemon/logger/plugin.go
Brian Goff 27bd6842f8 Implement plugins for logging drivers
Logging plugins use the same HTTP interface as other plugins for basic
command operations meanwhile actual logging operations are handled (on
Unix) via a fifo.

The plugin interface looks like so:

```go
type loggingPlugin interface {
  StartLogging(fifoPath string, loggingContext Context) error
  StopLogging(fifoPath)
```

This means a plugin must implement `LoggingDriver.StartLogging` and
`LoggingDriver.StopLogging` endpoints and be able to consume the passed
in fifo.

Logs are sent via stream encoder to the fifo encoded with protobuf.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2017-04-10 13:17:20 -04:00

89 lines
2.2 KiB
Go

package logger
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/docker/docker/api/types/plugins/logdriver"
getter "github.com/docker/docker/pkg/plugingetter"
"github.com/docker/docker/pkg/stringid"
"github.com/pkg/errors"
)
var pluginGetter getter.PluginGetter
const extName = "LogDriver"
// logPlugin defines the available functions that logging plugins must implement.
type logPlugin interface {
StartLogging(streamPath string, info Info) (err error)
StopLogging(streamPath string) (err error)
Capabilities() (cap Capability, err error)
ReadLogs(info Info, config ReadConfig) (stream io.ReadCloser, err error)
}
// RegisterPluginGetter sets the plugingetter
func RegisterPluginGetter(plugingetter getter.PluginGetter) {
pluginGetter = plugingetter
}
// GetDriver returns a logging driver by its name.
// If the driver is empty, it looks for the local driver.
func getPlugin(name string, mode int) (Creator, error) {
p, err := pluginGetter.Get(name, extName, mode)
if err != nil {
return nil, fmt.Errorf("error looking up logging plugin %s: %v", name, err)
}
d := &logPluginProxy{p.Client()}
return makePluginCreator(name, d, p.BasePath()), nil
}
func makePluginCreator(name string, l *logPluginProxy, basePath string) Creator {
return func(logCtx Info) (logger Logger, err error) {
defer func() {
if err != nil {
pluginGetter.Get(name, extName, getter.Release)
}
}()
root := filepath.Join(basePath, "run", "docker", "logging")
if err := os.MkdirAll(root, 0700); err != nil {
return nil, err
}
id := stringid.GenerateNonCryptoID()
a := &pluginAdapter{
driverName: name,
id: id,
plugin: l,
fifoPath: filepath.Join(root, id),
logInfo: logCtx,
}
cap, err := a.plugin.Capabilities()
if err == nil {
a.capabilities = cap
}
stream, err := openPluginStream(a)
if err != nil {
return nil, err
}
a.stream = stream
a.enc = logdriver.NewLogEntryEncoder(a.stream)
if err := l.StartLogging(strings.TrimPrefix(a.fifoPath, basePath), logCtx); err != nil {
return nil, errors.Wrapf(err, "error creating logger")
}
if cap.ReadLogs {
return &pluginAdapterWithRead{a}, nil
}
return a, nil
}
}