Ejemplo n.º 1
0
func createPingFactory(
	config *Config,
	hostname string,
	port uint16,
	tls *transport.TLSConfig,
	request *http.Request,
	body []byte,
	validator RespCheck,
) func(*net.IPAddr) monitors.TaskRunner {
	fields := common.MapStr{
		"scheme": request.URL.Scheme,
		"port":   port,
		"url":    request.URL.String(),
	}

	timeout := config.Timeout
	isTLS := request.URL.Scheme == "https"
	checkRedirect := makeCheckRedirect(config.MaxRedirects)

	return monitors.MakePingIPFactory(fields, func(ip *net.IPAddr) (common.MapStr, error) {
		addr := net.JoinHostPort(ip.String(), strconv.Itoa(int(port)))
		d := &dialchain.DialerChain{
			Net: dialchain.ConstAddrDialer("tcp_connect_rtt", addr, timeout),
		}
		if isTLS {
			d.AddLayer(dialchain.TLSLayer("tls_handshake_rtt", tls, timeout))
		}

		measures := common.MapStr{}
		dialer, err := d.BuildWithMeasures(measures)
		if err != nil {
			return nil, err
		}

		var httpStart, httpEnd time.Time

		client := &http.Client{
			CheckRedirect: checkRedirect,
			Timeout:       timeout,
			Transport: &SimpleTransport{
				Dialer:       dialer,
				OnStartWrite: func() { httpStart = time.Now() },
				OnStartRead:  func() { httpEnd = time.Now() },
			},
		}

		event, err := execPing(client, request, body, timeout, validator)
		if event == nil {
			event = measures
		} else {
			event.Update(measures)
		}

		if !httpEnd.IsZero() {
			event["http_rtt"] = look.RTT(httpEnd.Sub(httpStart))
		}
		return event, err
	})
}
Ejemplo n.º 2
0
func create(
	info monitors.Info,
	cfg *common.Config,
) ([]monitors.Job, error) {
	config := DefaultConfig
	if err := cfg.Unpack(&config); err != nil {
		return nil, err
	}

	// TODO: check icmp is support by OS + check we've
	// got required credentials (implementation uses RAW socket, requires root +
	// not supported on all OSes)
	// TODO: replace icmp package base reader/sender using raw sockets with
	//       OS specific solution

	var jobs []monitors.Job
	addJob := func(t monitors.Job, err error) error {
		if err != nil {
			return err
		}
		jobs = append(jobs, t)
		return nil
	}

	ipVersion := config.Mode.Network()
	if len(config.Hosts) > 0 && ipVersion == "" {
		err := fmt.Errorf("pinging hosts requires ipv4 or ipv6 mode enabled")
		return nil, err
	}

	var loopErr error
	loopInit.Do(func() {
		debugf("initialize icmp handler")
		loop, loopErr = newICMPLoop()
	})
	if loopErr != nil {
		debugf("Failed to initialize ICMP loop %v", loopErr)
		return nil, loopErr
	}

	typ := config.Name
	network := config.Mode.Network()
	pingFactory := monitors.MakePingIPFactory(nil, createPingIPFactory(&config))

	for _, host := range config.Hosts {
		ip := net.ParseIP(host)
		if ip != nil {
			name := fmt.Sprintf("icmp-ip@%v", ip.String())
			err := addJob(monitors.MakeByIPJob(name, typ, ip, pingFactory))
			if err != nil {
				return nil, err
			}
			continue
		}

		name := fmt.Sprintf("%v-host-%v@%v", config.Name, network, host)
		err := addJob(monitors.MakeByHostJob(name, typ, host, config.Mode, pingFactory))
		if err != nil {
			return nil, err
		}
	}

	return jobs, nil
}