func (m *Monitor) Watch(disco discovery.Discoverer, looper director.Looper) {
	m.DiscoveryFn = disco.Services  
	looper.Loop(func() error {
		services := disco.Services()
		for _, svc := range services {
			if m.Checks[svc.ID] == nil {
				check := m.CheckForService(&svc, disco)
				if check.Command == nil {
					log.Errorf(
						"Attempted to add %s (id: %s) but no check configured!",
						svc.Name, svc.ID,
					)
				} else {
					m.AddCheck(check)
				}
			}
		}
		m.Lock()
		defer m.Unlock()
	OUTER:
		for _, check := range m.Checks {
			for _, svc := range services {
				if svc.ID == check.ID {
					continue OUTER
				}
			}
			delete(m.Checks, check.ID)
		}
		return nil
	})
}
Watch loops over a list of services and adds checks for services we don't already
know about. It then removes any checks for services which have gone away. All
services are expected to be local to this node.
package healthy
import (
	"bytes"
	"fmt"
	"text/template"
	"github.com/NinesStack/sidecar/discovery"
	"github.com/NinesStack/sidecar/service"
	"github.com/relistan/go-director"
	log "github.com/sirupsen/logrus"
)
const (
	DEFAULT_STATUS_ENDPOINT = "/"
)
func (m *Monitor) Services() []service.Service {
	var svcList []service.Service
	if m.DiscoveryFn == nil {
		log.Errorf("Error: DiscoveryFn not defined!")
		return []service.Service{}
	}
	for _, svc := range m.DiscoveryFn() {
		if svc.ID == "" {
			log.Errorf("Error: monitor found empty service ID")
			continue
		}
		m.MarkService(&svc)
		svcList = append(svcList, svc)
	}
	return svcList
}
func findFirstTCPPort(svc *service.Service) *service.Port {
	for _, port := range svc.Ports {
		if port.Type == "tcp" {
			return &port
		}
	}
	return nil
}
func (m *Monitor) defaultCheckForService(svc *service.Service) *Check {
	port := findFirstTCPPort(svc)
	if port == nil {
		return &Check{ID: svc.ID, Command: &AlwaysSuccessfulCmd{}}
	}
	defaultCheckEndpoint := DEFAULT_STATUS_ENDPOINT
	if len(m.DefaultCheckEndpoint) != 0 {
		defaultCheckEndpoint = m.DefaultCheckEndpoint
	}
	url := fmt.Sprintf("http://%v:%v%v", m.DefaultCheckHost, port.Port, defaultCheckEndpoint)
	return &Check{
		ID:      svc.ID,
		Type:    "HttpGet",
		Args:    url,
		Status:  FAILED,
		Command: &HttpGetCmd{},
	}
}
func (m *Monitor) GetCommandNamed(name string) Checker {
	switch name {
	case "HttpGet":
		return &HttpGetCmd{}
	case "External":
		return &ExternalCmd{}
	case "AlwaysSuccessful":
		return &AlwaysSuccessfulCmd{}
	default:
		return &HttpGetCmd{}
	}
}
func (m *Monitor) fetchCheckForService(svc *service.Service, disco discovery.Discoverer) *Check {
	check := &Check{}
	check.Type, check.Args = disco.HealthCheck(svc)
	if check.Type == "" {
		log.Warnf("Got empty check type for service %s (id: %s) with args: %s!", svc.Name, svc.ID, check.Args)
		return nil
	}
	check.ID = svc.ID
	check.Command = m.GetCommandNamed(check.Type)
	check.Status = FAILED
	return check
}
func (m *Monitor) templateCheckArgs(check *Check, svc *service.Service) string {
	funcMap := template.FuncMap{
		"tcp":       func(p int64) int64 { return svc.PortForServicePort(p, "tcp") },
		"udp":       func(p int64) int64 { return svc.PortForServicePort(p, "udp") },
		"host":      func() string { return m.DefaultCheckHost },
		"container": func() string { return svc.Hostname },
	}
	t, err := template.New("check").Funcs(funcMap).Parse(check.Args)
	if err != nil {
		log.Errorf("Unable to parse check Args: '%s'", check.Args)
		return check.Args
	}
	var output bytes.Buffer
	err = t.Execute(&output, svc)
	if err != nil {
		log.Errorf("Unable to execute template: '%s'", check.Args)
		return check.Args
	}
	return output.String()
}
func (m *Monitor) CheckForService(svc *service.Service, disco discovery.Discoverer) *Check {
	check := m.fetchCheckForService(svc, disco)
	if check == nil {  
		log.Warnf("Using default check for service %s (id: %s).", svc.Name, svc.ID)
		check = m.defaultCheckForService(svc)
	}
	check.Args = m.templateCheckArgs(check, svc)
	return check
}