func (r *Route) MatchContainer(id, name string, labels map[string]string) bool {
	if r.matchAll() {
		return true
	}
	if r.FilterID != "" && !strings.HasPrefix(id, r.FilterID) {
		return false
	}
	match, err := path.Match(r.FilterName, name)
	if err != nil || (r.FilterName != "" && !match) {
		return false
	}
	for _, label := range r.FilterLabels {
		labelParts := strings.SplitN(label, ":", 2)
		if len(labelParts) > 1 {
			labelKey := labelParts[0]
			labelValue := labelParts[1]
			labelMatch, labelErr := path.Match(labelValue, labels[labelKey])
			if labelErr != nil || (labelValue != "" && !labelMatch) {
				return false
			}
		}
	}
	return true
}
MatchContainer returns whether the Route is responsible for a given container
package router
import (
	"net"
	"net/http"
	"path"
	"strings"
	"time"
	docker "github.com/fsouza/go-dockerclient"
)
type HTTPHandler func() http.Handler
type AdapterFactory func(route *Route) (LogAdapter, error)
type AdapterTransport interface {
	Dial(addr string, options map[string]string) (net.Conn, error)
}
type LogAdapter interface {
	Stream(logstream chan *Message)
}
type Job interface {
	Run() error
	Setup() error
	Name() string
}
type LogRouter interface {
	RoutingFrom(containerID string) bool
	Route(route *Route, logstream chan *Message)
}
type RouteStore interface {
	Get(id string) (*Route, error)
	GetAll() ([]*Route, error)
	Add(route *Route) error
	Remove(id string) bool
}
type Message struct {
	Container *docker.Container
	Source    string
	Data      string
	Time      time.Time
}
type Route struct {
	ID            string            `json:"id"`
	FilterID      string            `json:"filter_id,omitempty"`
	FilterName    string            `json:"filter_name,omitempty"`
	FilterSources []string          `json:"filter_sources,omitempty"`
	FilterLabels  []string          `json:"filter_labels,omitempty"`
	Adapter       string            `json:"adapter"`
	Address       string            `json:"address"`
	Options       map[string]string `json:"options,omitempty"`
	adapter       LogAdapter
	closed        bool
	closer        chan struct{}
	closerRcv     <-chan struct{}  
}
func (r *Route) AdapterType() string {
	return strings.Split(r.Adapter, "+")[0]
}
func (r *Route) AdapterTransport(dfault string) string {
	parts := strings.Split(r.Adapter, "+")
	if len(parts) > 1 {
		return parts[1]
	}
	return dfault
}
func (r *Route) Closer() <-chan struct{} {
	if r.closerRcv != nil {
		return r.closerRcv
	}
	return r.closer
}
func (r *Route) OverrideCloser(closer <-chan struct{}) {
	r.closerRcv = closer
}
func (r *Route) Close() {
	r.closer <- struct{}{}
}
func (r *Route) matchAll() bool {
	if r.FilterID == "" && r.FilterName == "" && len(r.FilterSources) == 0 && len(r.FilterLabels) == 0 {
		return true
	}
	return false
}
func (r *Route) MultiContainer() bool {
	return r.matchAll() || strings.Contains(r.FilterName, "*")
}