<commit_before>package ipv4

import (
	"network/ipv4/ipv4tps"
	"time"

	"github.com/hsheth2/logs"
	"sync"
)

type IP_Reader struct {
	incomingPackets chan []byte
	irm             *IP_Read_Manager
	protocol        uint8
	ip              *ipv4tps.IPaddress
	fragBuf         map[string](chan []byte)
	fragBufMutex    *sync.RWMutex
}

func NewIP_Reader(irm *IP_Read_Manager, ip *ipv4tps.IPaddress, protocol uint8) (*IP_Reader, error) {
	c, err := irm.Bind(ip, protocol)
	if err != nil {
		return nil, err
	}

	return &IP_Reader{
		incomingPackets: c,
		protocol:        protocol,
		ip:              ip,
		fragBuf:         make(map[string](chan []byte)),
		fragBufMutex:    &sync.RWMutex{},
	}, nil
}

func slicePacket(b []byte) (hrd, payload []byte) {
	hdrLen := int(b[0]&0x0f) * 4
	//fmt.Println("HdrLen: ", hdrLen)
	return b[:hdrLen], b[hdrLen:]
}

func (ipr *IP_Reader) fragmentAssembler(in <-chan []byte, quit <-chan bool, didQuit chan<- bool, done chan bool) {
	payload := make([]byte, 0)
	extraFrags := make(map[uint64]([]byte))
	recvLast := false

	for {
		select {
		case <-quit:
			//Trace.Println("quitting upon quit signal")
			didQuit <- true
			return
		case frag := <-in:
			//Trace.Println("got a fragment packet. len:", len(frag))
			hdr, p := slicePacket(frag)
			//offset := 8 * (uint64(hdr[6]&0x1f)<<8 + uint64(hdr[7]))
			//fmt.Println("RECEIVED FRAG")
			//fmt.Println("Offset:", offset)
			//fmt.Println(len(payload))

			// add to map
			offset := 8 * (uint64(hdr[6]&0x1F)<<8 + uint64(hdr[7]))
			//Trace.Println("Offset:", offset)
			extraFrags[offset] = p

			// check more fragments flag
			if (hdr[6]>>5)&0x01 == 0 {
				recvLast = true
			}

			// add to payload
			//Trace.Println("Begin to add to the payload")
			for {
				if storedFrag, found := extraFrags[uint64(len(payload))]; found {
					//Trace.Println("New Payload Len: ", len(payload))
					delete(extraFrags, uint64(len(payload)))
					payload = append(payload, storedFrag...)
				} else {
					break
				}
			}
			//Trace.Println("Finished add to the payload")

			// deal with the payload
			if recvLast && len(extraFrags) == 0 {
				//Trace.Println("Done")
				// correct the header
				fullPacketHdr := hdr
				totalLen := uint16(fullPacketHdr[0]&0x0F)*4 + uint16(len(payload))
				fullPacketHdr[2] = byte(totalLen >> 8)
				fullPacketHdr[3] = byte(totalLen)
				fullPacketHdr[6] = 0
				fullPacketHdr[7] = 0

				// update the checksum
				check := calculateIPChecksum(fullPacketHdr[:20])
				fullPacketHdr[10] = byte(check >> 8)
				fullPacketHdr[11] = byte(check)

				// send the packet back into processing
				//go func() {
				select {
				case ipr.incomingPackets <- append(fullPacketHdr, payload...):
				default:
					logs.Warn.Println("Dropping defragmented packet, no space in buffer")
				}
				//fmt.Println("FINISHED")
				//}()
				//Trace.Println("Just wrote back in")
				done <- true
				return // from goroutine
			}
			//Trace.Println("Looping")
		}
	}

	// drop the packet upon timeout
	//Trace.Println(errors.New("Fragments took too long, packet dropped"))
	//return
}

func (ipr *IP_Reader) killFragmentAssembler(quit chan<- bool, didQuit <-chan bool, done <-chan bool, bufID string) {
	// sends quit to the assembler if it doesn't send done
	select {
	case <-time.After(FRAGMENT_TIMEOUT):
		//Trace.Println("Force quitting packet assembler")
		quit <- true
		<-didQuit // will block until it has been received
	case <-done:
		//Trace.Println("Recieved done msg.")
	}

	//Trace.Println("Frag Assemble Ended, finished")
	ipr.fragBufMutex.Lock()
	delete(ipr.fragBuf, bufID)
	ipr.fragBufMutex.Unlock()
}

func (ipr *IP_Reader) ReadFrom() (rip, lip *ipv4tps.IPaddress, b, payload []byte, e error) {
	//fmt.Println("STARTING READ")
	b = <-ipr.incomingPackets
	//	logs.Info.Println("Read IP packet")
	//fmt.Println("RAW READ COMPLETED")
	//fmt.Println("Read Length: ", len(b))
	//fmt.Print(".")
	//fmt.Println("Full Read Data: ", b)

	hdr, p := slicePacket(b)

	// extract source IP and protocol
	rip = &ipv4tps.IPaddress{IP: hdr[12:16]}
	lip = &ipv4tps.IPaddress{IP: hdr[16:20]}
	//	proto := uint8(hdr[9])
	//	if !((bytes.Equal(ipr.ip.IP, rip.IP) || bytes.Equal(ipr.ip.IP, ipv4tps.IP_ALL)) && ipr.protocol == proto) {
	//		//Info.Println("Not interested in packet: dropping.")
	//		// TODO should this already have been done in the read manager?
	//		return ipr.ReadFrom()
	//	}

	// verify checksum
	if !verifyIPChecksum(hdr) {
		//Info.Println("Header checksum incorrect, packet dropped")
		return ipr.ReadFrom() // return another packet instead
	}

	packetOffset := uint16(hdr[6]&0x1f)<<8 + uint16(hdr[7])
	//fmt.Println("PACK OFF", packetOffset, "HEADER FLAGS", (hdr[6] >> 5))
	if ((hdr[6]>>5)&0x01 == 0) && (packetOffset == 0) {
		// not a fragment
		return rip, lip, b, p, nil
	} else {
		// is a fragment
		bufID := string([]byte{hdr[12], hdr[13], hdr[14], hdr[15], // the source IP
			hdr[16], hdr[17], hdr[18], hdr[19], // the destination IP
			hdr[9],         // protocol
			hdr[4], hdr[5], // identification
		})
		//Trace.Printf("rcvd a fragment-bufId: %x, len: %d\n", bufID, len(b))

		ipr.fragBufMutex.RLock()
		if _, ok := ipr.fragBuf[bufID]; !ok {
			ipr.fragBufMutex.RUnlock()
			ipr.fragBufMutex.Lock()
			// create the fragment buffer and quit
			//Trace.Printf("creating a new buffer for %x\n", bufID)
			ipr.fragBuf[bufID] = make(chan []byte, FRAGMENT_ASSEMBLER_BUFFER_SIZE)
			ipr.fragBufMutex.Unlock()

			quit := make(chan bool, 1)
			done := make(chan bool, 1)
			didQuit := make(chan bool, 1)

			// create the packet assembler in a goroutine to allow the program to continue
			go ipr.fragmentAssembler(ipr.fragBuf[bufID], quit, didQuit, done)
			go ipr.killFragmentAssembler(quit, didQuit, done, bufID)
		} else {
			ipr.fragBufMutex.RUnlock()
		}

		// send the packet to the assembler
		ipr.fragBufMutex.RLock()
		select {
		case ipr.fragBuf[bufID] <- b:
		default:
			logs.Warn.Println("Dropping fragmented packet, no space in fragment buffer")
		}
		ipr.fragBufMutex.RUnlock()

		// after dealing with the fragment, try reading again
		return ipr.ReadFrom()
	}
}

func (ipr *IP_Reader) Close() error {
	return ipr.irm.Unbind(ipr.ip, ipr.protocol)
}

/* h := &ipv4.Header{
	Version:  ipv4.Version,      // protocol version
	Len:      20,                // header length
	TOS:      0,                 // type-of-service (0 is everything normal)
	TotalLen: len(x) + 20,       // packet total length (octets)
	ID:       0,                 // identification
	Flags:    ipv4.DontFragment, // flags
	FragOff:  0,                 // fragment offset
	TTL:      8,                 // time-to-live (maximum lifespan in seconds)
	Protocol: 17,                // next protocol (17 is UDP)
	Checksum: 0,                 // checksum (apparently autocomputed)
	//Src:    net.IPv4(127, 0, 0, 1), // source address, apparently done automatically
	Dst: net.ParseIP(c.manager.ipAddress), // destination address
	//Options                         // options, extension headers
}
*/
<commit_msg>Changed RWMutex for fragBuf to a normal mutex.<commit_after>package ipv4

import (
	"network/ipv4/ipv4tps"
	"time"

	"github.com/hsheth2/logs"
	"sync"
)

type IP_Reader struct {
	incomingPackets chan []byte
	irm             *IP_Read_Manager
	protocol        uint8
	ip              *ipv4tps.IPaddress
	fragBuf         map[string](chan []byte)
	fragBufMutex    *sync.Mutex
}

func NewIP_Reader(irm *IP_Read_Manager, ip *ipv4tps.IPaddress, protocol uint8) (*IP_Reader, error) {
	c, err := irm.Bind(ip, protocol)
	if err != nil {
		return nil, err
	}

	return &IP_Reader{
		incomingPackets: c,
		protocol:        protocol,
		ip:              ip,
		fragBuf:         make(map[string](chan []byte)),
		fragBufMutex:    &sync.Mutex{},
	}, nil
}

func slicePacket(b []byte) (hrd, payload []byte) {
	hdrLen := int(b[0]&0x0f) * 4
	//fmt.Println("HdrLen: ", hdrLen)
	return b[:hdrLen], b[hdrLen:]
}

func (ipr *IP_Reader) fragmentAssembler(in <-chan []byte, quit <-chan bool, didQuit chan<- bool, done chan bool) {
	payload := make([]byte, 0)
	extraFrags := make(map[uint64]([]byte))
	recvLast := false

	for {
		select {
		case <-quit:
			//Trace.Println("quitting upon quit signal")
			didQuit <- true
			return
		case frag := <-in:
			//Trace.Println("got a fragment packet. len:", len(frag))
			hdr, p := slicePacket(frag)
			//offset := 8 * (uint64(hdr[6]&0x1f)<<8 + uint64(hdr[7]))
			//fmt.Println("RECEIVED FRAG")
			//fmt.Println("Offset:", offset)
			//fmt.Println(len(payload))

			// add to map
			offset := 8 * (uint64(hdr[6]&0x1F)<<8 + uint64(hdr[7]))
			//Trace.Println("Offset:", offset)
			extraFrags[offset] = p

			// check more fragments flag
			if (hdr[6]>>5)&0x01 == 0 {
				recvLast = true
			}

			// add to payload
			//Trace.Println("Begin to add to the payload")
			for {
				if storedFrag, found := extraFrags[uint64(len(payload))]; found {
					//Trace.Println("New Payload Len: ", len(payload))
					delete(extraFrags, uint64(len(payload)))
					payload = append(payload, storedFrag...)
				} else {
					break
				}
			}
			//Trace.Println("Finished add to the payload")

			// deal with the payload
			if recvLast && len(extraFrags) == 0 {
				//Trace.Println("Done")
				// correct the header
				fullPacketHdr := hdr
				totalLen := uint16(fullPacketHdr[0]&0x0F)*4 + uint16(len(payload))
				fullPacketHdr[2] = byte(totalLen >> 8)
				fullPacketHdr[3] = byte(totalLen)
				fullPacketHdr[6] = 0
				fullPacketHdr[7] = 0

				// update the checksum
				check := calculateIPChecksum(fullPacketHdr[:20])
				fullPacketHdr[10] = byte(check >> 8)
				fullPacketHdr[11] = byte(check)

				// send the packet back into processing
				//go func() {
				select {
				case ipr.incomingPackets <- append(fullPacketHdr, payload...):
				default:
					logs.Warn.Println("Dropping defragmented packet, no space in buffer")
				}
				//fmt.Println("FINISHED")
				//}()
				//Trace.Println("Just wrote back in")
				done <- true
				return // from goroutine
			}
			//Trace.Println("Looping")
		}
	}

	// drop the packet upon timeout
	//Trace.Println(errors.New("Fragments took too long, packet dropped"))
	//return
}

func (ipr *IP_Reader) killFragmentAssembler(quit chan<- bool, didQuit <-chan bool, done <-chan bool, bufID string) {
	// sends quit to the assembler if it doesn't send done
	select {
	case <-time.After(FRAGMENT_TIMEOUT):
		//Trace.Println("Force quitting packet assembler")
		quit <- true
		<-didQuit // will block until it has been received
	case <-done:
		//Trace.Println("Recieved done msg.")
	}

	//Trace.Println("Frag Assemble Ended, finished")
	ipr.fragBufMutex.Lock()
	delete(ipr.fragBuf, bufID)
	ipr.fragBufMutex.Unlock()
}

func (ipr *IP_Reader) ReadFrom() (rip, lip *ipv4tps.IPaddress, b, payload []byte, e error) {
	//fmt.Println("STARTING READ")
	b = <-ipr.incomingPackets
	//	logs.Info.Println("Read IP packet")
	//fmt.Println("RAW READ COMPLETED")
	//fmt.Println("Read Length: ", len(b))
	//fmt.Print(".")
	//fmt.Println("Full Read Data: ", b)

	hdr, p := slicePacket(b)

	// extract source IP and protocol
	rip = &ipv4tps.IPaddress{IP: hdr[12:16]}
	lip = &ipv4tps.IPaddress{IP: hdr[16:20]}
	//	proto := uint8(hdr[9])
	//	if !((bytes.Equal(ipr.ip.IP, rip.IP) || bytes.Equal(ipr.ip.IP, ipv4tps.IP_ALL)) && ipr.protocol == proto) {
	//		//Info.Println("Not interested in packet: dropping.")
	//		// TODO should this already have been done in the read manager?
	//		return ipr.ReadFrom()
	//	}

	// verify checksum
	if !verifyIPChecksum(hdr) {
		//Info.Println("Header checksum incorrect, packet dropped")
		return ipr.ReadFrom() // return another packet instead
	}

	packetOffset := uint16(hdr[6]&0x1f)<<8 + uint16(hdr[7])
	//fmt.Println("PACK OFF", packetOffset, "HEADER FLAGS", (hdr[6] >> 5))
	if ((hdr[6]>>5)&0x01 == 0) && (packetOffset == 0) {
		// not a fragment
		return rip, lip, b, p, nil
	} else {
		// is a fragment
		bufID := string([]byte{hdr[12], hdr[13], hdr[14], hdr[15], // the source IP
			hdr[16], hdr[17], hdr[18], hdr[19], // the destination IP
			hdr[9],         // protocol
			hdr[4], hdr[5], // identification
		})
		//Trace.Printf("rcvd a fragment-bufId: %x, len: %d\n", bufID, len(b))

		ipr.fragBufMutex.Lock()
		if _, ok := ipr.fragBuf[bufID]; !ok {
			// create the fragment buffer and quit
			//Trace.Printf("creating a new buffer for %x\n", bufID)
			ipr.fragBuf[bufID] = make(chan []byte, FRAGMENT_ASSEMBLER_BUFFER_SIZE)

			quit := make(chan bool, 1)
			done := make(chan bool, 1)
			didQuit := make(chan bool, 1)

			// create the packet assembler in a goroutine to allow the program to continue
			go ipr.fragmentAssembler(ipr.fragBuf[bufID], quit, didQuit, done)
			go ipr.killFragmentAssembler(quit, didQuit, done, bufID)
		}

		// send the packet to the assembler
		select {
		case ipr.fragBuf[bufID] <- b:
		default:
			logs.Warn.Println("Dropping fragmented packet, no space in fragment buffer")
		}
		ipr.fragBufMutex.Unlock()

		// after dealing with the fragment, try reading again
		return ipr.ReadFrom()
	}
}

func (ipr *IP_Reader) Close() error {
	return ipr.irm.Unbind(ipr.ip, ipr.protocol)
}

/* h := &ipv4.Header{
	Version:  ipv4.Version,      // protocol version
	Len:      20,                // header length
	TOS:      0,                 // type-of-service (0 is everything normal)
	TotalLen: len(x) + 20,       // packet total length (octets)
	ID:       0,                 // identification
	Flags:    ipv4.DontFragment, // flags
	FragOff:  0,                 // fragment offset
	TTL:      8,                 // time-to-live (maximum lifespan in seconds)
	Protocol: 17,                // next protocol (17 is UDP)
	Checksum: 0,                 // checksum (apparently autocomputed)
	//Src:    net.IPv4(127, 0, 0, 1), // source address, apparently done automatically
	Dst: net.ParseIP(c.manager.ipAddress), // destination address
	//Options                         // options, extension headers
}
*/
<|endoftext|>


<commit_before><commit_msg>Implemented KdfCk<commit_after><|endoftext|>


<commit_before>package main

import (
	"bytes"
	"math"
	"strconv"
	"time"

	pb "github.com/dgryski/carbonzipper/carbonzipperpb"
	pickle "github.com/kisielk/og-rek"
)

type metricData struct {
	pb.FetchResponse

	// extra options
	xStep          float64
	valuesPerPoint int
	drawAsInfinite bool
	secondYAxis    bool
	dashed         bool // TODO (ikruglov) smth like lineType would be better
	color          string
	lineWidth      float64
}

func marshalCSV(results []*metricData) []byte {

	var b []byte

	for _, r := range results {

		step := r.GetStepTime()
		t := r.GetStartTime()
		for i, v := range r.Values {
			if !r.IsAbsent[i] {
				b = append(b, '"')
				b = append(b, r.GetName()...)
				b = append(b, '"')
				b = append(b, ',')
				b = append(b, time.Unix(int64(t), 0).Format("2006-01-02 15:04:05")...)
				b = append(b, ',')
				b = strconv.AppendFloat(b, v, 'f', -1, 64)
				b = append(b, '\n')
			}
			t += step
		}
	}
	return b
}

func marshalJSON(results []*metricData) []byte {

	var b []byte
	b = append(b, '[')

	var topComma bool
	for _, r := range results {
		if r == nil {
			continue
		}

		if topComma {
			b = append(b, ',')
		}
		topComma = true

		b = append(b, `{"target":`...)
		b = strconv.AppendQuoteToASCII(b, r.GetName())
		b = append(b, `,"datapoints":[`...)

		var innerComma bool
		t := r.GetStartTime()
		for i, v := range r.Values {
			if innerComma {
				b = append(b, ',')
			}
			innerComma = true

			b = append(b, '[')

			if r.IsAbsent[i] || math.IsInf(v, 0) {
				b = append(b, "null"...)
			} else {
				b = strconv.AppendFloat(b, v, 'f', -1, 64)
			}

			b = append(b, ',')

			b = strconv.AppendInt(b, int64(t), 10)

			b = append(b, ']')

			t += r.GetStepTime()
		}

		b = append(b, `]}`...)
	}

	b = append(b, ']')

	return b
}

func marshalPickle(results []*metricData) []byte {

	var p []map[string]interface{}

	for _, r := range results {
		values := make([]interface{}, len(r.Values))
		for i, v := range r.Values {
			if r.IsAbsent[i] {
				values[i] = pickle.None{}
			} else {
				values[i] = v
			}

		}
		p = append(p, map[string]interface{}{
			"name":   r.GetName(),
			"start":  r.GetStartTime(),
			"end":    r.GetStopTime(),
			"step":   r.GetStepTime(),
			"values": values,
		})
	}

	var buf bytes.Buffer

	penc := pickle.NewEncoder(&buf)
	penc.Encode(p)

	return buf.Bytes()
}

func marshalProtobuf(results []*metricData) []byte {
	response := pb.MultiFetchResponse{}
	for _, metric := range results {
		response.Metrics = append(response.Metrics, &((*metric).FetchResponse))
	}
	b, err := response.Marshal()
	if err != nil {
		logger.Logf("proto.Marshal: %v", err)
	}

	return b
}

func marshalRaw(results []*metricData) []byte {

	var b []byte

	for _, r := range results {

		b = append(b, r.GetName()...)

		b = append(b, ',')
		b = strconv.AppendInt(b, int64(r.GetStartTime()), 10)
		b = append(b, ',')
		b = strconv.AppendInt(b, int64(r.GetStopTime()), 10)
		b = append(b, ',')
		b = strconv.AppendInt(b, int64(r.GetStepTime()), 10)
		b = append(b, '|')

		var comma bool
		for i, v := range r.Values {
			if comma {
				b = append(b, ',')
			}
			comma = true
			if r.IsAbsent[i] {
				b = append(b, "None"...)
			} else {
				b = strconv.AppendFloat(b, v, 'f', -1, 64)
			}
		}

		b = append(b, '\n')
	}
	return b
}
<commit_msg>make format=csv output all data points<commit_after>package main

import (
	"bytes"
	"math"
	"strconv"
	"time"

	pb "github.com/dgryski/carbonzipper/carbonzipperpb"
	pickle "github.com/kisielk/og-rek"
)

type metricData struct {
	pb.FetchResponse

	// extra options
	xStep          float64
	valuesPerPoint int
	drawAsInfinite bool
	secondYAxis    bool
	dashed         bool // TODO (ikruglov) smth like lineType would be better
	color          string
	lineWidth      float64
}

func marshalCSV(results []*metricData) []byte {

	var b []byte

	for _, r := range results {

		step := r.GetStepTime()
		t := r.GetStartTime()
		for i, v := range r.Values {
			b = append(b, '"')
			b = append(b, r.GetName()...)
			b = append(b, '"')
			b = append(b, ',')
			b = append(b, time.Unix(int64(t), 0).Format("2006-01-02 15:04:05")...)
			b = append(b, ',')
			if !r.IsAbsent[i] {
				b = strconv.AppendFloat(b, v, 'f', -1, 64)
			}
			b = append(b, '\n')
			t += step
		}
	}
	return b
}

func marshalJSON(results []*metricData) []byte {

	var b []byte
	b = append(b, '[')

	var topComma bool
	for _, r := range results {
		if r == nil {
			continue
		}

		if topComma {
			b = append(b, ',')
		}
		topComma = true

		b = append(b, `{"target":`...)
		b = strconv.AppendQuoteToASCII(b, r.GetName())
		b = append(b, `,"datapoints":[`...)

		var innerComma bool
		t := r.GetStartTime()
		for i, v := range r.Values {
			if innerComma {
				b = append(b, ',')
			}
			innerComma = true

			b = append(b, '[')

			if r.IsAbsent[i] || math.IsInf(v, 0) {
				b = append(b, "null"...)
			} else {
				b = strconv.AppendFloat(b, v, 'f', -1, 64)
			}

			b = append(b, ',')

			b = strconv.AppendInt(b, int64(t), 10)

			b = append(b, ']')

			t += r.GetStepTime()
		}

		b = append(b, `]}`...)
	}

	b = append(b, ']')

	return b
}

func marshalPickle(results []*metricData) []byte {

	var p []map[string]interface{}

	for _, r := range results {
		values := make([]interface{}, len(r.Values))
		for i, v := range r.Values {
			if r.IsAbsent[i] {
				values[i] = pickle.None{}
			} else {
				values[i] = v
			}

		}
		p = append(p, map[string]interface{}{
			"name":   r.GetName(),
			"start":  r.GetStartTime(),
			"end":    r.GetStopTime(),
			"step":   r.GetStepTime(),
			"values": values,
		})
	}

	var buf bytes.Buffer

	penc := pickle.NewEncoder(&buf)
	penc.Encode(p)

	return buf.Bytes()
}

func marshalProtobuf(results []*metricData) []byte {
	response := pb.MultiFetchResponse{}
	for _, metric := range results {
		response.Metrics = append(response.Metrics, &((*metric).FetchResponse))
	}
	b, err := response.Marshal()
	if err != nil {
		logger.Logf("proto.Marshal: %v", err)
	}

	return b
}

func marshalRaw(results []*metricData) []byte {

	var b []byte

	for _, r := range results {

		b = append(b, r.GetName()...)

		b = append(b, ',')
		b = strconv.AppendInt(b, int64(r.GetStartTime()), 10)
		b = append(b, ',')
		b = strconv.AppendInt(b, int64(r.GetStopTime()), 10)
		b = append(b, ',')
		b = strconv.AppendInt(b, int64(r.GetStepTime()), 10)
		b = append(b, '|')

		var comma bool
		for i, v := range r.Values {
			if comma {
				b = append(b, ',')
			}
			comma = true
			if r.IsAbsent[i] {
				b = append(b, "None"...)
			} else {
				b = strconv.AppendFloat(b, v, 'f', -1, 64)
			}
		}

		b = append(b, '\n')
	}
	return b
}
<|endoftext|>


<commit_before>package nlgids

import (
	"fmt"
	"net/http"

	"github.com/mholt/caddy/caddy/setup"
	"github.com/mholt/caddy/middleware"
)

const nlgids = "nlgids.london"

func Setup(c *setup.Controller) (middleware.Middleware, error) {
	return func(next middleware.Handler) middleware.Handler {
		return &handler{Next: next}
	}, nil
}

type handler struct {
	Next middleware.Handler
}

func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	// only POST are handled by this middleware
	if r.Method != "POST" {
		return h.Next.ServeHTTP(w, r)
	}

	path := middleware.Path(r.URL.Path)
	if !path.Matches("/api") {
		return h.Next.ServeHTTP(w, r)
	}
	//	r.ParseForm() // Required if you don't call r.FormValue()
	//      fmt.Println(r.Form["new_data"])

	switch {
	case path.Matches("/api/auth/test"):
		return WebInvoiceTest(w, r)

	case path.Matches("/api/open/contact/contact"):
		return WebContactTest(w, r)

	case path.Matches("/api/auth/invoice"):
		name := r.PostFormValue("name")
		fmt.Fprintf(w, "auth! %s", name)
	case path.Matches("/api/open/contact"):
		fallthrough
	case path.Matches("/api/open/booking"):
		name := r.PostFormValue("name")
		fmt.Fprintf(w, "Hello, %s!", name)
	}
	return http.StatusOK, nil
}
<commit_msg>correct path<commit_after>package nlgids

import (
	"fmt"
	"net/http"

	"github.com/mholt/caddy/caddy/setup"
	"github.com/mholt/caddy/middleware"
)

const nlgids = "nlgids.london"

func Setup(c *setup.Controller) (middleware.Middleware, error) {
	return func(next middleware.Handler) middleware.Handler {
		return &handler{Next: next}
	}, nil
}

type handler struct {
	Next middleware.Handler
}

func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	// only POST are handled by this middleware
	if r.Method != "POST" {
		return h.Next.ServeHTTP(w, r)
	}

	path := middleware.Path(r.URL.Path)
	if !path.Matches("/api") {
		return h.Next.ServeHTTP(w, r)
	}
	//	r.ParseForm() // Required if you don't call r.FormValue()
	//      fmt.Println(r.Form["new_data"])

	switch {
	case path.Matches("/api/auth/test"):
		return WebInvoiceTest(w, r)

	case path.Matches("/api/open/contact/test"):
		return WebContactTest(w, r)

	case path.Matches("/api/auth/invoice"):
		name := r.PostFormValue("name")
		fmt.Fprintf(w, "auth! %s", name)
	case path.Matches("/api/open/contact"):
		fallthrough
	case path.Matches("/api/open/booking"):
		name := r.PostFormValue("name")
		fmt.Fprintf(w, "Hello, %s!", name)
	}
	return http.StatusOK, nil
}
<|endoftext|>


<commit_before>package buffalo

import (
	"reflect"
	"runtime"
	"strings"
)

// MiddlewareFunc defines the interface for a piece of Buffalo
// Middleware.
/*
	func DoSomething(next Handler) Handler {
		return func(c Context) error {
			// do something before calling the next handler
			err := next(c)
			// do something after call the handler
			return err
		}
	}
*/
type MiddlewareFunc func(Handler) Handler

// Use the specified Middleware for the App.
// When defined on an `*App` the specified middleware will be
// inherited by any `Group` calls that are made on that on
// the App.
func (a *App) Use(mw ...MiddlewareFunc) {
	a.Middleware.Use(mw...)
}

// MiddlewareStack manages the middleware stack for an App/Group.
type MiddlewareStack struct {
	stack []MiddlewareFunc
	skips map[string]bool
}

func (ms *MiddlewareStack) clone() *MiddlewareStack {
	n := newMiddlewareStack()
	for _, s := range ms.stack {
		n.stack = append(n.stack, s)
	}
	for k, v := range ms.skips {
		n.skips[k] = v
	}
	return n
}

// Clear wipes out the current middleware stack for the App/Group,
// any middleware previously defined will be removed leaving an empty
// middleware stack.
func (ms *MiddlewareStack) Clear() {
	ms.stack = []MiddlewareFunc{}
	ms.skips = map[string]bool{}
}

// Use the specified Middleware for the App.
// When defined on an `*App` the specified middleware will be
// inherited by any `Group` calls that are made on that on
// the App.
func (ms *MiddlewareStack) Use(mw ...MiddlewareFunc) {
	ms.stack = append(ms.stack, mw...)
}

// Skip a specified piece of middleware the specified Handlers.
// This is useful for things like wrapping your application in an
// authorization middleware, but skipping it for things the home
// page, the login page, etc...
/*
	a.Middleware.Skip(Authorization, HomeHandler, LoginHandler, RegistrationHandler)
*/
// NOTE: When skipping Resource handlers, you need to first declare your
// resource handler as a type of buffalo.Resource for the Skip function to
// properly recognize and match it.
/*
	// Works:
	var cr Resource
	cr = &carsResource{&buffaloBaseResource{}}
	g = a.Resource("/cars", cr)
	g.Use(SomeMiddleware)
	g.Middleware.Skip(SomeMiddleware, cr.Show)

	// Doesn't Work:
	cr := &carsResource{&buffaloBaseResource{}}
	g = a.Resource("/cars", cr)
	g.Use(SomeMiddleware)
	g.Middleware.Skip(SomeMiddleware, cr.Show)
*/
func (ms *MiddlewareStack) Skip(mw MiddlewareFunc, handlers ...Handler) {
	for _, h := range handlers {
		key := funcKey(mw, h)
		ms.skips[key] = true
	}
}

// Replace a piece of middleware with another piece of middleware. Great for
// testing.
func (ms *MiddlewareStack) Replace(mw1 MiddlewareFunc, mw2 MiddlewareFunc) {
	m1k := funcKey(mw1)
	stack := []MiddlewareFunc{}
	for _, mw := range ms.stack {
		if funcKey(mw) == m1k {
			stack = append(stack, mw2)
		} else {
			stack = append(stack, mw)
		}
	}
	ms.stack = stack
}

func (ms *MiddlewareStack) handler(h Handler) Handler {
	if len(ms.stack) > 0 {
		mh := func(_ Handler) Handler {
			return h
		}

		tstack := []MiddlewareFunc{mh}

		sl := len(ms.stack) - 1
		for i := sl; i >= 0; i-- {
			mw := ms.stack[i]
			key := funcKey(mw, h)
			if !ms.skips[key] {
				tstack = append(tstack, mw)
			}
		}

		for _, mw := range tstack {
			h = mw(h)
		}
		return h
	}
	return h
}

func newMiddlewareStack(mws ...MiddlewareFunc) *MiddlewareStack {
	return &MiddlewareStack{
		stack: mws,
		skips: map[string]bool{},
	}
}

func funcKey(funcs ...interface{}) string {
	names := []string{}
	for _, f := range funcs {
		rv := reflect.ValueOf(f)
		ptr := rv.Pointer()
		if n, ok := keyMap[ptr]; ok {
			names = append(names, n)
			continue
		}
		fnc := runtime.FuncForPC(ptr)
		n := fnc.Name()
		keyMap[ptr] = n
		names = append(names, n)
	}
	return strings.Join(names, "/")
}

func setFuncKey(f interface{}, name string) {
	rv := reflect.ValueOf(f)
	ptr := rv.Pointer()
	keyMap[ptr] = name
}

var keyMap = map[uintptr]string{}
<commit_msg>fixed the naming of functions to be more uniformed<commit_after>package buffalo

import (
	"reflect"
	"runtime"
	"strings"
)

// MiddlewareFunc defines the interface for a piece of Buffalo
// Middleware.
/*
	func DoSomething(next Handler) Handler {
		return func(c Context) error {
			// do something before calling the next handler
			err := next(c)
			// do something after call the handler
			return err
		}
	}
*/
type MiddlewareFunc func(Handler) Handler

// Use the specified Middleware for the App.
// When defined on an `*App` the specified middleware will be
// inherited by any `Group` calls that are made on that on
// the App.
func (a *App) Use(mw ...MiddlewareFunc) {
	a.Middleware.Use(mw...)
}

// MiddlewareStack manages the middleware stack for an App/Group.
type MiddlewareStack struct {
	stack []MiddlewareFunc
	skips map[string]bool
}

func (ms *MiddlewareStack) clone() *MiddlewareStack {
	n := newMiddlewareStack()
	for _, s := range ms.stack {
		n.stack = append(n.stack, s)
	}
	for k, v := range ms.skips {
		n.skips[k] = v
	}
	return n
}

// Clear wipes out the current middleware stack for the App/Group,
// any middleware previously defined will be removed leaving an empty
// middleware stack.
func (ms *MiddlewareStack) Clear() {
	ms.stack = []MiddlewareFunc{}
	ms.skips = map[string]bool{}
}

// Use the specified Middleware for the App.
// When defined on an `*App` the specified middleware will be
// inherited by any `Group` calls that are made on that on
// the App.
func (ms *MiddlewareStack) Use(mw ...MiddlewareFunc) {
	ms.stack = append(ms.stack, mw...)
}

// Skip a specified piece of middleware the specified Handlers.
// This is useful for things like wrapping your application in an
// authorization middleware, but skipping it for things the home
// page, the login page, etc...
/*
	a.Middleware.Skip(Authorization, HomeHandler, LoginHandler, RegistrationHandler)
*/
// NOTE: When skipping Resource handlers, you need to first declare your
// resource handler as a type of buffalo.Resource for the Skip function to
// properly recognize and match it.
/*
	// Works:
	var cr Resource
	cr = &carsResource{&buffaloBaseResource{}}
	g = a.Resource("/cars", cr)
	g.Use(SomeMiddleware)
	g.Middleware.Skip(SomeMiddleware, cr.Show)

	// Doesn't Work:
	cr := &carsResource{&buffaloBaseResource{}}
	g = a.Resource("/cars", cr)
	g.Use(SomeMiddleware)
	g.Middleware.Skip(SomeMiddleware, cr.Show)
*/
func (ms *MiddlewareStack) Skip(mw MiddlewareFunc, handlers ...Handler) {
	for _, h := range handlers {
		key := funcKey(mw, h)
		ms.skips[key] = true
	}
}

// Replace a piece of middleware with another piece of middleware. Great for
// testing.
func (ms *MiddlewareStack) Replace(mw1 MiddlewareFunc, mw2 MiddlewareFunc) {
	m1k := funcKey(mw1)
	stack := []MiddlewareFunc{}
	for _, mw := range ms.stack {
		if funcKey(mw) == m1k {
			stack = append(stack, mw2)
		} else {
			stack = append(stack, mw)
		}
	}
	ms.stack = stack
}

func (ms *MiddlewareStack) handler(h Handler) Handler {
	if len(ms.stack) > 0 {
		mh := func(_ Handler) Handler {
			return h
		}

		tstack := []MiddlewareFunc{mh}

		sl := len(ms.stack) - 1
		for i := sl; i >= 0; i-- {
			mw := ms.stack[i]
			key := funcKey(mw, h)
			if !ms.skips[key] {
				tstack = append(tstack, mw)
			}
		}

		for _, mw := range tstack {
			h = mw(h)
		}
		return h
	}
	return h
}

func newMiddlewareStack(mws ...MiddlewareFunc) *MiddlewareStack {
	return &MiddlewareStack{
		stack: mws,
		skips: map[string]bool{},
	}
}

func funcKey(funcs ...interface{}) string {
	names := []string{}
	for _, f := range funcs {
		rv := reflect.ValueOf(f)
		ptr := rv.Pointer()
		if n, ok := keyMap[ptr]; ok {
			names = append(names, n)
			continue
		}
		fnc := runtime.FuncForPC(ptr)
		n := fnc.Name()

		n = strings.Replace(n, "-fm", "", 1)
		n = strings.Replace(n, "(", "", 1)
		n = strings.Replace(n, ")", "", 1)
		keyMap[ptr] = n
		names = append(names, n)
	}
	return strings.Join(names, "/")
}

func setFuncKey(f interface{}, name string) {
	rv := reflect.ValueOf(f)
	ptr := rv.Pointer()
	keyMap[ptr] = name
}

var keyMap = map[uintptr]string{}
<|endoftext|>


<commit_before>// Copyright 2017 Axel Etcheverry. All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package main

import (
	"context"
	"errors"
	"net/http"

	"fmt"

	"crypto/subtle"
	"path/filepath"
	"strings"
	"time"

	"github.com/euskadi31/image-service/httputil"
	"github.com/h2non/bimg"
	"github.com/rs/xlog"
	"github.com/whitedevops/colors"
)

var (
	errContextIsNull     = errors.New("The context is null")
	errNotFountInContext = errors.New("The entry is not found in context")
)

type key int

const (
	paramsKey key = iota
)

// NewParamsContext func
func NewParamsContext(ctx context.Context, params *ImageOptions) context.Context {
	return context.WithValue(ctx, paramsKey, params)
}

// ParamsFromContext gets the params out of the context.
func ParamsFromContext(ctx context.Context) (*ImageOptions, error) {
	if ctx == nil {
		return nil, errContextIsNull
	}

	params, ok := ctx.Value(paramsKey).(*ImageOptions)
	if !ok {
		return nil, errNotFountInContext
	}

	return params, nil
}

// NewLoggerHandler log request
func NewLoggerHandler() func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			start := time.Now()

			next.ServeHTTP(w, r)

			xlog.Infof("  %s   %s   %s  %s", fmtDuration(start), fmtStatus(w), fmtMethod(r), fmtPath(r.URL.Path))
		})
	}
}

// NewImageExtensionFilterHandler filtered url for accept image file only
func NewImageExtensionFilterHandler(config *Configuration) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			ext := strings.ToLower(filepath.Ext(r.URL.Path))
			ext = ext[1:]

			if config.Image.Support.IsExtSupported(ext) == false {
				msg := fmt.Sprintf("File %s is not supported", r.URL.Path)

				xlog.Debug(msg)
				http.Error(w, msg, http.StatusNotFound)

				return
			}

			next.ServeHTTP(w, r)
		})
	}
}

// NewParamsHandler parse query string
func NewParamsHandler() func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			params := ParseParams(r.URL.Query())

			r = r.WithContext(NewParamsContext(r.Context(), params))

			next.ServeHTTP(w, r)
		})
	}
}

// NewAuthHandler authenticate by key
func NewAuthHandler(config *AuthConfiguration) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			s := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
			if len(s) != 2 {
				http.Error(w, "Not authorized", 401)

				return
			}

			if s[0] != "Bearer" {
				http.Error(w, "Not authorized", 401)

				return
			}

			if subtle.ConstantTimeCompare([]byte(s[1]), []byte(config.Secret)) == 0 {
				http.Error(w, "Not authorized", 401)

				return
			}

			next.ServeHTTP(w, r)
		})
	}
}

// NewClientHintsHandler parse query string
// see: http://httpwg.org/http-extensions/client-hints.html
func NewClientHintsHandler() func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			params, err := ParamsFromContext(r.Context())
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)

				return
			}

			if params.Format != bimg.UNKNOWN {
				next.ServeHTTP(w, r)

				return
			}

			if params.Format == bimg.UNKNOWN {
				mime := httputil.NegotiateContentType(r, []string{
					"image/jpg",
					"image/webp",
					"image/jpeg",
					"image/tiff",
					"image/png",
				}, "image/jpg")

				xlog.Infof("Accept: %s", mime)

				format := ExtractImageTypeFromMime(mime)

				xlog.Infof("Format: %s", format)

				if !bimg.IsTypeNameSupported(format) {
					http.Error(w, fmt.Sprintf("Format not supported"), http.StatusUnsupportedMediaType)

					return
				}

				params.Format = ImageType(format)
				w.Header().Set("Content-Type", mime)
				w.Header().Add("Vary", "Accept")
			}

			if dpr := r.Header.Get("DPR"); dpr != "" {
				params.DPR = parseFloat(dpr)

				w.Header().Set("Content-DPR", fmt.Sprintf("%f", params.DPR))
				w.Header().Add("Vary", "DPR")
			}

			if width := r.Header.Get("Width"); width != "" {
				params.Width = parseInt(width)
				w.Header().Add("Vary", "Width")
			}

			if saveData := r.Header.Get("Save-Data"); saveData == "on" {
				params.Quality = 65
				w.Header().Add("Vary", "Save-Data")
			}

			r = r.WithContext(NewParamsContext(r.Context(), params))

			next.ServeHTTP(w, r)
		})
	}
}

func fmtDuration(start time.Time) string {
	return fmt.Sprintf("%s%s%13s%s", colors.ResetAll, colors.Dim, time.Since(start), colors.ResetAll)
}

func fmtStatus(w http.ResponseWriter) string {
	code := httputil.ResponseStatus(w)

	color := colors.White

	switch {
	case code >= 200 && code <= 299:
		color += colors.BackgroundGreen
	case code >= 300 && code <= 399:
		color += colors.BackgroundCyan
	case code >= 400 && code <= 499:
		color += colors.BackgroundYellow
	default:
		color += colors.BackgroundRed
	}

	return fmt.Sprintf("%s%s %3d %s", colors.ResetAll, color, code, colors.ResetAll)
}

func fmtMethod(r *http.Request) string {
	var color string

	switch r.Method {
	case "GET":
		color += colors.Green
	case "POST":
		color += colors.Cyan
	case "PUT", "PATCH":
		color += colors.Blue
	case "DELETE":
		color += colors.Red
	}

	return fmt.Sprintf("%s%s%s%s", colors.ResetAll, color, r.Method, colors.ResetAll)
}

func fmtPath(path string) string {
	return fmt.Sprintf("%s%s%s%s", colors.ResetAll, colors.Dim, path, colors.ResetAll)
}
<commit_msg>feat(ClientHintsHandler): Added debug mode<commit_after>// Copyright 2017 Axel Etcheverry. All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package main

import (
	"context"
	"errors"
	"net/http"

	"fmt"

	"crypto/subtle"
	"path/filepath"
	"strings"
	"time"

	"github.com/euskadi31/image-service/httputil"
	"github.com/h2non/bimg"
	"github.com/rs/xlog"
	"github.com/whitedevops/colors"
)

var (
	errContextIsNull     = errors.New("The context is null")
	errNotFountInContext = errors.New("The entry is not found in context")
)

type key int

const (
	paramsKey key = iota
)

// NewParamsContext func
func NewParamsContext(ctx context.Context, params *ImageOptions) context.Context {
	return context.WithValue(ctx, paramsKey, params)
}

// ParamsFromContext gets the params out of the context.
func ParamsFromContext(ctx context.Context) (*ImageOptions, error) {
	if ctx == nil {
		return nil, errContextIsNull
	}

	params, ok := ctx.Value(paramsKey).(*ImageOptions)
	if !ok {
		return nil, errNotFountInContext
	}

	return params, nil
}

// NewLoggerHandler log request
func NewLoggerHandler() func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			start := time.Now()

			next.ServeHTTP(w, r)

			xlog.Infof("  %s   %s   %s  %s", fmtDuration(start), fmtStatus(w), fmtMethod(r), fmtPath(r.URL.Path))
		})
	}
}

// NewImageExtensionFilterHandler filtered url for accept image file only
func NewImageExtensionFilterHandler(config *Configuration) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			ext := strings.ToLower(filepath.Ext(r.URL.Path))
			ext = ext[1:]

			if config.Image.Support.IsExtSupported(ext) == false {
				msg := fmt.Sprintf("File %s is not supported", r.URL.Path)

				xlog.Debug(msg)
				http.Error(w, msg, http.StatusNotFound)

				return
			}

			next.ServeHTTP(w, r)
		})
	}
}

// NewParamsHandler parse query string
func NewParamsHandler() func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			params := ParseParams(r.URL.Query())

			r = r.WithContext(NewParamsContext(r.Context(), params))

			next.ServeHTTP(w, r)
		})
	}
}

// NewAuthHandler authenticate by key
func NewAuthHandler(config *AuthConfiguration) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			s := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
			if len(s) != 2 {
				http.Error(w, "Not authorized", 401)

				return
			}

			if s[0] != "Bearer" {
				http.Error(w, "Not authorized", 401)

				return
			}

			if subtle.ConstantTimeCompare([]byte(s[1]), []byte(config.Secret)) == 0 {
				http.Error(w, "Not authorized", 401)

				return
			}

			next.ServeHTTP(w, r)
		})
	}
}

// NewClientHintsHandler parse query string
// see: http://httpwg.org/http-extensions/client-hints.html
func NewClientHintsHandler() func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			params, err := ParamsFromContext(r.Context())
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)

				return
			}

			xlog.Infof("params: %#v", params)

			if params.Format != bimg.UNKNOWN {
				xlog.Infof("Format (query): %s", params.Format)

				next.ServeHTTP(w, r)

				return
			}

			if params.Format == bimg.UNKNOWN {
				mime := httputil.NegotiateContentType(r, []string{
					"image/jpg",
					"image/webp",
					"image/jpeg",
					"image/tiff",
					"image/png",
				}, "image/jpg")

				xlog.Infof("Accept: %s", mime)

				format := ExtractImageTypeFromMime(mime)

				xlog.Infof("Format: %s", format)

				if !bimg.IsTypeNameSupported(format) {
					http.Error(w, fmt.Sprintf("Format not supported"), http.StatusUnsupportedMediaType)

					return
				}

				params.Format = ImageType(format)
				w.Header().Set("Content-Type", mime)
				w.Header().Add("Vary", "Accept")
			}

			if dpr := r.Header.Get("DPR"); dpr != "" {
				params.DPR = parseFloat(dpr)

				w.Header().Set("Content-DPR", fmt.Sprintf("%f", params.DPR))
				w.Header().Add("Vary", "DPR")
			}

			if width := r.Header.Get("Width"); width != "" {
				params.Width = parseInt(width)
				w.Header().Add("Vary", "Width")
			}

			if saveData := r.Header.Get("Save-Data"); saveData == "on" {
				params.Quality = 65
				w.Header().Add("Vary", "Save-Data")
			}

			r = r.WithContext(NewParamsContext(r.Context(), params))

			next.ServeHTTP(w, r)
		})
	}
}

func fmtDuration(start time.Time) string {
	return fmt.Sprintf("%s%s%13s%s", colors.ResetAll, colors.Dim, time.Since(start), colors.ResetAll)
}

func fmtStatus(w http.ResponseWriter) string {
	code := httputil.ResponseStatus(w)

	color := colors.White

	switch {
	case code >= 200 && code <= 299:
		color += colors.BackgroundGreen
	case code >= 300 && code <= 399:
		color += colors.BackgroundCyan
	case code >= 400 && code <= 499:
		color += colors.BackgroundYellow
	default:
		color += colors.BackgroundRed
	}

	return fmt.Sprintf("%s%s %3d %s", colors.ResetAll, color, code, colors.ResetAll)
}

func fmtMethod(r *http.Request) string {
	var color string

	switch r.Method {
	case "GET":
		color += colors.Green
	case "POST":
		color += colors.Cyan
	case "PUT", "PATCH":
		color += colors.Blue
	case "DELETE":
		color += colors.Red
	}

	return fmt.Sprintf("%s%s%s%s", colors.ResetAll, color, r.Method, colors.ResetAll)
}

func fmtPath(path string) string {
	return fmt.Sprintf("%s%s%s%s", colors.ResetAll, colors.Dim, path, colors.ResetAll)
}
<|endoftext|>


<commit_before>package promclient

import (
	"reflect"
	"strconv"
	"testing"

	model "github.com/prometheus/common/model"
)

func TestMergeLabelValues(t *testing.T) {
	tests := []struct {
		a      []model.LabelValue
		b      []model.LabelValue
		merged []model.LabelValue
	}{
		{
			a:      []model.LabelValue{"a"},
			b:      []model.LabelValue{"b"},
			merged: []model.LabelValue{"a", "b"},
		},
	}

	for i, test := range tests {
		t.Run(strconv.Itoa(i), func(t *testing.T) {
			merged := MergeLabelValues(test.a, test.b)

			if !reflect.DeepEqual(merged, test.merged) {
				t.Fatalf("doesn't match\nexpected=%v\nactual=%v", test.merged, merged)
			}
		})
	}
}

func TestMergeLabelSets(t *testing.T) {
	tests := []struct {
		a      []model.LabelSet
		b      []model.LabelSet
		merged []model.LabelSet
	}{
		// Basic merge
		{
			a: []model.LabelSet{
				model.LabelSet{model.MetricNameLabel: model.LabelValue("hosta")},
			},
			b: []model.LabelSet{
				model.LabelSet{model.MetricNameLabel: model.LabelValue("hostb")},
			},
			merged: []model.LabelSet{
				model.LabelSet{model.MetricNameLabel: model.LabelValue("hosta")},
				model.LabelSet{model.MetricNameLabel: model.LabelValue("hostb")},
			},
		},
		// No merge
		{
			a: []model.LabelSet{
				model.LabelSet{model.MetricNameLabel: model.LabelValue("hosta")},
			},
			b: []model.LabelSet{},
			merged: []model.LabelSet{
				model.LabelSet{model.MetricNameLabel: model.LabelValue("hosta")},
			},
		},
		// Dupe
		{
			a: []model.LabelSet{
				model.LabelSet{model.MetricNameLabel: model.LabelValue("hosta")},
			},
			b: []model.LabelSet{
				model.LabelSet{model.MetricNameLabel: model.LabelValue("hosta")},
			},
			merged: []model.LabelSet{
				model.LabelSet{model.MetricNameLabel: model.LabelValue("hosta")},
			},
		},
	}

	for i, test := range tests {
		t.Run(strconv.Itoa(i), func(t *testing.T) {
			merged := MergeLabelSets(test.a, test.b)

			if !reflect.DeepEqual(merged, test.merged) {
				t.Fatalf("doesn't match\nexpected=%v\nactual=%v", test.merged, merged)
			}
		})
	}
}
<commit_msg>gofmt -s<commit_after>package promclient

import (
	"reflect"
	"strconv"
	"testing"

	model "github.com/prometheus/common/model"
)

func TestMergeLabelValues(t *testing.T) {
	tests := []struct {
		a      []model.LabelValue
		b      []model.LabelValue
		merged []model.LabelValue
	}{
		{
			a:      []model.LabelValue{"a"},
			b:      []model.LabelValue{"b"},
			merged: []model.LabelValue{"a", "b"},
		},
	}

	for i, test := range tests {
		t.Run(strconv.Itoa(i), func(t *testing.T) {
			merged := MergeLabelValues(test.a, test.b)

			if !reflect.DeepEqual(merged, test.merged) {
				t.Fatalf("doesn't match\nexpected=%v\nactual=%v", test.merged, merged)
			}
		})
	}
}

func TestMergeLabelSets(t *testing.T) {
	tests := []struct {
		a      []model.LabelSet
		b      []model.LabelSet
		merged []model.LabelSet
	}{
		// Basic merge
		{
			a: []model.LabelSet{
				{model.MetricNameLabel: model.LabelValue("hosta")},
			},
			b: []model.LabelSet{
				{model.MetricNameLabel: model.LabelValue("hostb")},
			},
			merged: []model.LabelSet{
				{model.MetricNameLabel: model.LabelValue("hosta")},
				{model.MetricNameLabel: model.LabelValue("hostb")},
			},
		},
		// No merge
		{
			a: []model.LabelSet{
				{model.MetricNameLabel: model.LabelValue("hosta")},
			},
			b: []model.LabelSet{},
			merged: []model.LabelSet{
				{model.MetricNameLabel: model.LabelValue("hosta")},
			},
		},
		// Dupe
		{
			a: []model.LabelSet{
				{model.MetricNameLabel: model.LabelValue("hosta")},
			},
			b: []model.LabelSet{
				{model.MetricNameLabel: model.LabelValue("hosta")},
			},
			merged: []model.LabelSet{
				{model.MetricNameLabel: model.LabelValue("hosta")},
			},
		},
	}

	for i, test := range tests {
		t.Run(strconv.Itoa(i), func(t *testing.T) {
			merged := MergeLabelSets(test.a, test.b)

			if !reflect.DeepEqual(merged, test.merged) {
				t.Fatalf("doesn't match\nexpected=%v\nactual=%v", test.merged, merged)
			}
		})
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"flag"
	"strconv"
	"time"

	"github.com/golang/glog"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	v3 "google.golang.org/api/monitoring/v3"

	"k8s.io/contrib/prometheus-to-sd/config"
	"k8s.io/contrib/prometheus-to-sd/flags"
	"k8s.io/contrib/prometheus-to-sd/translator"
)

var (
	host       = flag.String("target-host", "localhost", "The monitored component's hostname. DEPRECATED: Use --source instead.")
	port       = flag.Uint("target-port", 80, "The monitored component's port. DEPRECATED: Use --source instead.")
	component  = flag.String("component", "", "The monitored target's name. DEPRECATED: Use --source instead.")
	resolution = flag.Duration("metrics-resolution", 60*time.Second,
		"The resolution at which prometheus-to-sd will scrape the component for metrics.")
	metricsPrefix = flag.String("stackdriver-prefix", "container.googleapis.com/master",
		"Prefix that is appended to every metric.")
	whitelisted = flag.String("whitelisted-metrics", "",
		"Comma-separated list of whitelisted metrics. If empty all metrics will be exported. DEPRECATED: Use --source instead.")
	autoWhitelistMetrics = flag.Bool("auto-whitelist-metrics", false,
		"If component has no whitelisted metrics, prometheus-to-sd will fetch them from Stackdriver.")
	autoWhitelistMetricsResolution = flag.Duration("auto-whitelist-metrics-resolution", 10*time.Minute,
		"The resolution at which prometheus-to-sd will scrape metric descriptors from Stackdriver.")
	apioverride = flag.String("api-override", "",
		"The stackdriver API endpoint to override the default one used (which is prod).")
	source = flags.Uris{}
)

func main() {
	flag.Set("logtostderr", "true")
	flag.Var(&source, "source", "source(s) to watch in [component-name]:http://host:port?whitelisted=a,b,c format")

	defer glog.Flush()
	flag.Parse()

	var sourceConfigs []config.SourceConfig

	for _, c := range source {
		if sourceConfig, err := config.ParseSourceConfig(c); err != nil {
			glog.Fatalf("Error while parsing source config flag %v: %v", c, err)
		} else {
			sourceConfigs = append(sourceConfigs, *sourceConfig)
		}
	}

	if len(source) == 0 && *component != "" {
		glog.Warningf("--component, --host, --port and --whitelisted flags are deprecated. Please use --source instead.")
		portStr := strconv.FormatUint(uint64(*port), 10)

		if sourceConfig, err := config.NewSourceConfig(*component, *host, portStr, *whitelisted); err != nil {
			glog.Fatalf("Error while parsing --component flag: %v", err)
		} else {
			glog.Infof("Created a new source instance from --component flag: %+v", sourceConfig)
			sourceConfigs = append(sourceConfigs, *sourceConfig)
		}
	}

	gceConf, err := config.GetGceConfig(*metricsPrefix)
	if err != nil {
		glog.Fatalf("Failed to get GCE config: %v", err)
	}
	glog.Infof("GCE config: %+v", gceConf)

	client := oauth2.NewClient(oauth2.NoContext, google.ComputeTokenSource(""))
	stackdriverService, err := v3.New(client)
	if *apioverride != "" {
		stackdriverService.BasePath = *apioverride
	}
	if err != nil {
		glog.Fatalf("Failed to create Stackdriver client: %v", err)
	}
	glog.V(4).Infof("Successfully created Stackdriver client")

	if len(sourceConfigs) == 0 {
		glog.Fatalf("No sources defined. Please specify at least one --source flag.")
	}

	for _, sourceConfig := range sourceConfigs {
		glog.V(4).Infof("Starting goroutine for %+v", sourceConfig)

		// Pass sourceConfig as a parameter to avoid using the last sourceConfig by all goroutines.
		go func(sourceConfig config.SourceConfig) {
			glog.Infof("Running prometheus-to-sd, monitored target is %s %v:%v", sourceConfig.Component, sourceConfig.Host, sourceConfig.Port)

			signal := time.After(0)
			useWhitelistedMetricsAutodiscovery := *autoWhitelistMetrics && len(sourceConfig.Whitelisted) == 0

			for range time.Tick(*resolution) {
				glog.V(4).Infof("Scraping metrics of component %v", sourceConfig.Component)

				if useWhitelistedMetricsAutodiscovery {
					select {
					case <-signal:
						glog.V(4).Infof("Updating metrics cache for component %v", sourceConfig.Component)
						if metricDescriptors, err := translator.GetMetricDescriptors(stackdriverService, gceConf, sourceConfig.Component); err == nil {
							sourceConfig.Whitelisted = nil
							for metricName := range metricDescriptors {
								sourceConfig.Whitelisted = append(sourceConfig.Whitelisted, metricName)
							}
						} else {
							glog.Warningf("Error while fetching metric descriptors for %v: %v", sourceConfig.Component, err)
						}

						signal = time.After(*autoWhitelistMetricsResolution)
					default:
					}

					if len(sourceConfig.Whitelisted) == 0 {
						glog.V(4).Infof("Skipping %v component as there are no metric to expose.", sourceConfig.Component)
						continue
					}
				}

				metrics, err := translator.GetPrometheusMetrics(sourceConfig.Host, sourceConfig.Port)
				if err != nil {
					glog.Warningf("Error while getting Prometheus metrics %v", err)
					continue
				}

				ts := translator.TranslatePrometheusToStackdriver(gceConf, sourceConfig.Component, metrics, sourceConfig.Whitelisted)
				translator.SendToStackdriver(stackdriverService, gceConf, ts)
			}
		}(sourceConfig)
	}

	// As worker goroutines work forever, block main thread as well.
	<-make(chan int)
}
<commit_msg>Small refactoring, improve code readability.<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"flag"
	"strconv"
	"time"

	"github.com/golang/glog"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	v3 "google.golang.org/api/monitoring/v3"

	"k8s.io/contrib/prometheus-to-sd/config"
	"k8s.io/contrib/prometheus-to-sd/flags"
	"k8s.io/contrib/prometheus-to-sd/translator"
)

var (
	host       = flag.String("target-host", "localhost", "The monitored component's hostname. DEPRECATED: Use --source instead.")
	port       = flag.Uint("target-port", 80, "The monitored component's port. DEPRECATED: Use --source instead.")
	component  = flag.String("component", "", "The monitored target's name. DEPRECATED: Use --source instead.")
	resolution = flag.Duration("metrics-resolution", 60*time.Second,
		"The resolution at which prometheus-to-sd will scrape the component for metrics.")
	metricsPrefix = flag.String("stackdriver-prefix", "container.googleapis.com/master",
		"Prefix that is appended to every metric.")
	whitelisted = flag.String("whitelisted-metrics", "",
		"Comma-separated list of whitelisted metrics. If empty all metrics will be exported. DEPRECATED: Use --source instead.")
	autoWhitelistMetrics = flag.Bool("auto-whitelist-metrics", false,
		"If component has no whitelisted metrics, prometheus-to-sd will fetch them from Stackdriver.")
	metricDescriptorsResolution = flag.Duration("metric-descriptors-resolution", 10*time.Minute,
		"The resolution at which prometheus-to-sd will scrape metric descriptors from Stackdriver.")
	apioverride = flag.String("api-override", "",
		"The stackdriver API endpoint to override the default one used (which is prod).")
	source = flags.Uris{}
)

func main() {
	flag.Set("logtostderr", "true")
	flag.Var(&source, "source", "source(s) to watch in [component-name]:http://host:port?whitelisted=a,b,c format")

	defer glog.Flush()
	flag.Parse()

	sourceConfigs := extractSourceConfigsFromFlags()

	gceConf, err := config.GetGceConfig(*metricsPrefix)
	if err != nil {
		glog.Fatalf("Failed to get GCE config: %v", err)
	}
	glog.Infof("GCE config: %+v", gceConf)

	client := oauth2.NewClient(oauth2.NoContext, google.ComputeTokenSource(""))
	stackdriverService, err := v3.New(client)
	if *apioverride != "" {
		stackdriverService.BasePath = *apioverride
	}
	if err != nil {
		glog.Fatalf("Failed to create Stackdriver client: %v", err)
	}
	glog.V(4).Infof("Successfully created Stackdriver client")

	if len(sourceConfigs) == 0 {
		glog.Fatalf("No sources defined. Please specify at least one --source flag.")
	}

	for _, sourceConfig := range sourceConfigs {
		glog.V(4).Infof("Starting goroutine for %+v", sourceConfig)

		// Pass sourceConfig as a parameter to avoid using the last sourceConfig by all goroutines.
		go readAndPushDataToStackdriver(stackdriverService, gceConf, sourceConfig)
	}

	// As worker goroutines work forever, block main thread as well.
	<-make(chan int)
}

func extractSourceConfigsFromFlags() []config.SourceConfig {
	var sourceConfigs []config.SourceConfig
	for _, c := range source {
		if sourceConfig, err := config.ParseSourceConfig(c); err != nil {
			glog.Fatalf("Error while parsing source config flag %v: %v", c, err)
		} else {
			sourceConfigs = append(sourceConfigs, *sourceConfig)
		}
	}

	if len(source) == 0 && *component != "" {
		glog.Warningf("--component, --host, --port and --whitelisted flags are deprecated. Please use --source instead.")
		portStr := strconv.FormatUint(uint64(*port), 10)

		if sourceConfig, err := config.NewSourceConfig(*component, *host, portStr, *whitelisted); err != nil {
			glog.Fatalf("Error while parsing --component flag: %v", err)
		} else {
			glog.Infof("Created a new source instance from --component flag: %+v", sourceConfig)
			sourceConfigs = append(sourceConfigs, *sourceConfig)
		}
	}
	return sourceConfigs
}

func readAndPushDataToStackdriver(stackdriverService *v3.Service, gceConf *config.GceConfig, sourceConfig config.SourceConfig) {
	glog.Infof("Running prometheus-to-sd, monitored target is %s %v:%v", sourceConfig.Component, sourceConfig.Host, sourceConfig.Port)

	signal := time.After(0)
	useWhitelistedMetricsAutodiscovery := *autoWhitelistMetrics && len(sourceConfig.Whitelisted) == 0

	for range time.Tick(*resolution) {
		glog.V(4).Infof("Scraping metrics of component %v", sourceConfig.Component)

		select {
		case <-signal:
			glog.V(4).Infof("Updating metrics cache for component %v", sourceConfig.Component)
			metricDescriptors, err := translator.GetMetricDescriptors(stackdriverService, gceConf, sourceConfig.Component);
			if err != nil {
				glog.Warningf("Error while fetching metric descriptors for %v: %v", sourceConfig.Component, err)
			}
			if useWhitelistedMetricsAutodiscovery {
				updateWhitelistedMetrics(&sourceConfig, metricDescriptors)
			}
			signal = time.After(*metricDescriptorsResolution)
		default:
		}
		if useWhitelistedMetricsAutodiscovery && len(sourceConfig.Whitelisted) == 0 {
			glog.V(4).Infof("Skipping %v component as there are no metric to expose.", sourceConfig.Component)
			continue
		}

		metrics, err := translator.GetPrometheusMetrics(sourceConfig.Host, sourceConfig.Port)
		if err != nil {
			glog.Warningf("Error while getting Prometheus metrics %v", err)
			continue
		}

		ts := translator.TranslatePrometheusToStackdriver(gceConf, sourceConfig.Component, metrics, sourceConfig.Whitelisted)
		translator.SendToStackdriver(stackdriverService, gceConf, ts)
	}
}

func updateWhitelistedMetrics(sourceConfig *config.SourceConfig, metricDescriptors map[string]*v3.MetricDescriptor) {
	sourceConfig.Whitelisted = nil
	for metricName := range metricDescriptors {
		sourceConfig.Whitelisted = append(sourceConfig.Whitelisted, metricName)
	}
}<|endoftext|>


<commit_before>/*
Copyright 2017 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"flag"
	"time"

	"github.com/golang/glog"
	"golang.org/x/net/context"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	v3 "google.golang.org/api/monitoring/v3"

	"github.com/GoogleCloudPlatform/k8s-stackdriver/prometheus-to-sd/config"
	"github.com/GoogleCloudPlatform/k8s-stackdriver/prometheus-to-sd/flags"
	"github.com/GoogleCloudPlatform/k8s-stackdriver/prometheus-to-sd/translator"
	"strings"
)

var (
	host       = flag.String("target-host", "localhost", "The monitored component's hostname. DEPRECATED: Use --source instead.")
	port       = flag.Uint("target-port", 80, "The monitored component's port. DEPRECATED: Use --source instead.")
	component  = flag.String("component", "", "The monitored target's name. DEPRECATED: Use --source instead.")
	resolution = flag.Duration("metrics-resolution", 60*time.Second,
		"The resolution at which prometheus-to-sd will scrape the component for metrics.")
	metricsPrefix = flag.String("stackdriver-prefix", "container.googleapis.com/master",
		"Prefix that is appended to every metric.")
	whitelisted = flag.String("whitelisted-metrics", "",
		"Comma-separated list of whitelisted metrics. If empty all metrics will be exported. DEPRECATED: Use --source instead.")
	autoWhitelistMetrics = flag.Bool("auto-whitelist-metrics", false,
		"If component has no whitelisted metrics, prometheus-to-sd will fetch them from Stackdriver.")
	metricDescriptorsResolution = flag.Duration("metric-descriptors-resolution", 10*time.Minute,
		"The resolution at which prometheus-to-sd will scrape metric descriptors from Stackdriver.")
	apioverride = flag.String("api-override", "",
		"The stackdriver API endpoint to override the default one used (which is prod).")
	source = flags.Uris{}
	podId  = flag.String("pod-id", "machine",
		"Name of the pod in which monitored component is running.")
	namespaceId = flag.String("namespace-id", "",
		"Namespace name of the pod in which monitored component is running.")
	omitComponentName = flag.Bool("omit-component-name", true,
		"If metric name starts with the component name then this substring is removed to keep metric name shorter.")

	customMetricsPrefix = "custom.googleapis.com"
)

func main() {
	flag.Set("logtostderr", "true")
	flag.Var(&source, "source", "source(s) to watch in [component-name]:http://host:port?whitelisted=a,b,c format")

	defer glog.Flush()
	flag.Parse()

	sourceConfigs := config.SourceConfigsFromFlags(source, component, host, port, whitelisted)

	gceConf, err := config.GetGceConfig(*metricsPrefix)
	podConfig := &config.PodConfig{
		PodId:       *podId,
		NamespaceId: *namespaceId,
	}
	if err != nil {
		glog.Fatalf("Failed to get GCE config: %v", err)
	}
	glog.Infof("GCE config: %+v", gceConf)

	client := oauth2.NewClient(context.Background(), google.ComputeTokenSource(""))
	stackdriverService, err := v3.New(client)
	if *apioverride != "" {
		stackdriverService.BasePath = *apioverride
	}
	if err != nil {
		glog.Fatalf("Failed to create Stackdriver client: %v", err)
	}
	glog.V(4).Infof("Successfully created Stackdriver client")

	if len(sourceConfigs) == 0 {
		glog.Fatalf("No sources defined. Please specify at least one --source flag.")
	}

	for _, sourceConfig := range sourceConfigs {
		glog.V(4).Infof("Starting goroutine for %+v", sourceConfig)

		// Pass sourceConfig as a parameter to avoid using the last sourceConfig by all goroutines.
		go readAndPushDataToStackdriver(stackdriverService, gceConf, podConfig, sourceConfig)
	}

	// As worker goroutines work forever, block main thread as well.
	<-make(chan int)
}

func readAndPushDataToStackdriver(stackdriverService *v3.Service, gceConf *config.GceConfig, podConfig *config.PodConfig, sourceConfig config.SourceConfig) {
	glog.Infof("Running prometheus-to-sd, monitored target is %s %v:%v", sourceConfig.Component, sourceConfig.Host, sourceConfig.Port)
	commonConfig := &config.CommonConfig{
		GceConfig:     gceConf,
		PodConfig:     podConfig,
		ComponentName: sourceConfig.Component,
	}
	metricDescriptorCache := translator.NewMetricDescriptorCache(stackdriverService, commonConfig, sourceConfig.Component)
	signal := time.After(0)
	useWhitelistedMetricsAutodiscovery := *autoWhitelistMetrics && len(sourceConfig.Whitelisted) == 0

	for range time.Tick(*resolution) {
		// Mark cache at the beginning of each iteration as stale. Cache is considered refreshed only if during
		// current iteration there was successful call to Refresh function.
		metricDescriptorCache.MarkStale()
		glog.V(4).Infof("Scraping metrics of component %v", sourceConfig.Component)
		select {
		case <-signal:
			glog.V(4).Infof("Updating metrics cache for component %v", sourceConfig.Component)
			metricDescriptorCache.Refresh()
			if useWhitelistedMetricsAutodiscovery {
				sourceConfig.UpdateWhitelistedMetrics(metricDescriptorCache.GetMetricNames())
			}
			signal = time.After(*metricDescriptorsResolution)
		default:
		}
		if useWhitelistedMetricsAutodiscovery && len(sourceConfig.Whitelisted) == 0 {
			glog.V(4).Infof("Skipping %v component as there are no metric to expose.", sourceConfig.Component)
			continue
		}
		metrics, err := translator.GetPrometheusMetrics(sourceConfig.Host, sourceConfig.Port)
		if err != nil {
			glog.Warningf("Error while getting Prometheus metrics %v", err)
			continue
		}
		if *omitComponentName {
			metrics = translator.OmitComponentName(metrics, sourceConfig.Component)
		}
		if strings.HasPrefix(commonConfig.GceConfig.MetricsPrefix, customMetricsPrefix) {
			metricDescriptorCache.UpdateMetricDescriptors(metrics, sourceConfig.Whitelisted)
		}
		ts := translator.TranslatePrometheusToStackdriver(commonConfig, sourceConfig.Whitelisted, metrics, metricDescriptorCache)
		translator.SendToStackdriver(stackdriverService, gceConf, ts)
	}
}
<commit_msg>Add pprofiler to the prometheus-to-sd.<commit_after>/*
Copyright 2017 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"flag"
	"fmt"
	"net/http"
	_ "net/http/pprof"
	"strings"
	"time"

	"github.com/golang/glog"
	"golang.org/x/net/context"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	v3 "google.golang.org/api/monitoring/v3"

	"github.com/GoogleCloudPlatform/k8s-stackdriver/prometheus-to-sd/config"
	"github.com/GoogleCloudPlatform/k8s-stackdriver/prometheus-to-sd/flags"
	"github.com/GoogleCloudPlatform/k8s-stackdriver/prometheus-to-sd/translator"
)

var (
	host       = flag.String("target-host", "localhost", "The monitored component's hostname. DEPRECATED: Use --source instead.")
	port       = flag.Uint("target-port", 80, "The monitored component's port. DEPRECATED: Use --source instead.")
	component  = flag.String("component", "", "The monitored target's name. DEPRECATED: Use --source instead.")
	resolution = flag.Duration("metrics-resolution", 60*time.Second,
		"The resolution at which prometheus-to-sd will scrape the component for metrics.")
	metricsPrefix = flag.String("stackdriver-prefix", "container.googleapis.com/master",
		"Prefix that is appended to every metric.")
	whitelisted = flag.String("whitelisted-metrics", "",
		"Comma-separated list of whitelisted metrics. If empty all metrics will be exported. DEPRECATED: Use --source instead.")
	autoWhitelistMetrics = flag.Bool("auto-whitelist-metrics", false,
		"If component has no whitelisted metrics, prometheus-to-sd will fetch them from Stackdriver.")
	metricDescriptorsResolution = flag.Duration("metric-descriptors-resolution", 10*time.Minute,
		"The resolution at which prometheus-to-sd will scrape metric descriptors from Stackdriver.")
	apioverride = flag.String("api-override", "",
		"The stackdriver API endpoint to override the default one used (which is prod).")
	source = flags.Uris{}
	podId  = flag.String("pod-id", "machine",
		"Name of the pod in which monitored component is running.")
	namespaceId = flag.String("namespace-id", "",
		"Namespace name of the pod in which monitored component is running.")
	omitComponentName = flag.Bool("omit-component-name", true,
		"If metric name starts with the component name then this substring is removed to keep metric name shorter.")
	debugPort = flag.Uint("port", 6060, "Port on which debug information is exposed.")

	customMetricsPrefix = "custom.googleapis.com"
)

func main() {
	flag.Set("logtostderr", "true")
	flag.Var(&source, "source", "source(s) to watch in [component-name]:http://host:port?whitelisted=a,b,c format")

	defer glog.Flush()
	flag.Parse()

	sourceConfigs := config.SourceConfigsFromFlags(source, component, host, port, whitelisted)

	gceConf, err := config.GetGceConfig(*metricsPrefix)
	podConfig := &config.PodConfig{
		PodId:       *podId,
		NamespaceId: *namespaceId,
	}
	if err != nil {
		glog.Fatalf("Failed to get GCE config: %v", err)
	}
	glog.Infof("GCE config: %+v", gceConf)

	go func() {
		glog.Error(http.ListenAndServe(fmt.Sprintf(":%d", *debugPort), nil))
	}()

	client := oauth2.NewClient(context.Background(), google.ComputeTokenSource(""))
	stackdriverService, err := v3.New(client)
	if *apioverride != "" {
		stackdriverService.BasePath = *apioverride
	}
	if err != nil {
		glog.Fatalf("Failed to create Stackdriver client: %v", err)
	}
	glog.V(4).Infof("Successfully created Stackdriver client")

	if len(sourceConfigs) == 0 {
		glog.Fatalf("No sources defined. Please specify at least one --source flag.")
	}

	for _, sourceConfig := range sourceConfigs {
		glog.V(4).Infof("Starting goroutine for %+v", sourceConfig)

		// Pass sourceConfig as a parameter to avoid using the last sourceConfig by all goroutines.
		go readAndPushDataToStackdriver(stackdriverService, gceConf, podConfig, sourceConfig)
	}

	// As worker goroutines work forever, block main thread as well.
	<-make(chan int)
}

func readAndPushDataToStackdriver(stackdriverService *v3.Service, gceConf *config.GceConfig, podConfig *config.PodConfig, sourceConfig config.SourceConfig) {
	glog.Infof("Running prometheus-to-sd, monitored target is %s %v:%v", sourceConfig.Component, sourceConfig.Host, sourceConfig.Port)
	commonConfig := &config.CommonConfig{
		GceConfig:     gceConf,
		PodConfig:     podConfig,
		ComponentName: sourceConfig.Component,
	}
	metricDescriptorCache := translator.NewMetricDescriptorCache(stackdriverService, commonConfig, sourceConfig.Component)
	signal := time.After(0)
	useWhitelistedMetricsAutodiscovery := *autoWhitelistMetrics && len(sourceConfig.Whitelisted) == 0

	for range time.Tick(*resolution) {
		// Mark cache at the beginning of each iteration as stale. Cache is considered refreshed only if during
		// current iteration there was successful call to Refresh function.
		metricDescriptorCache.MarkStale()
		glog.V(4).Infof("Scraping metrics of component %v", sourceConfig.Component)
		select {
		case <-signal:
			glog.V(4).Infof("Updating metrics cache for component %v", sourceConfig.Component)
			metricDescriptorCache.Refresh()
			if useWhitelistedMetricsAutodiscovery {
				sourceConfig.UpdateWhitelistedMetrics(metricDescriptorCache.GetMetricNames())
			}
			signal = time.After(*metricDescriptorsResolution)
		default:
		}
		if useWhitelistedMetricsAutodiscovery && len(sourceConfig.Whitelisted) == 0 {
			glog.V(4).Infof("Skipping %v component as there are no metric to expose.", sourceConfig.Component)
			continue
		}
		metrics, err := translator.GetPrometheusMetrics(sourceConfig.Host, sourceConfig.Port)
		if err != nil {
			glog.Warningf("Error while getting Prometheus metrics %v", err)
			continue
		}
		if *omitComponentName {
			metrics = translator.OmitComponentName(metrics, sourceConfig.Component)
		}
		if strings.HasPrefix(commonConfig.GceConfig.MetricsPrefix, customMetricsPrefix) {
			metricDescriptorCache.UpdateMetricDescriptors(metrics, sourceConfig.Whitelisted)
		}
		ts := translator.TranslatePrometheusToStackdriver(commonConfig, sourceConfig.Whitelisted, metrics, metricDescriptorCache)
		translator.SendToStackdriver(stackdriverService, gceConf, ts)
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Niko Korhonen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// main executable for the teleport command
package main

import (
	"fmt"
	"os"
	"os/user"
	"path/filepath"
	"sort"
	"strings"
	"time"
	"unicode"

	"github.com/niktheblak/teleport/pkg/warppoint"
	"github.com/urfave/cli"
)

var (
	teleportHome     = ""
	teleportFileName = ".tp"
)

func main() {
	app := cli.NewApp()
	app.Name = "teleport"
	app.Usage = "Tool for rapidly switching between directories"
	app.Version = "1.0.0"
	app.Compiled = time.Now()
	app.Authors = []cli.Author{
		{
			Name:  "Niko Korhonen",
			Email: "niko@bitnik.fi",
		},
	}
	app.Copyright = "(c) 2018 Niko Korhonen"
	app.Commands = []cli.Command{
		{
			Name:      "add",
			Aliases:   []string{"a"},
			Usage:     "adds a warp point to the current directory or to the specified directory",
			ArgsUsage: "{warp point} [dir]",
			Action: func(c *cli.Context) error {
				switch c.NArg() {
				case 0:
					return fmt.Errorf("warp point name is required")
				case 1:
					key := strings.TrimSpace(c.Args().First())
					if !isValidKey(app, key) {
						return fmt.Errorf("%s cannot be used as warp point key\n", key)
					}
					dir, err := os.Getwd()
					if err != nil {
						return err
					}
					err = addWarpPoint(key, dir)
					if err != nil {
						return err
					}
				case 2:
					key := strings.TrimSpace(c.Args().First())
					if !isValidKey(app, key) {
						return fmt.Errorf("%s cannot be used as warp point key\n", key)
					}
					dir, err := filepath.Abs(c.Args().Get(1))
					if err != nil {
						return err
					}
					err = addWarpPoint(key, dir)
					if err != nil {
						return err
					}
				}
				return nil
			},
		},
		{
			Name:      "remove",
			Aliases:   []string{"rm"},
			Usage:     "removes warp point pointing to the current directory or the specified warp point",
			ArgsUsage: "[dir]",
			Action: func(c *cli.Context) error {
				switch c.NArg() {
				case 0:
					return removeCurrentDirWarpPoint()
				case 1:
					key := c.Args().First()
					return removeWarpPoint(key)
				}
				return nil
			},
		},
		{
			Name:    "list",
			Aliases: []string{"ls"},
			Usage:   "lists warp points",
			Action: func(c *cli.Context) error {
				return listWarpPoints()
			},
		},
		{
			Name:  "prune",
			Usage: "removes warp points whose target directory no longer exist",
			Action: func(c *cli.Context) error {
				return prune()
			},
		},
		{
			Name:      "warp",
			Aliases:   []string{"w"},
			Usage:     "teleport to the specified warp point",
			ArgsUsage: "{warp point}",
			Action: func(c *cli.Context) error {
				return warpTo(c.Args().First())
			},
		},
	}
	tpHome, ok := os.LookupEnv("TELEPORT_HOME")
	if ok {
		teleportHome = tpHome
	}
	tpFile, ok := os.LookupEnv("TELEPORT_FILE")
	if ok {
		teleportFileName = tpFile
	}
	if err := app.Run(os.Args); err != nil {
		fmt.Fprint(os.Stderr, err)
		os.Exit(1)
	}
}

func isValidKey(app *cli.App, key string) bool {
	if isCommand(app, key) || strings.Contains(key, "=") {
		return false
	}
	for _, r := range key {
		if unicode.IsSpace(r) || !unicode.IsPrint(r) {
			return false
		}
	}
	return true
}

func isCommand(app *cli.App, s string) bool {
	for _, c := range app.Commands {
		if s == c.Name {
			return true
		}
		for _, a := range c.Aliases {
			if s == a {
				return true
			}
		}
	}
	return false
}

func warpTo(key string) error {
	f, err := warpPointsFile()
	if err != nil {
		return err
	}
	wps, err := warppoint.ReadFromFile(f)
	if err != nil {
		return err
	}
	dir, ok := wps[key]
	if !ok {
		return fmt.Errorf("warp point %s does not exist", key)
	}
	fmt.Println(dir)
	return nil
}

func addWarpPoint(key, dir string) error {
	f, err := warpPointsFile()
	if err != nil {
		return err
	}
	wps, err := warppoint.ReadFromFile(f)
	if err != nil {
		return err
	}
	wps[key] = dir
	return warppoint.WriteToFile(f, wps)
}

func listWarpPoints() error {
	f, err := warpPointsFile()
	if err != nil {
		return err
	}
	wps, err := warppoint.ReadFromFile(f)
	if err != nil {
		return err
	}
	var sorted []string
	for key := range wps {
		sorted = append(sorted, key)
	}
	sort.Strings(sorted)
	for _, wp := range sorted {
		fmt.Printf("%s\t%s\n", wp, wps[wp])
	}
	return nil
}

func removeWarpPoint(key string) error {
	f, err := warpPointsFile()
	if err != nil {
		return err
	}
	wps, err := warppoint.ReadFromFile(f)
	if err != nil {
		return err
	}
	delete(wps, key)
	return warppoint.WriteToFile(f, wps)
}

func removeCurrentDirWarpPoint() error {
	dir, err := os.Getwd()
	if err != nil {
		return err
	}
	f, err := warpPointsFile()
	if err != nil {
		return err
	}
	wps, err := warppoint.ReadFromFile(f)
	if err != nil {
		return err
	}
	for key, val := range wps {
		if val == dir {
			delete(wps, key)
			break
		}
	}
	return warppoint.WriteToFile(f, wps)
}

func prune() error {
	f, err := warpPointsFile()
	if err != nil {
		return err
	}
	wps, err := warppoint.ReadFromFile(f)
	if err != nil {
		return err
	}
	var pruned []string
	for wp, path := range wps {
		target, err := os.Open(path)
		if err != nil {
			pruned = append(pruned, wp)
			continue
		}
		info, err := target.Stat()
		if err != nil {
			pruned = append(pruned, wp)
			continue
		}
		if !info.IsDir() {
			pruned = append(pruned, wp)
			continue
		}
	}
	for _, wp := range pruned {
		fmt.Printf("Removing warp point %s to %s\n", wp, wps[wp])
		delete(wps, wp)
	}
	return warppoint.WriteToFile(f, wps)
}

func warpPointsFile() (string, error) {
	if teleportHome != "" {
		return fmt.Sprintf("%s/%s", teleportHome, teleportFileName), nil
	}
	u, err := user.Current()
	if err != nil {
		return "", err
	}
	return fmt.Sprintf("%s/%s", u.HomeDir, teleportFileName), nil
}
<commit_msg>Propagate non file not found errors<commit_after>/*
 * Copyright 2017 Niko Korhonen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// main executable for the teleport command
package main

import (
	"fmt"
	"os"
	"os/user"
	"path/filepath"
	"sort"
	"strings"
	"time"
	"unicode"

	"github.com/niktheblak/teleport/pkg/warppoint"
	"github.com/urfave/cli"
)

var (
	teleportHome     = ""
	teleportFileName = ".tp"
)

func main() {
	app := cli.NewApp()
	app.Name = "teleport"
	app.Usage = "Tool for rapidly switching between directories"
	app.Version = "1.0.0"
	app.Compiled = time.Now()
	app.Authors = []cli.Author{
		{
			Name:  "Niko Korhonen",
			Email: "niko@bitnik.fi",
		},
	}
	app.Copyright = "(c) 2018 Niko Korhonen"
	app.Commands = []cli.Command{
		{
			Name:      "add",
			Aliases:   []string{"a"},
			Usage:     "adds a warp point to the current directory or to the specified directory",
			ArgsUsage: "{warp point} [dir]",
			Action: func(c *cli.Context) error {
				switch c.NArg() {
				case 0:
					return fmt.Errorf("warp point name is required")
				case 1:
					key := strings.TrimSpace(c.Args().First())
					if !isValidKey(app, key) {
						return fmt.Errorf("%s cannot be used as warp point key\n", key)
					}
					dir, err := os.Getwd()
					if err != nil {
						return err
					}
					err = addWarpPoint(key, dir)
					if err != nil {
						return err
					}
				case 2:
					key := strings.TrimSpace(c.Args().First())
					if !isValidKey(app, key) {
						return fmt.Errorf("%s cannot be used as warp point key\n", key)
					}
					dir, err := filepath.Abs(c.Args().Get(1))
					if err != nil {
						return err
					}
					err = addWarpPoint(key, dir)
					if err != nil {
						return err
					}
				}
				return nil
			},
		},
		{
			Name:      "remove",
			Aliases:   []string{"rm"},
			Usage:     "removes warp point pointing to the current directory or the specified warp point",
			ArgsUsage: "[dir]",
			Action: func(c *cli.Context) error {
				switch c.NArg() {
				case 0:
					return removeCurrentDirWarpPoint()
				case 1:
					key := c.Args().First()
					return removeWarpPoint(key)
				}
				return nil
			},
		},
		{
			Name:    "list",
			Aliases: []string{"ls"},
			Usage:   "lists warp points",
			Action: func(c *cli.Context) error {
				return listWarpPoints()
			},
		},
		{
			Name:  "prune",
			Usage: "removes warp points whose target directory no longer exist",
			Action: func(c *cli.Context) error {
				return prune()
			},
		},
		{
			Name:      "warp",
			Aliases:   []string{"w"},
			Usage:     "teleport to the specified warp point",
			ArgsUsage: "{warp point}",
			Action: func(c *cli.Context) error {
				return warpTo(c.Args().First())
			},
		},
	}
	tpHome, ok := os.LookupEnv("TELEPORT_HOME")
	if ok {
		teleportHome = tpHome
	}
	tpFile, ok := os.LookupEnv("TELEPORT_FILE")
	if ok {
		teleportFileName = tpFile
	}
	if err := app.Run(os.Args); err != nil {
		fmt.Fprint(os.Stderr, err)
		os.Exit(1)
	}
}

func isValidKey(app *cli.App, key string) bool {
	if isCommand(app, key) || strings.Contains(key, "=") {
		return false
	}
	for _, r := range key {
		if unicode.IsSpace(r) || !unicode.IsPrint(r) {
			return false
		}
	}
	return true
}

func isCommand(app *cli.App, s string) bool {
	for _, c := range app.Commands {
		if s == c.Name {
			return true
		}
		for _, a := range c.Aliases {
			if s == a {
				return true
			}
		}
	}
	return false
}

func warpTo(key string) error {
	f, err := warpPointsFile()
	if err != nil {
		return err
	}
	wps, err := warppoint.ReadFromFile(f)
	if err != nil {
		return err
	}
	dir, ok := wps[key]
	if !ok {
		return fmt.Errorf("warp point %s does not exist", key)
	}
	fmt.Println(dir)
	return nil
}

func addWarpPoint(key, dir string) error {
	f, err := warpPointsFile()
	if err != nil {
		return err
	}
	wps, err := warppoint.ReadFromFile(f)
	if err != nil {
		return err
	}
	wps[key] = dir
	return warppoint.WriteToFile(f, wps)
}

func listWarpPoints() error {
	f, err := warpPointsFile()
	if err != nil {
		return err
	}
	wps, err := warppoint.ReadFromFile(f)
	if err != nil {
		return err
	}
	var sorted []string
	for key := range wps {
		sorted = append(sorted, key)
	}
	sort.Strings(sorted)
	for _, wp := range sorted {
		fmt.Printf("%s\t%s\n", wp, wps[wp])
	}
	return nil
}

func removeWarpPoint(key string) error {
	f, err := warpPointsFile()
	if err != nil {
		return err
	}
	wps, err := warppoint.ReadFromFile(f)
	if err != nil {
		return err
	}
	delete(wps, key)
	return warppoint.WriteToFile(f, wps)
}

func removeCurrentDirWarpPoint() error {
	dir, err := os.Getwd()
	if err != nil {
		return err
	}
	f, err := warpPointsFile()
	if err != nil {
		return err
	}
	wps, err := warppoint.ReadFromFile(f)
	if err != nil {
		return err
	}
	for key, val := range wps {
		if val == dir {
			delete(wps, key)
			break
		}
	}
	return warppoint.WriteToFile(f, wps)
}

func prune() error {
	f, err := warpPointsFile()
	if err != nil {
		return err
	}
	wps, err := warppoint.ReadFromFile(f)
	if err != nil {
		return err
	}
	var pruned []string
	for wp, path := range wps {
		target, err := os.Open(path)
		if err != nil {
			if os.IsNotExist(err) {
				pruned = append(pruned, wp)
				continue
			} else {
				return err
			}
		}
		info, err := target.Stat()
		if err != nil {
			pruned = append(pruned, wp)
			continue
		}
		if !info.IsDir() {
			pruned = append(pruned, wp)
			continue
		}
	}
	for _, wp := range pruned {
		fmt.Printf("Removing warp point %s to %s\n", wp, wps[wp])
		delete(wps, wp)
	}
	return warppoint.WriteToFile(f, wps)
}

func warpPointsFile() (string, error) {
	if teleportHome != "" {
		return fmt.Sprintf("%s/%s", teleportHome, teleportFileName), nil
	}
	u, err := user.Current()
	if err != nil {
		return "", err
	}
	return fmt.Sprintf("%s/%s", u.HomeDir, teleportFileName), nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"os"
)

type IPAddress struct {
	IP string `json:"ip"`
}

func ipify(w http.ResponseWriter, r *http.Request) {
	host := net.ParseIP(r.Header["X-Forwarded-For"][len(r.Header["X-Forwarded-For"])-1]).String()
	jsonStr, _ := json.MarshalIndent(IPAddress{host}, "", "  ")

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, string(jsonStr))
}

func main() {
	http.HandleFunc("/", ipify)

	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<commit_msg>Removing indented Marshalling stuff.<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"os"
)

type IPAddress struct {
	IP string `json:"ip"`
}

func ipify(w http.ResponseWriter, r *http.Request) {
	host := net.ParseIP(r.Header["X-Forwarded-For"][len(r.Header["X-Forwarded-For"])-1]).String()
	jsonStr, _ := json.Marshal(IPAddress{host})

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, string(jsonStr))
}

func main() {
	http.HandleFunc("/", ipify)

	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
)

type IPAddress struct {
	IP string `json:"ip"`
}

func ipify(w http.ResponseWriter, r *http.Request) {
	host := net.ParseIP(r.Header["X-Forwarded-For"][len(r.Header["X-Forwarded-For"])-1]).String()
	jsonStr, _ := json.MarshalIndent(IPAddress{host}, "", "  ")

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, string(jsonStr))
}

func main() {
	http.HandleFunc("/", ipify)

	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<commit_msg>Removing unused dependency.<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"os"
)

type IPAddress struct {
	IP string `json:"ip"`
}

func ipify(w http.ResponseWriter, r *http.Request) {
	host := net.ParseIP(r.Header["X-Forwarded-For"][len(r.Header["X-Forwarded-For"])-1]).String()
	jsonStr, _ := json.MarshalIndent(IPAddress{host}, "", "  ")

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, string(jsonStr))
}

func main() {
	http.HandleFunc("/", ipify)

	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2018, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package trace

import "go.opencensus.io/trace/internal"

// Config represents the global tracing configuration.
type Config struct {
	// DefaultSampler is the default sampler used when creating new spans.
	DefaultSampler Sampler

	// IDGenerator is for internal use only.
	IDGenerator internal.IDGenerator
}

// ApplyConfig applies changes to the global tracing configuration.
//
// Fields not provided in the given config are going to be preserved.
func ApplyConfig(cfg Config) {
	c := *config.Load().(*Config)
	if cfg.DefaultSampler != nil {
		c.DefaultSampler = cfg.DefaultSampler
	}
	if cfg.IDGenerator != nil {
		c.IDGenerator = cfg.IDGenerator
	}
	config.Store(&c)
}
<commit_msg>Fix race to update config in trace.ApplyConfig (#840)<commit_after>// Copyright 2018, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package trace

import (
	"go.opencensus.io/trace/internal"
	"sync"
)

// Config represents the global tracing configuration.
type Config struct {
	// DefaultSampler is the default sampler used when creating new spans.
	DefaultSampler Sampler

	// IDGenerator is for internal use only.
	IDGenerator internal.IDGenerator
}

var configWriteMu sync.Mutex

// ApplyConfig applies changes to the global tracing configuration.
//
// Fields not provided in the given config are going to be preserved.
func ApplyConfig(cfg Config) {
	configWriteMu.Lock()
	defer configWriteMu.Unlock()
	c := *config.Load().(*Config)
	if cfg.DefaultSampler != nil {
		c.DefaultSampler = cfg.DefaultSampler
	}
	if cfg.IDGenerator != nil {
		c.IDGenerator = cfg.IDGenerator
	}
	config.Store(&c)
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"io"
	"os"
	"syscall"
	"time"
)

// Network file descriptor.
type netFD struct {
	// locking/lifetime of sysfd + serialize access to Read and Write methods
	fdmu fdMutex

	// immutable until Close
	net          string
	n            string
	dir          string
	ctl, data    *os.File
	laddr, raddr Addr
}

var (
	netdir string // default network
)

func sysInit() {
	netdir = "/net"
}

func newFD(net, name string, ctl, data *os.File, laddr, raddr Addr) (*netFD, error) {
	return &netFD{net: net, n: name, dir: netdir + "/" + net + "/" + name, ctl: ctl, data: data, laddr: laddr, raddr: raddr}, nil
}

func (fd *netFD) init() error {
	// stub for future fd.pd.Init(fd)
	return nil
}

func (fd *netFD) name() string {
	var ls, rs string
	if fd.laddr != nil {
		ls = fd.laddr.String()
	}
	if fd.raddr != nil {
		rs = fd.raddr.String()
	}
	return fd.net + ":" + ls + "->" + rs
}

func (fd *netFD) ok() bool { return fd != nil && fd.ctl != nil }

func (fd *netFD) destroy() {
	if !fd.ok() {
		return
	}
	err := fd.ctl.Close()
	if fd.data != nil {
		if err1 := fd.data.Close(); err1 != nil && err == nil {
			err = err1
		}
	}
	fd.ctl = nil
	fd.data = nil
}

func (fd *netFD) Read(b []byte) (n int, err error) {
	if !fd.ok() || fd.data == nil {
		return 0, syscall.EINVAL
	}
	if err := fd.readLock(); err != nil {
		return 0, err
	}
	defer fd.readUnlock()
	n, err = fd.data.Read(b)
	if isHangup(err) {
		err = io.EOF
	}
	if fd.net == "udp" && err == io.EOF {
		n = 0
		err = nil
	}
	return
}

func (fd *netFD) Write(b []byte) (n int, err error) {
	if !fd.ok() || fd.data == nil {
		return 0, syscall.EINVAL
	}
	if err := fd.writeLock(); err != nil {
		return 0, err
	}
	defer fd.writeUnlock()
	return fd.data.Write(b)
}

func (fd *netFD) closeRead() error {
	if !fd.ok() {
		return syscall.EINVAL
	}
	return syscall.EPLAN9
}

func (fd *netFD) closeWrite() error {
	if !fd.ok() {
		return syscall.EINVAL
	}
	return syscall.EPLAN9
}

func (fd *netFD) Close() error {
	if !fd.fdmu.increfAndClose() {
		return errClosing
	}
	if !fd.ok() {
		return syscall.EINVAL
	}
	if fd.net == "tcp" {
		// The following line is required to unblock Reads.
		// For some reason, WriteString returns an error:
		// "write /net/tcp/39/listen: inappropriate use of fd"
		// But without it, Reads on dead conns hang forever.
		// See Issue 9554.
		fd.ctl.WriteString("hangup")
	}
	err := fd.ctl.Close()
	if fd.data != nil {
		if err1 := fd.data.Close(); err1 != nil && err == nil {
			err = err1
		}
	}
	fd.ctl = nil
	fd.data = nil
	return err
}

// This method is only called via Conn.
func (fd *netFD) dup() (*os.File, error) {
	if !fd.ok() || fd.data == nil {
		return nil, syscall.EINVAL
	}
	return fd.file(fd.data, fd.dir+"/data")
}

func (l *TCPListener) dup() (*os.File, error) {
	if !l.fd.ok() {
		return nil, syscall.EINVAL
	}
	return l.fd.file(l.fd.ctl, l.fd.dir+"/ctl")
}

func (fd *netFD) file(f *os.File, s string) (*os.File, error) {
	dfd, err := syscall.Dup(int(f.Fd()), -1)
	if err != nil {
		return nil, os.NewSyscallError("dup", err)
	}
	return os.NewFile(uintptr(dfd), s), nil
}

func (fd *netFD) setDeadline(t time.Time) error {
	return syscall.EPLAN9
}

func (fd *netFD) setReadDeadline(t time.Time) error {
	return syscall.EPLAN9
}

func (fd *netFD) setWriteDeadline(t time.Time) error {
	return syscall.EPLAN9
}

func setReadBuffer(fd *netFD, bytes int) error {
	return syscall.EPLAN9
}

func setWriteBuffer(fd *netFD, bytes int) error {
	return syscall.EPLAN9
}

func isHangup(err error) bool {
	return err != nil && stringsHasSuffix(err.Error(), "Hangup")
}
<commit_msg>net: don't return io.EOF from zero byte reads on Plan 9<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"io"
	"os"
	"syscall"
	"time"
)

// Network file descriptor.
type netFD struct {
	// locking/lifetime of sysfd + serialize access to Read and Write methods
	fdmu fdMutex

	// immutable until Close
	net          string
	n            string
	dir          string
	ctl, data    *os.File
	laddr, raddr Addr
}

var (
	netdir string // default network
)

func sysInit() {
	netdir = "/net"
}

func newFD(net, name string, ctl, data *os.File, laddr, raddr Addr) (*netFD, error) {
	return &netFD{net: net, n: name, dir: netdir + "/" + net + "/" + name, ctl: ctl, data: data, laddr: laddr, raddr: raddr}, nil
}

func (fd *netFD) init() error {
	// stub for future fd.pd.Init(fd)
	return nil
}

func (fd *netFD) name() string {
	var ls, rs string
	if fd.laddr != nil {
		ls = fd.laddr.String()
	}
	if fd.raddr != nil {
		rs = fd.raddr.String()
	}
	return fd.net + ":" + ls + "->" + rs
}

func (fd *netFD) ok() bool { return fd != nil && fd.ctl != nil }

func (fd *netFD) destroy() {
	if !fd.ok() {
		return
	}
	err := fd.ctl.Close()
	if fd.data != nil {
		if err1 := fd.data.Close(); err1 != nil && err == nil {
			err = err1
		}
	}
	fd.ctl = nil
	fd.data = nil
}

func (fd *netFD) Read(b []byte) (n int, err error) {
	if !fd.ok() || fd.data == nil {
		return 0, syscall.EINVAL
	}
	if err := fd.readLock(); err != nil {
		return 0, err
	}
	defer fd.readUnlock()
	if len(b) == 0 {
		return 0, nil
	}
	n, err = fd.data.Read(b)
	if isHangup(err) {
		err = io.EOF
	}
	if fd.net == "udp" && err == io.EOF {
		n = 0
		err = nil
	}
	return
}

func (fd *netFD) Write(b []byte) (n int, err error) {
	if !fd.ok() || fd.data == nil {
		return 0, syscall.EINVAL
	}
	if err := fd.writeLock(); err != nil {
		return 0, err
	}
	defer fd.writeUnlock()
	return fd.data.Write(b)
}

func (fd *netFD) closeRead() error {
	if !fd.ok() {
		return syscall.EINVAL
	}
	return syscall.EPLAN9
}

func (fd *netFD) closeWrite() error {
	if !fd.ok() {
		return syscall.EINVAL
	}
	return syscall.EPLAN9
}

func (fd *netFD) Close() error {
	if !fd.fdmu.increfAndClose() {
		return errClosing
	}
	if !fd.ok() {
		return syscall.EINVAL
	}
	if fd.net == "tcp" {
		// The following line is required to unblock Reads.
		// For some reason, WriteString returns an error:
		// "write /net/tcp/39/listen: inappropriate use of fd"
		// But without it, Reads on dead conns hang forever.
		// See Issue 9554.
		fd.ctl.WriteString("hangup")
	}
	err := fd.ctl.Close()
	if fd.data != nil {
		if err1 := fd.data.Close(); err1 != nil && err == nil {
			err = err1
		}
	}
	fd.ctl = nil
	fd.data = nil
	return err
}

// This method is only called via Conn.
func (fd *netFD) dup() (*os.File, error) {
	if !fd.ok() || fd.data == nil {
		return nil, syscall.EINVAL
	}
	return fd.file(fd.data, fd.dir+"/data")
}

func (l *TCPListener) dup() (*os.File, error) {
	if !l.fd.ok() {
		return nil, syscall.EINVAL
	}
	return l.fd.file(l.fd.ctl, l.fd.dir+"/ctl")
}

func (fd *netFD) file(f *os.File, s string) (*os.File, error) {
	dfd, err := syscall.Dup(int(f.Fd()), -1)
	if err != nil {
		return nil, os.NewSyscallError("dup", err)
	}
	return os.NewFile(uintptr(dfd), s), nil
}

func (fd *netFD) setDeadline(t time.Time) error {
	return syscall.EPLAN9
}

func (fd *netFD) setReadDeadline(t time.Time) error {
	return syscall.EPLAN9
}

func (fd *netFD) setWriteDeadline(t time.Time) error {
	return syscall.EPLAN9
}

func setReadBuffer(fd *netFD, bytes int) error {
	return syscall.EPLAN9
}

func setWriteBuffer(fd *netFD, bytes int) error {
	return syscall.EPLAN9
}

func isHangup(err error) bool {
	return err != nil && stringsHasSuffix(err.Error(), "Hangup")
}
<|endoftext|>