<commit_before>package golog

import "github.com/mndrix/golog/read"

import "testing"

func TestFacts (t *testing.T) {
    rt := read.Term_
    facts := read.TermAll_(`
        father(michael).
        father(marc).
        parent(X) :-
            father(X).
    `)
    db := NewDatabase()
    for _, fact := range facts {
        db = db.Asserta(fact)
    }
    t.Logf("%s\n", db.String())

    // these should be provably true
    if !IsTrue(db, rt(`father(michael).`)) {
        t.Errorf("Couldn't prove father(michael)")
    }
    if !IsTrue(db, rt(`father(marc).`)) {
        t.Errorf("Couldn't prove father(marc)")
    }
    if !IsTrue(db, rt(`parent(michael).`)) {
        t.Errorf("Couldn't prove parent(michael)")
    }
    if !IsTrue(db, rt(`parent(marc).`)) {
        t.Errorf("Couldn't prove parent(marc)")
    }

    // these should not be provable
    if IsTrue(db, rt(`father(sue).`)) {
        t.Errorf("Proved father(sue)")
    }
    if IsTrue(db, rt(`father(michael,marc).`)) {
        t.Errorf("Proved father(michael, marc)")
    }
    if IsTrue(db, rt(`mother(michael).`)) {
        t.Errorf("Proved mother(michael)")
    }
    if IsTrue(db, rt(`parent(sue).`)) {
        t.Errorf("Proved parent(sue)")
    }

    // trivial predicate with multiple solutions
    solutions := ProveAll(db, rt(`father(X).`))
    if len(solutions) != 2 {
        t.Errorf("Wrong number of solutions: %d vs 2", len(solutions))
    }
    if x := solutions[0].ByName_("X").String(); x != "marc" {  // 1st by Asserta
        t.Errorf("Wrong first solution: %s", x)
    }
    if x := solutions[1].ByName_("X").String(); x != "michael" {  // 2nd by Asserta
        t.Errorf("Wrong second solution: %s", x)
    }

    // simple predicate with multiple solutions
    solutions = ProveAll(db, rt(`parent(X).`))
    if len(solutions) != 2 {
        t.Errorf("Wrong number of solutions: %d vs 2", len(solutions))
    }
    if x := solutions[0].ByName_("X").String(); x != "marc" {  // 1st by Asserta
        t.Errorf("Wrong first solution: %s", x)
    }
    if x := solutions[1].ByName_("X").String(); x != "michael" {  // 2nd by Asserta
        t.Errorf("Wrong second solution: %s", x)
    }
}
<commit_msg>Slightly more complicated test case<commit_after>package golog

import "github.com/mndrix/golog/read"

import "testing"

func TestFacts (t *testing.T) {
    rt := read.Term_
    facts := read.TermAll_(`
        father(michael).
        father(marc).
        mother(gail).
        parent(X) :-
            father(X).
        parent(X) :-
            mother(X).
    `)
    db := NewDatabase()
    for _, fact := range facts {
        db = db.Asserta(fact)
    }
    t.Logf("%s\n", db.String())

    // these should be provably true
    if !IsTrue(db, rt(`father(michael).`)) {
        t.Errorf("Couldn't prove father(michael)")
    }
    if !IsTrue(db, rt(`father(marc).`)) {
        t.Errorf("Couldn't prove father(marc)")
    }
    if !IsTrue(db, rt(`parent(michael).`)) {
        t.Errorf("Couldn't prove parent(michael)")
    }
    if !IsTrue(db, rt(`parent(marc).`)) {
        t.Errorf("Couldn't prove parent(marc)")
    }

    // these should not be provable
    if IsTrue(db, rt(`father(sue).`)) {
        t.Errorf("Proved father(sue)")
    }
    if IsTrue(db, rt(`father(michael,marc).`)) {
        t.Errorf("Proved father(michael, marc)")
    }
    if IsTrue(db, rt(`mother(michael).`)) {
        t.Errorf("Proved mother(michael)")
    }
    if IsTrue(db, rt(`parent(sue).`)) {
        t.Errorf("Proved parent(sue)")
    }

    // trivial predicate with multiple solutions
    solutions := ProveAll(db, rt(`father(X).`))
    if len(solutions) != 2 {
        t.Errorf("Wrong number of solutions: %d vs 2", len(solutions))
    }
    if x := solutions[0].ByName_("X").String(); x != "marc" {  // 1st by Asserta
        t.Errorf("Wrong first solution: %s", x)
    }
    if x := solutions[1].ByName_("X").String(); x != "michael" {  // 2nd by Asserta
        t.Errorf("Wrong second solution: %s", x)
    }

    // simple predicate with multiple solutions
    solutions = ProveAll(db, rt(`parent(X).`))
    if len(solutions) != 3 {
        t.Errorf("Wrong number of solutions: %d vs 2", len(solutions))
    }
    if x := solutions[0].ByName_("X").String(); x != "gail" {  // 1st by Asserta
        t.Errorf("Wrong first solution: %s", x)
    }
    if x := solutions[1].ByName_("X").String(); x != "marc" {  // 2nd by Asserta
        t.Errorf("Wrong second solution: %s", x)
    }
    if x := solutions[2].ByName_("X").String(); x != "michael" {  // 3rd by Asserta
        t.Errorf("Wrong third solution: %s", x)
    }
}
<|endoftext|>


<commit_before>package main

import (
    "github.com/elazarl/goproxy"
    "log"
    "flag"
    "bufio"
    "os"
    "fmt"
    "strings"
    "regexp"
    "net/http"
    "net/url"
)

// TODO: Try and get HTTPS MITM working so we can also block javascript/ads on
// https sites

// TODO: remember exceptions, allow option to except anythign on a given
// domain or subdomain.domain

func main() {
    verbose := flag.Bool("v", false, "should every proxy request be logged to stdout")
    addr := flag.String("addr", "127.0.0.1:3128", "proxy listen address")
    whitelistFilename := flag.String("wl", "whitelist.txt", "file of regexes to whitelist request urls (overrides blacklist)")
    blacklistFilename := flag.String("bl", "blacklist.txt", "file of regexes to blacklistlist request urls")

    whiteList, wlErr := getRegexlist(*whitelistFilename)
    if wlErr != nil {
        log.Fatalf("Could not load whitelist. Error: %s", wlErr)
    }
    blackList, blErr := getRegexlist(*blacklistFilename)
    if blErr != nil {
        log.Fatalf("Could not load blacklist. Error: %s", blErr)
    }
    flag.Parse()
    proxyExceptionString := "LOL-WHUT-JUST-DOIT-DOOD"
    proxy := goproxy.NewProxyHttpServer()
    proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm)
    proxy.OnRequest().DoFunc(func (req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
        // Prevent upgrades to https so we can easily see everything as plain
        if req.URL.Scheme == "https" {
            req.URL.Scheme = "http"
        }
        urlString := req.URL.String()
        for _, w := range whiteList {
            if w.MatchString(urlString) {
                log.Printf("WHITELISTED:  %s\n", req.URL)
                return req, nil
            }
        }
        // See if we're manually allowing this page thru
        if (strings.HasSuffix(urlString, proxyExceptionString)) {
            urlString := urlString[:len(urlString) - len(proxyExceptionString)]
            u, uErr := url.Parse(urlString)
            if uErr == nil {
                req.URL = u
                log.Printf("MANUALLY ALLOWED: %s\n", req.URL)
                return req, nil
            } else {
                log.Printf("ERROR trying to rewrite URL. Url: %s, Error: %s", urlString, uErr)
                return req, goproxy.NewResponse(req,
                        goproxy.ContentTypeHtml, http.StatusForbidden,
                        fmt.Sprintf(`
                            <title>BAD URL</title>

Ehhh.... wut?

Error rewriting URL:

%s

Error:

%s

                        `, urlString, uErr))
            }
        }
        for _, b := range blackList {
            if b.MatchString(urlString) {
                log.Printf("BLACKLISTED:  %s\n", req.URL)
                return req, goproxy.NewResponse(req,
                        goproxy.ContentTypeHtml, http.StatusForbidden,
                        fmt.Sprintf(`
                            <title>BLOCKED</title>

I pitty the fool!

Webpage Blocked

%s

Continue to Webpage

                        `, req.URL, req.URL, proxyExceptionString))
            }
        }
        log.Printf("NOT MATCHED: (allow by default) %s\n", req.URL)
        return req, nil
    })
    proxy.Verbose = *verbose
    log.Fatal(http.ListenAndServe(*addr, proxy))
}

func getRegexlist(filename string) ([]*regexp.Regexp,  error) {
    file, err := os.Open(filename)
    if err != nil {
        log.Fatalf("Error opening %s: %q", filename, err)
    }
    defer file.Close()
    scanner := bufio.NewScanner(file)
    var list []*regexp.Regexp = make([]*regexp.Regexp, 0)
    for scanner.Scan() {
        line := strings.TrimSpace(scanner.Text())
        // ignore blank/whitespace lines and comments
        if len(line) > 0 && !strings.HasPrefix(line, "#") {
            // add ignore case option to regex and compile it
            if r, err := regexp.Compile("(?i)" + line) ; err == nil {
                list = append(list, r)
            } else {
                log.Fatalf("Invalid pattern: %q", err)
            }
        }
    }
    if err := scanner.Err(); err != nil {
        log.Fatalf("Error reading %s: %q", filename, err)
    }
    return list, nil
}

<commit_msg>moving flags parse before using options<commit_after>package main

import (
    "github.com/elazarl/goproxy"
    "log"
    "flag"
    "bufio"
    "os"
    "fmt"
    "strings"
    "regexp"
    "net/http"
    "net/url"
)

// TODO: Try and get HTTPS MITM working so we can also block javascript/ads on
// https sites

// TODO: remember exceptions, allow option to except anythign on a given
// domain or subdomain.domain

func main() {
    verbose := flag.Bool("v", false, "should every proxy request be logged to stdout")
    addr := flag.String("addr", "127.0.0.1:3128", "proxy listen address")
    whitelistFilename := flag.String("wl", "whitelist.txt", "file of regexes to whitelist request urls (overrides blacklist)")
    blacklistFilename := flag.String("bl", "blacklist.txt", "file of regexes to blacklistlist request urls")

    flag.Parse()
    whiteList, wlErr := getRegexlist(*whitelistFilename)
    if wlErr != nil {
        log.Fatalf("Could not load whitelist. Error: %s", wlErr)
    }
    blackList, blErr := getRegexlist(*blacklistFilename)
    if blErr != nil {
        log.Fatalf("Could not load blacklist. Error: %s", blErr)
    }
    proxyExceptionString := "LOL-WHUT-JUST-DOIT-DOOD"
    proxy := goproxy.NewProxyHttpServer()
    proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm)
    proxy.OnRequest().DoFunc(func (req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
        // Prevent upgrades to https so we can easily see everything as plain
        if req.URL.Scheme == "https" {
            req.URL.Scheme = "http"
        }
        urlString := req.URL.String()
        for _, w := range whiteList {
            if w.MatchString(urlString) {
                log.Printf("WHITELISTED:  %s\n", req.URL)
                return req, nil
            }
        }
        // See if we're manually allowing this page thru
        if (strings.HasSuffix(urlString, proxyExceptionString)) {
            urlString := urlString[:len(urlString) - len(proxyExceptionString)]
            u, uErr := url.Parse(urlString)
            if uErr == nil {
                req.URL = u
                log.Printf("MANUALLY ALLOWED: %s\n", req.URL)
                return req, nil
            } else {
                log.Printf("ERROR trying to rewrite URL. Url: %s, Error: %s", urlString, uErr)
                return req, goproxy.NewResponse(req,
                        goproxy.ContentTypeHtml, http.StatusForbidden,
                        fmt.Sprintf(`
                            <title>BAD URL</title>

Ehhh.... wut?

Error rewriting URL:

%s

Error:

%s

                        `, urlString, uErr))
            }
        }
        for _, b := range blackList {
            if b.MatchString(urlString) {
                log.Printf("BLACKLISTED:  %s\n", req.URL)
                return req, goproxy.NewResponse(req,
                        goproxy.ContentTypeHtml, http.StatusForbidden,
                        fmt.Sprintf(`
                            <title>BLOCKED</title>

I pitty the fool!

Webpage Blocked

%s

Continue to Webpage

                        `, req.URL, req.URL, proxyExceptionString))
            }
        }
        log.Printf("NOT MATCHED: (allow by default) %s\n", req.URL)
        return req, nil
    })
    proxy.Verbose = *verbose
    log.Fatal(http.ListenAndServe(*addr, proxy))
}

func getRegexlist(filename string) ([]*regexp.Regexp,  error) {
    file, err := os.Open(filename)
    if err != nil {
        log.Fatalf("Error opening %s: %q", filename, err)
    }
    defer file.Close()
    scanner := bufio.NewScanner(file)
    var list []*regexp.Regexp = make([]*regexp.Regexp, 0)
    for scanner.Scan() {
        line := strings.TrimSpace(scanner.Text())
        // ignore blank/whitespace lines and comments
        if len(line) > 0 && !strings.HasPrefix(line, "#") {
            // add ignore case option to regex and compile it
            if r, err := regexp.Compile("(?i)" + line) ; err == nil {
                list = append(list, r)
            } else {
                log.Fatalf("Invalid pattern: %q", err)
            }
        }
    }
    if err := scanner.Err(); err != nil {
        log.Fatalf("Error reading %s: %q", filename, err)
    }
    return list, nil
}

<|endoftext|>


<commit_before>package pt

import (
	"errors"
	"fmt"
	"image"
	"path"
	"strings"
)

type Texture interface {
	Sample(u, v float64) Color
}

type ImageTexture struct {
	image.Image
}

var textures map[string]Texture

func init() {
	textures = make(map[string]Texture)
}

func PNGTexture(path string) (Texture, error) {
	fmt.Printf("Loading PNG: %s\n", path)
	im, err := LoadPNG(path)
	if err != nil {
		return nil, err
	}
	return &ImageTexture{im}, nil
}

func JPGTexture(path string) (Texture, error) {
	fmt.Printf("Loading JPG: %s\n", path)
	im, err := LoadJPG(path)
	if err != nil {
		return nil, err
	}
	return &ImageTexture{im}, nil
}

func LoadTexture(p string) (Texture, error) {
	ext := strings.ToLower(path.Ext(p))
	switch ext {
	case ".png":
		return PNGTexture(p)
	case ".jpg":
		return JPGTexture(p)
	case ".jpeg":
		return JPGTexture(p)
	}
	err := errors.New(fmt.Sprintf("Unrecognized texture extension: %s", p))
	return nil, err
}

func GetTexture(path string) Texture {
	if texture, ok := textures[path]; ok {
		return texture
	}
	if texture, err := LoadTexture(path); err == nil {
		textures[path] = texture
		return texture
	}
	return nil
}

func (t *ImageTexture) Sample(u, v float64) Color {
	u = Fract(Fract(u) + 1)
	v = Fract(Fract(v) + 1)
	size := t.Image.Bounds().Max
	x := int(u * float64(size.X-1))
	y := int(v * float64(size.Y-1))
	r, g, b, _ := t.Image.At(x, y).RGBA()
	return Color{float64(r) / 65535, float64(g) / 65535, float64(b) / 65535}.Pow(2.2)
}
<commit_msg>ColorTexture<commit_after>package pt

import (
	"errors"
	"fmt"
	"image"
	"path"
	"strings"
)

type Texture interface {
	Sample(u, v float64) Color
}

var textures map[string]Texture

func init() {
	textures = make(map[string]Texture)
}

func GetTexture(path string) Texture {
	if texture, ok := textures[path]; ok {
		return texture
	}
	if texture, err := LoadTexture(path); err == nil {
		textures[path] = texture
		return texture
	}
	return nil
}

func LoadTexture(p string) (Texture, error) {
	ext := strings.ToLower(path.Ext(p))
	switch ext {
	case ".png":
		return PNGTexture(p)
	case ".jpg":
		return JPGTexture(p)
	case ".jpeg":
		return JPGTexture(p)
	}
	err := errors.New(fmt.Sprintf("Unrecognized texture extension: %s", p))
	return nil, err
}

func PNGTexture(path string) (Texture, error) {
	fmt.Printf("Loading PNG: %s\n", path)
	im, err := LoadPNG(path)
	if err != nil {
		return nil, err
	}
	return NewTexture(im), nil
}

func JPGTexture(path string) (Texture, error) {
	fmt.Printf("Loading JPG: %s\n", path)
	im, err := LoadJPG(path)
	if err != nil {
		return nil, err
	}
	return NewTexture(im), nil
}

type ColorTexture struct {
	width, height int
	data          []Color
}

func NewTexture(im image.Image) Texture {
	size := im.Bounds().Max
	data := make([]Color, size.X*size.Y)
	for y := 0; y < size.Y; y++ {
		for x := 0; x < size.X; x++ {
			index := y*size.X + x
			r, g, b, _ := im.At(x, y).RGBA()
			fr := float64(r) / 65535
			fg := float64(g) / 65535
			fb := float64(b) / 65535
			data[index] = Color{fr, fg, fb}.Pow(2.2)
		}
	}
	return &ColorTexture{size.X, size.Y, data}
}

func (t *ColorTexture) Sample(u, v float64) Color {
	u = Fract(Fract(u) + 1)
	v = Fract(Fract(v) + 1)
	x := int(u * float64(t.width-1))
	y := int(v * float64(t.height-1))
	return t.data[y*t.width+x]
}
<|endoftext|>


<commit_before>package veneur

import (
	"container/ring"
	"context"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
	"sync"
	"time"

	"github.com/DataDog/datadog-go/statsd"
	lightstep "github.com/lightstep/lightstep-tracer-go"
	opentracing "github.com/opentracing/opentracing-go"
	"github.com/opentracing/opentracing-go/ext"
	"github.com/sirupsen/logrus"
	"github.com/stripe/veneur/ssf"
	"github.com/stripe/veneur/trace"
)

const datadogResourceKey = "resource"
const datadogNameKey = "name"

const lightStepOperationKey = "name"

const totalSpansFlushedMetricKey = "worker.spans_flushed_total"

// spanSink is a receiver of spans that handles sending those spans to some
// downstream sink. Calls to `Ingest(span)` are meant to give the sink control
// of the span, with periodic calls to flush as a signal for sinks that don't
// handle their own flushing in a separate goroutine, etc.
type spanSink interface {
	Name() string
	Ingest(ssf.SSFSpan) error
	Flush()
}

// DatadogSpanSink is a sink for sending spans to a Datadog trace agent.
type datadogSpanSink struct {
	HTTPClient   *http.Client
	buffer       *ring.Ring
	bufferSize   int
	mutex        *sync.Mutex
	stats        *statsd.Client
	commonTags   map[string]string
	traceAddress string
}

// NewDatadogSpanSink creates a new Datadog sink for trace spans.
func NewDatadogSpanSink(config *Config, stats *statsd.Client, httpClient *http.Client, commonTags map[string]string) (*datadogSpanSink, error) {
	return &datadogSpanSink{
		HTTPClient:   httpClient,
		bufferSize:   config.SsfBufferSize,
		buffer:       ring.New(config.SsfBufferSize),
		mutex:        &sync.Mutex{},
		stats:        stats,
		commonTags:   commonTags,
		traceAddress: config.DatadogTraceAPIAddress,
	}, nil
}

// Name returns the name of this sink.
func (dd *datadogSpanSink) Name() string {
	return "datadog"
}

// Ingest takes the span and adds it to the ringbuffer.
func (dd *datadogSpanSink) Ingest(span ssf.SSFSpan) error {
	dd.mutex.Lock()
	defer dd.mutex.Unlock()

	dd.buffer.Value = span
	dd.buffer = dd.buffer.Next()
	return nil
}

// Flush signals the sink to send it's spans to their destination. For this
// sync it means we'll be making an HTTP request to send them along. We assume
// it's beneficial to performance to defer these until the normal 10s flush.
func (dd *datadogSpanSink) Flush() {
	dd.mutex.Lock()

	ssfSpans := make([]ssf.SSFSpan, 0, dd.buffer.Len())

	dd.buffer.Do(func(t interface{}) {
		const tooEarly = 1497
		const tooLate = 1497629343000000

		if t != nil {
			ssfSpan, ok := t.(ssf.SSFSpan)
			if !ok {
				log.Error("Got an unknown object in tracing ring!")
				// We'll just skip this one so we don't poison pill or anything.
				return
			}

			var timeErr string
			if ssfSpan.StartTimestamp < tooEarly {
				timeErr = "type:tooEarly"
			}
			if ssfSpan.StartTimestamp > tooLate {
				timeErr = "type:tooLate"
			}
			if timeErr != "" {
				dd.stats.Incr("worker.trace.sink.timestamp_error", []string{timeErr}, 1) // TODO tag as dd?
			}

			if ssfSpan.Tags == nil {
				ssfSpan.Tags = make(map[string]string)
			}

			// Add common tags from veneur's config
			// this will overwrite tags already present on the span
			for k, v := range dd.commonTags {
				ssfSpan.Tags[k] = v
			}
			ssfSpans = append(ssfSpans, ssfSpan)
		}
	})

	// Reset the ring.
	dd.buffer = ring.New(dd.bufferSize)

	// We're done manipulating stuff, let Ingest loose again.
	dd.mutex.Unlock()

	serviceCount := make(map[string]int64)
	var finalTraces []*DatadogTraceSpan
	// Conver the SSFSpans into Datadog Spans
	for _, span := range ssfSpans {
		// -1 is a canonical way of passing in invalid info in Go
		// so we should support that too
		parentID := span.ParentId

		// check if this is the root span
		if parentID <= 0 {
			// we need parentId to be zero for json:omitempty to work
			parentID = 0
		}

		resource := span.Tags[datadogResourceKey]
		name := span.Name

		tags := map[string]string{}
		// Get the span's existing tags
		for k, v := range span.Tags {
			tags[k] = v
		}

		delete(tags, datadogResourceKey)

		// TODO implement additional metrics
		var metrics map[string]float64

		var errorCode int64
		if span.Error {
			errorCode = 2
		}

		ddspan := &DatadogTraceSpan{
			TraceID:  span.TraceId,
			SpanID:   span.Id,
			ParentID: parentID,
			Service:  span.Service,
			Name:     name,
			Resource: resource,
			Start:    span.StartTimestamp,
			Duration: span.EndTimestamp - span.StartTimestamp,
			// TODO don't hardcode
			Type:    "http",
			Error:   errorCode,
			Metrics: metrics,
			Meta:    tags,
		}
		serviceCount[span.Service]++
		finalTraces = append(finalTraces, ddspan)
	}

	if len(finalTraces) != 0 {
		// this endpoint is not documented to take an array... but it does
		// another curious constraint of this endpoint is that it does not
		// support "Content-Encoding: deflate"

		err := postHelper(context.TODO(), dd.HTTPClient, dd.stats, fmt.Sprintf("%s/spans", dd.traceAddress), finalTraces, "flush_traces", false)

		if err == nil {
			log.WithField("traces", len(finalTraces)).Info("Completed flushing traces to Datadog")
			dd.stats.Count(totalSpansFlushedMetricKey, int64(len(ssfSpans)), []string{"sink:datadog"}, 1)
			// TODO: Per service counters?
		} else {
			log.WithFields(logrus.Fields{
				"traces":        len(finalTraces),
				logrus.ErrorKey: err}).Warn("Error flushing traces to Datadog")
		}
		for service, count := range serviceCount {
			dd.stats.Count(totalSpansFlushedMetricKey, count, []string{"sink:datadog", fmt.Sprintf("service:%s", service)}, 1)
		}
	} else {
		log.Info("No traces to flush to Datadog, skipping.")
	}
}

// lightStepSpanSink is a sink for spans to be sent to the LightStep client.
type lightStepSpanSink struct {
	tracerPool   sync.Pool
	stats        *statsd.Client
	commonTags   map[string]string
	mutex        *sync.Mutex
	serviceCount map[string]int64
}

// NewLightStepSpanSink creates a new instance of a LightStepSpanSink.
func NewLightStepSpanSink(config *Config, stats *statsd.Client, commonTags map[string]string) (*lightStepSpanSink, error) {

	var host *url.URL
	host, err := url.Parse(config.TraceLightstepCollectorHost)
	if err != nil {
		log.WithError(err).WithField(
			"host", config.TraceLightstepCollectorHost,
		).Error("Error parsing LightStep collector URL")
		return &lightStepSpanSink{}, err
	}

	port, err := strconv.Atoi(host.Port())
	if err != nil {
		log.WithError(err).WithFields(logrus.Fields{
			"port":         port,
			"default_port": lightstepDefaultPort,
		}).Warn("Error parsing LightStep port, using default")
		port = lightstepDefaultPort
	}

	reconPeriod := lightstepDefaultInterval
	if config.TraceLightstepReconnectPeriod != "" {
		reconPeriod, err = time.ParseDuration(config.TraceLightstepReconnectPeriod)
		if err != nil {
			log.WithError(err).WithFields(logrus.Fields{
				"interval":         config.TraceLightstepReconnectPeriod,
				"default_interval": lightstepDefaultInterval,
			}).Warn("Failed to parse reconnect duration, using default.")
			reconPeriod = lightstepDefaultInterval
		}
	}

	log.WithFields(logrus.Fields{
		"Host": host.Hostname(),
		"Port": port,
	}).Info("Dialing lightstep host")

	maxSpans := config.TraceLightstepMaximumSpans
	if maxSpans == 0 {
		maxSpans = config.SsfBufferSize
		log.WithField("max spans", maxSpans).Info("Using default maximum spans — ssf_buffer_size — for LightStep")
	}

	p := sync.Pool{
		New: func() interface{} {
			stats.Incr("tracer.pool.new", nil, 1.0)
			return lightstep.NewTracer(lightstep.Options{
				AccessToken:     config.TraceLightstepAccessToken,
				ReconnectPeriod: reconPeriod,
				Collector: lightstep.Endpoint{
					Host:      host.Hostname(),
					Port:      port,
					Plaintext: true,
				},
				UseGRPC:          true,
				MaxBufferedSpans: maxSpans,
			})
		},
	}

	return &lightStepSpanSink{
		tracerPool:   p,
		stats:        stats,
		serviceCount: make(map[string]int64),
		mutex:        &sync.Mutex{},
	}, nil
}

// Name returns this sink's name.
func (ls *lightStepSpanSink) Name() string {
	return "lightstep"
}

// Ingest takes in a span and passed it along to the LS client after
// some sanity checks and improvements are made.
func (ls *lightStepSpanSink) Ingest(ssfSpan ssf.SSFSpan) error {
	parentID := ssfSpan.ParentId
	if parentID <= 0 {
		parentID = 0
	}

	var errorCode int64
	if ssfSpan.Error {
		errorCode = 1
	}

	timestamp := time.Unix(ssfSpan.StartTimestamp/1e9, ssfSpan.StartTimestamp%1e9)
	tracer := ls.tracerPool.Get().(opentracing.Tracer)
	defer ls.tracerPool.Put(tracer)
	sp := tracer.StartSpan(
		ssfSpan.Name,
		opentracing.StartTime(timestamp),
		lightstep.SetTraceID(uint64(ssfSpan.TraceId)),
		lightstep.SetSpanID(uint64(ssfSpan.Id)),
		lightstep.SetParentSpanID(uint64(parentID)))

	sp.SetTag(trace.ResourceKey, ssfSpan.Tags[trace.ResourceKey]) // TODO Why is this here?
	sp.SetTag(lightstep.ComponentNameKey, ssfSpan.Service)
	// TODO don't hardcode
	sp.SetTag("type", "http")
	sp.SetTag("error-code", errorCode)
	for k, v := range ssfSpan.Tags {
		sp.SetTag(k, v)
	}
	// And now set any veneur common tags
	for k, v := range ls.commonTags {
		sp.SetTag(k, v)
	}
	// TODO add metrics as tags to the span as well?

	if errorCode > 0 {
		// Note: this sets the OT-standard "error" tag, which
		// LightStep uses to flag error spans.
		ext.Error.Set(sp, true)
	}

	endTime := time.Unix(ssfSpan.EndTimestamp/1e9, ssfSpan.EndTimestamp%1e9)
	sp.FinishWithOptions(opentracing.FinishOptions{
		FinishTime: endTime,
	})

	service := ssfSpan.Service
	if service == "" {
		service = "unknown"
	}

	// Protect mutating the service count with a mutex
	ls.mutex.Lock()
	defer ls.mutex.Unlock()
	ls.serviceCount[service]++

	return nil
}

// Flush doesn't need to do anything to the LS tracer, so we emit metrics
// instead.
func (ls *lightStepSpanSink) Flush() {
	ls.mutex.Lock()
	defer ls.mutex.Unlock()

	totalCount := int64(0)
	for service, count := range ls.serviceCount {
		totalCount += count
		ls.stats.Count(totalSpansFlushedMetricKey, count, []string{"sink:lightstep", fmt.Sprintf("service:%s", service)}, 1)
	}
	ls.serviceCount = make(map[string]int64)
	log.WithField("total_spans", totalCount).Debug("Checkpointing flushed spans for Lightstep")
}
<commit_msg>Use modular division to multiplex by TraceID<commit_after>package veneur

import (
	"container/ring"
	"context"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
	"sync"
	"time"

	"github.com/DataDog/datadog-go/statsd"
	lightstep "github.com/lightstep/lightstep-tracer-go"
	opentracing "github.com/opentracing/opentracing-go"
	"github.com/opentracing/opentracing-go/ext"
	"github.com/sirupsen/logrus"
	"github.com/stripe/veneur/ssf"
	"github.com/stripe/veneur/trace"
)

const datadogResourceKey = "resource"
const datadogNameKey = "name"

const lightStepOperationKey = "name"
const lightstepMultiplexTracerNum = 10

const totalSpansFlushedMetricKey = "worker.spans_flushed_total"

// spanSink is a receiver of spans that handles sending those spans to some
// downstream sink. Calls to `Ingest(span)` are meant to give the sink control
// of the span, with periodic calls to flush as a signal for sinks that don't
// handle their own flushing in a separate goroutine, etc.
type spanSink interface {
	Name() string
	Ingest(ssf.SSFSpan) error
	Flush()
}

// DatadogSpanSink is a sink for sending spans to a Datadog trace agent.
type datadogSpanSink struct {
	HTTPClient   *http.Client
	buffer       *ring.Ring
	bufferSize   int
	mutex        *sync.Mutex
	stats        *statsd.Client
	commonTags   map[string]string
	traceAddress string
}

// NewDatadogSpanSink creates a new Datadog sink for trace spans.
func NewDatadogSpanSink(config *Config, stats *statsd.Client, httpClient *http.Client, commonTags map[string]string) (*datadogSpanSink, error) {
	return &datadogSpanSink{
		HTTPClient:   httpClient,
		bufferSize:   config.SsfBufferSize,
		buffer:       ring.New(config.SsfBufferSize),
		mutex:        &sync.Mutex{},
		stats:        stats,
		commonTags:   commonTags,
		traceAddress: config.DatadogTraceAPIAddress,
	}, nil
}

// Name returns the name of this sink.
func (dd *datadogSpanSink) Name() string {
	return "datadog"
}

// Ingest takes the span and adds it to the ringbuffer.
func (dd *datadogSpanSink) Ingest(span ssf.SSFSpan) error {
	dd.mutex.Lock()
	defer dd.mutex.Unlock()

	dd.buffer.Value = span
	dd.buffer = dd.buffer.Next()
	return nil
}

// Flush signals the sink to send it's spans to their destination. For this
// sync it means we'll be making an HTTP request to send them along. We assume
// it's beneficial to performance to defer these until the normal 10s flush.
func (dd *datadogSpanSink) Flush() {
	dd.mutex.Lock()

	ssfSpans := make([]ssf.SSFSpan, 0, dd.buffer.Len())

	dd.buffer.Do(func(t interface{}) {
		const tooEarly = 1497
		const tooLate = 1497629343000000

		if t != nil {
			ssfSpan, ok := t.(ssf.SSFSpan)
			if !ok {
				log.Error("Got an unknown object in tracing ring!")
				// We'll just skip this one so we don't poison pill or anything.
				return
			}

			var timeErr string
			if ssfSpan.StartTimestamp < tooEarly {
				timeErr = "type:tooEarly"
			}
			if ssfSpan.StartTimestamp > tooLate {
				timeErr = "type:tooLate"
			}
			if timeErr != "" {
				dd.stats.Incr("worker.trace.sink.timestamp_error", []string{timeErr}, 1) // TODO tag as dd?
			}

			if ssfSpan.Tags == nil {
				ssfSpan.Tags = make(map[string]string)
			}

			// Add common tags from veneur's config
			// this will overwrite tags already present on the span
			for k, v := range dd.commonTags {
				ssfSpan.Tags[k] = v
			}
			ssfSpans = append(ssfSpans, ssfSpan)
		}
	})

	// Reset the ring.
	dd.buffer = ring.New(dd.bufferSize)

	// We're done manipulating stuff, let Ingest loose again.
	dd.mutex.Unlock()

	serviceCount := make(map[string]int64)
	var finalTraces []*DatadogTraceSpan
	// Conver the SSFSpans into Datadog Spans
	for _, span := range ssfSpans {
		// -1 is a canonical way of passing in invalid info in Go
		// so we should support that too
		parentID := span.ParentId

		// check if this is the root span
		if parentID <= 0 {
			// we need parentId to be zero for json:omitempty to work
			parentID = 0
		}

		resource := span.Tags[datadogResourceKey]
		name := span.Name

		tags := map[string]string{}
		// Get the span's existing tags
		for k, v := range span.Tags {
			tags[k] = v
		}

		delete(tags, datadogResourceKey)

		// TODO implement additional metrics
		var metrics map[string]float64

		var errorCode int64
		if span.Error {
			errorCode = 2
		}

		ddspan := &DatadogTraceSpan{
			TraceID:  span.TraceId,
			SpanID:   span.Id,
			ParentID: parentID,
			Service:  span.Service,
			Name:     name,
			Resource: resource,
			Start:    span.StartTimestamp,
			Duration: span.EndTimestamp - span.StartTimestamp,
			// TODO don't hardcode
			Type:    "http",
			Error:   errorCode,
			Metrics: metrics,
			Meta:    tags,
		}
		serviceCount[span.Service]++
		finalTraces = append(finalTraces, ddspan)
	}

	if len(finalTraces) != 0 {
		// this endpoint is not documented to take an array... but it does
		// another curious constraint of this endpoint is that it does not
		// support "Content-Encoding: deflate"

		err := postHelper(context.TODO(), dd.HTTPClient, dd.stats, fmt.Sprintf("%s/spans", dd.traceAddress), finalTraces, "flush_traces", false)

		if err == nil {
			log.WithField("traces", len(finalTraces)).Info("Completed flushing traces to Datadog")
			dd.stats.Count(totalSpansFlushedMetricKey, int64(len(ssfSpans)), []string{"sink:datadog"}, 1)
			// TODO: Per service counters?
		} else {
			log.WithFields(logrus.Fields{
				"traces":        len(finalTraces),
				logrus.ErrorKey: err}).Warn("Error flushing traces to Datadog")
		}
		for service, count := range serviceCount {
			dd.stats.Count(totalSpansFlushedMetricKey, count, []string{"sink:datadog", fmt.Sprintf("service:%s", service)}, 1)
		}
	} else {
		log.Info("No traces to flush to Datadog, skipping.")
	}
}

// lightStepSpanSink is a sink for spans to be sent to the LightStep client.
type lightStepSpanSink struct {
	tracers      []opentracing.Tracer
	stats        *statsd.Client
	commonTags   map[string]string
	mutex        *sync.Mutex
	serviceCount map[string]int64
}

// NewLightStepSpanSink creates a new instance of a LightStepSpanSink.
func NewLightStepSpanSink(config *Config, stats *statsd.Client, commonTags map[string]string) (*lightStepSpanSink, error) {

	var host *url.URL
	host, err := url.Parse(config.TraceLightstepCollectorHost)
	if err != nil {
		log.WithError(err).WithField(
			"host", config.TraceLightstepCollectorHost,
		).Error("Error parsing LightStep collector URL")
		return &lightStepSpanSink{}, err
	}

	port, err := strconv.Atoi(host.Port())
	if err != nil {
		log.WithError(err).WithFields(logrus.Fields{
			"port":         port,
			"default_port": lightstepDefaultPort,
		}).Warn("Error parsing LightStep port, using default")
		port = lightstepDefaultPort
	}

	reconPeriod := lightstepDefaultInterval
	if config.TraceLightstepReconnectPeriod != "" {
		reconPeriod, err = time.ParseDuration(config.TraceLightstepReconnectPeriod)
		if err != nil {
			log.WithError(err).WithFields(logrus.Fields{
				"interval":         config.TraceLightstepReconnectPeriod,
				"default_interval": lightstepDefaultInterval,
			}).Warn("Failed to parse reconnect duration, using default.")
			reconPeriod = lightstepDefaultInterval
		}
	}

	log.WithFields(logrus.Fields{
		"Host": host.Hostname(),
		"Port": port,
	}).Info("Dialing lightstep host")

	maxSpans := config.TraceLightstepMaximumSpans
	if maxSpans == 0 {
		maxSpans = config.SsfBufferSize
		log.WithField("max spans", maxSpans).Info("Using default maximum spans — ssf_buffer_size — for LightStep")
	}

	tracers := make([]opentracing.Tracer, 0, lightstepMultiplexTracerNum)

	for _, _ = range tracers {
		tracers = append(tracers, lightstep.NewTracer(lightstep.Options{
			AccessToken:     config.TraceLightstepAccessToken,
			ReconnectPeriod: reconPeriod,
			Collector: lightstep.Endpoint{
				Host:      host.Hostname(),
				Port:      port,
				Plaintext: true,
			},
			UseGRPC:          true,
			MaxBufferedSpans: maxSpans,
		}))
	}

	return &lightStepSpanSink{
		tracers:      tracers,
		stats:        stats,
		serviceCount: make(map[string]int64),
		mutex:        &sync.Mutex{},
	}, nil
}

// Name returns this sink's name.
func (ls *lightStepSpanSink) Name() string {
	return "lightstep"
}

// Ingest takes in a span and passed it along to the LS client after
// some sanity checks and improvements are made.
func (ls *lightStepSpanSink) Ingest(ssfSpan ssf.SSFSpan) error {
	parentID := ssfSpan.ParentId
	if parentID <= 0 {
		parentID = 0
	}

	var errorCode int64
	if ssfSpan.Error {
		errorCode = 1
	}

	timestamp := time.Unix(ssfSpan.StartTimestamp/1e9, ssfSpan.StartTimestamp%1e9)

	// pick the tracer to use
	tracerIndex := ssfSpan.TraceId % int64(len(ls.tracers))
	tracer := ls.tracers[tracerIndex]

	sp := tracer.StartSpan(
		ssfSpan.Name,
		opentracing.StartTime(timestamp),
		lightstep.SetTraceID(uint64(ssfSpan.TraceId)),
		lightstep.SetSpanID(uint64(ssfSpan.Id)),
		lightstep.SetParentSpanID(uint64(parentID)))

	sp.SetTag(trace.ResourceKey, ssfSpan.Tags[trace.ResourceKey]) // TODO Why is this here?
	sp.SetTag(lightstep.ComponentNameKey, ssfSpan.Service)
	// TODO don't hardcode
	sp.SetTag("type", "http")
	sp.SetTag("error-code", errorCode)
	for k, v := range ssfSpan.Tags {
		sp.SetTag(k, v)
	}
	// And now set any veneur common tags
	for k, v := range ls.commonTags {
		sp.SetTag(k, v)
	}
	// TODO add metrics as tags to the span as well?

	if errorCode > 0 {
		// Note: this sets the OT-standard "error" tag, which
		// LightStep uses to flag error spans.
		ext.Error.Set(sp, true)
	}

	endTime := time.Unix(ssfSpan.EndTimestamp/1e9, ssfSpan.EndTimestamp%1e9)
	sp.FinishWithOptions(opentracing.FinishOptions{
		FinishTime: endTime,
	})

	service := ssfSpan.Service
	if service == "" {
		service = "unknown"
	}

	// Protect mutating the service count with a mutex
	ls.mutex.Lock()
	defer ls.mutex.Unlock()
	ls.serviceCount[service]++

	return nil
}

// Flush doesn't need to do anything to the LS tracer, so we emit metrics
// instead.
func (ls *lightStepSpanSink) Flush() {
	ls.mutex.Lock()
	defer ls.mutex.Unlock()

	totalCount := int64(0)
	for service, count := range ls.serviceCount {
		totalCount += count
		ls.stats.Count(totalSpansFlushedMetricKey, count, []string{"sink:lightstep", fmt.Sprintf("service:%s", service)}, 1)
	}
	ls.serviceCount = make(map[string]int64)
	log.WithField("total_spans", totalCount).Debug("Checkpointing flushed spans for Lightstep")
}
<|endoftext|>


<commit_before>// Copyright 2017 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.

package termui

// Sparkline is like: ▅▆▂▂▅▇▂▂▃▆▆▆▅▃. The data points should be non-negative integers.
/*
  data := []int{4, 2, 1, 6, 3, 9, 1, 4, 2, 15, 14, 9, 8, 6, 10, 13, 15, 12, 10, 5, 3, 6, 1}
  spl := termui.NewSparkline()
  spl.Data = data
  spl.Title = "Sparkline 0"
  spl.LineColor = termui.ColorGreen
*/
type Sparkline struct {
	Data          []int
	Height        int
	Title         string
	TitleColor    Attribute
	LineColor     Attribute
	displayHeight int
	scale         float32
	max           int
}

// Sparklines is a renderable widget which groups together the given sparklines.
/*
  spls := termui.NewSparklines(spl0,spl1,spl2) //...
  spls.Height = 2
  spls.Width = 20
*/
type Sparklines struct {
	Block
	Lines        []Sparkline
	displayLines int
	displayWidth int
}

var sparks = []rune{'▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'}

// Add appends a given Sparkline to s *Sparklines.
func (s *Sparklines) Add(sl Sparkline) {
	s.Lines = append(s.Lines, sl)
}

// NewSparkline returns a unrenderable single sparkline that intended to be added into Sparklines.
func NewSparkline() Sparkline {
	return Sparkline{
		Height:     1,
		TitleColor: ThemeAttr("sparkline.title.fg"),
		LineColor:  ThemeAttr("sparkline.line.fg")}
}

// NewSparklines return a new *Spaklines with given Sparkline(s), you can always add a new Sparkline later.
func NewSparklines(ss ...Sparkline) *Sparklines {
	s := &Sparklines{Block: *NewBlock(), Lines: ss}
	return s
}

func (sl *Sparklines) update() {
	for i, v := range sl.Lines {
		if v.Title == "" {
			sl.Lines[i].displayHeight = v.Height
		} else {
			sl.Lines[i].displayHeight = v.Height + 1
		}
	}
	sl.displayWidth = sl.innerArea.Dx()

	// get how many lines gotta display
	h := 0
	sl.displayLines = 0
	for _, v := range sl.Lines {
		if h+v.displayHeight <= sl.innerArea.Dy() {
			sl.displayLines++
		} else {
			break
		}
		h += v.displayHeight
	}

	for i := 0; i < sl.displayLines; i++ {
		data := sl.Lines[i].Data

		max := 0
		for _, v := range data {
			if max < v {
				max = v
			}
		}
		sl.Lines[i].max = max
		if max != 0 {
			sl.Lines[i].scale = float32(8*sl.Lines[i].Height) / float32(max)
		} else { // when all negative
			sl.Lines[i].scale = 0
		}
	}
}

// Buffer implements Bufferer interface.
func (sl *Sparklines) Buffer() Buffer {
	buf := sl.Block.Buffer()
	sl.update()

	oftY := 0
	for i := 0; i < sl.displayLines; i++ {
		l := sl.Lines[i]
		data := l.Data

		if len(data) > sl.innerArea.Dx() {
			data = data[len(data)-sl.innerArea.Dx():]
		}

		if l.Title != "" {
			rs := trimStr2Runes(l.Title, sl.innerArea.Dx())
			oftX := 0
			for _, v := range rs {
				w := charWidth(v)
				c := Cell{
					Ch: v,
					Fg: l.TitleColor,
					Bg: sl.Bg,
				}
				x := sl.innerArea.Min.X + oftX
				y := sl.innerArea.Min.Y + oftY
				buf.Set(x, y, c)
				oftX += w
			}
		}

		for j, v := range data {
			// display height of the data point, zero when data is negative
			h := int(float32(v)*l.scale + 0.5)
			if v < 0 {
				h = 0
			}

			barCnt := h / 8
			barMod := h % 8
			for jj := 0; jj < barCnt; jj++ {
				c := Cell{
					Ch: ' ', // => sparks[7]
					Bg: l.LineColor,
				}
				x := sl.innerArea.Min.X + j
				y := sl.innerArea.Min.Y + oftY + l.Height - jj

				//p.Bg = sl.BgColor
				buf.Set(x, y, c)
			}
			if barMod != 0 {
				c := Cell{
					Ch: sparks[barMod-1],
					Fg: l.LineColor,
					Bg: sl.Bg,
				}
				x := sl.innerArea.Min.X + j
				y := sl.innerArea.Min.Y + oftY + l.Height - barCnt
				buf.Set(x, y, c)
			}
		}

		oftY += l.displayHeight
	}

	return buf
}
<commit_msg>spelling: sparklines<commit_after>// Copyright 2017 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.

package termui

// Sparkline is like: ▅▆▂▂▅▇▂▂▃▆▆▆▅▃. The data points should be non-negative integers.
/*
  data := []int{4, 2, 1, 6, 3, 9, 1, 4, 2, 15, 14, 9, 8, 6, 10, 13, 15, 12, 10, 5, 3, 6, 1}
  spl := termui.NewSparkline()
  spl.Data = data
  spl.Title = "Sparkline 0"
  spl.LineColor = termui.ColorGreen
*/
type Sparkline struct {
	Data          []int
	Height        int
	Title         string
	TitleColor    Attribute
	LineColor     Attribute
	displayHeight int
	scale         float32
	max           int
}

// Sparklines is a renderable widget which groups together the given sparklines.
/*
  spls := termui.NewSparklines(spl0,spl1,spl2) //...
  spls.Height = 2
  spls.Width = 20
*/
type Sparklines struct {
	Block
	Lines        []Sparkline
	displayLines int
	displayWidth int
}

var sparks = []rune{'▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'}

// Add appends a given Sparkline to s *Sparklines.
func (s *Sparklines) Add(sl Sparkline) {
	s.Lines = append(s.Lines, sl)
}

// NewSparkline returns a unrenderable single sparkline that intended to be added into Sparklines.
func NewSparkline() Sparkline {
	return Sparkline{
		Height:     1,
		TitleColor: ThemeAttr("sparkline.title.fg"),
		LineColor:  ThemeAttr("sparkline.line.fg")}
}

// NewSparklines return a new *Sparklines with given Sparkline(s), you can always add a new Sparkline later.
func NewSparklines(ss ...Sparkline) *Sparklines {
	s := &Sparklines{Block: *NewBlock(), Lines: ss}
	return s
}

func (sl *Sparklines) update() {
	for i, v := range sl.Lines {
		if v.Title == "" {
			sl.Lines[i].displayHeight = v.Height
		} else {
			sl.Lines[i].displayHeight = v.Height + 1
		}
	}
	sl.displayWidth = sl.innerArea.Dx()

	// get how many lines gotta display
	h := 0
	sl.displayLines = 0
	for _, v := range sl.Lines {
		if h+v.displayHeight <= sl.innerArea.Dy() {
			sl.displayLines++
		} else {
			break
		}
		h += v.displayHeight
	}

	for i := 0; i < sl.displayLines; i++ {
		data := sl.Lines[i].Data

		max := 0
		for _, v := range data {
			if max < v {
				max = v
			}
		}
		sl.Lines[i].max = max
		if max != 0 {
			sl.Lines[i].scale = float32(8*sl.Lines[i].Height) / float32(max)
		} else { // when all negative
			sl.Lines[i].scale = 0
		}
	}
}

// Buffer implements Bufferer interface.
func (sl *Sparklines) Buffer() Buffer {
	buf := sl.Block.Buffer()
	sl.update()

	oftY := 0
	for i := 0; i < sl.displayLines; i++ {
		l := sl.Lines[i]
		data := l.Data

		if len(data) > sl.innerArea.Dx() {
			data = data[len(data)-sl.innerArea.Dx():]
		}

		if l.Title != "" {
			rs := trimStr2Runes(l.Title, sl.innerArea.Dx())
			oftX := 0
			for _, v := range rs {
				w := charWidth(v)
				c := Cell{
					Ch: v,
					Fg: l.TitleColor,
					Bg: sl.Bg,
				}
				x := sl.innerArea.Min.X + oftX
				y := sl.innerArea.Min.Y + oftY
				buf.Set(x, y, c)
				oftX += w
			}
		}

		for j, v := range data {
			// display height of the data point, zero when data is negative
			h := int(float32(v)*l.scale + 0.5)
			if v < 0 {
				h = 0
			}

			barCnt := h / 8
			barMod := h % 8
			for jj := 0; jj < barCnt; jj++ {
				c := Cell{
					Ch: ' ', // => sparks[7]
					Bg: l.LineColor,
				}
				x := sl.innerArea.Min.X + j
				y := sl.innerArea.Min.Y + oftY + l.Height - jj

				//p.Bg = sl.BgColor
				buf.Set(x, y, c)
			}
			if barMod != 0 {
				c := Cell{
					Ch: sparks[barMod-1],
					Fg: l.LineColor,
					Bg: sl.Bg,
				}
				x := sl.innerArea.Min.X + j
				y := sl.innerArea.Min.Y + oftY + l.Height - barCnt
				buf.Set(x, y, c)
			}
		}

		oftY += l.displayHeight
	}

	return buf
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 integration_test

import (
	"testing"

	. "github.com/jacobsa/ogletest"
)

func TestGcsfuse(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type GcsfuseTest struct {
}

func init() { RegisterTestSuite(&GcsfuseTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *GcsfuseTest) DoesFoo() {
	AssertTrue(false, "TODO")
}
<commit_msg>Added test names.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 integration_test

import (
	"testing"

	. "github.com/jacobsa/ogletest"
)

func TestGcsfuse(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type GcsfuseTest struct {
}

func init() { RegisterTestSuite(&GcsfuseTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *GcsfuseTest) BadUsage() {
	AssertTrue(false, "TODO")
}

func (t *GcsfuseTest) ErrorOpeningBucket() {
	AssertTrue(false, "TODO")
}

func (t *GcsfuseTest) ReadOnlyMode() {
	AssertTrue(false, "TODO")
}

func (t *GcsfuseTest) ReadWriteMode() {
	AssertTrue(false, "TODO")
}

func (t *GcsfuseTest) FileAndDirModeFlags() {
	AssertTrue(false, "TODO")
}

func (t *GcsfuseTest) UidAndGidFlags() {
	AssertTrue(false, "TODO")
}

func (t *GcsfuseTest) ImplicitDirs() {
	AssertTrue(false, "TODO")
}

func (t *GcsfuseTest) VersionFlags() {
	AssertTrue(false, "TODO")
}

func (t *GcsfuseTest) HelpFlags() {
	AssertTrue(false, "TODO")
}
<|endoftext|>


<commit_before>package runid

import (
	"context"
	"database/sql"

	"github.com/anacrolix/missinggo/expect"
)

type T int64

func New(db *sql.DB) (ret *T) {
	ctx := context.Background()
	conn, err := db.Conn(ctx)
	expect.Nil(err)
	defer func() {
		expect.Nil(conn.Close())
	}()
	res, err := conn.ExecContext(ctx, "insert into runs default values")
	expect.Nil(err)
	expect.OneRowAffected(res)
	expect.Nil(conn.QueryRowContext(ctx, "select last_insert_rowid()").Scan(&ret))
	return
}
<commit_msg>runid: Create the runs table if it doesn't exist<commit_after>package runid

import (
	"context"
	"database/sql"

	"github.com/anacrolix/missinggo/expect"
)

type T int64

func New(db *sql.DB) (ret *T) {
	ctx := context.Background()
	conn, err := db.Conn(ctx)
	expect.Nil(err)
	defer func() {
		expect.Nil(conn.Close())
	}()
	_, err = conn.ExecContext(ctx, `CREATE TABLE if not exists runs (started datetime default (datetime('now')))`)
	expect.Nil(err)
	res, err := conn.ExecContext(ctx, "insert into runs default values")
	expect.Nil(err)
	expect.OneRowAffected(res)
	expect.Nil(conn.QueryRowContext(ctx, "select last_insert_rowid()").Scan(&ret))
	return
}
<|endoftext|>


<commit_before>package runner

import (
	"errors"
	"fmt"
	"io"
	"reflect"
	"runtime"
	"syscall"
	"unsafe"

	"github.com/tsavola/wag/internal/imports"
	"github.com/tsavola/wag/internal/types"
	"github.com/tsavola/wag/traps"
)

func run(text []byte, initialMemorySize int, memory, stack []byte, stackOffset, resumeResult, arg, slaveFd int) (result int32, trap int, currentMemorySize int, stackPtr uintptr)

func importSnapshot() int64
func importSpectestPrint() int64

const (
	memoryIncrementSize = 65536
)

var (
	systemPageSize = syscall.Getpagesize()
)

var Imports = map[string]map[string]imports.Function{
	"spectest": {
		"print": imports.Function{
			Variadic: true,
			Address:  importSpectestPrint(),
		},
	},
	"wag": {
		"snapshot": imports.Function{
			Function: types.Function{
				Result: types.I32,
			},
			Address: importSnapshot(),
		},
	},
}

type Buffer struct {
	Text   []byte
	ROData []byte
}

func NewBuffer(maxTextSize, maxRODataSize int) (b *Buffer, err error) {
	b = &Buffer{}

	b.Text, err = makeMemory(maxTextSize, syscall.PROT_EXEC, syscall.MAP_32BIT)
	if err != nil {
		b.Close()
		return
	}

	b.ROData, err = makeMemory(maxRODataSize, 0, syscall.MAP_32BIT)
	if err != nil {
		b.Close()
		return
	}

	return
}

func (b *Buffer) RODataAddr() int32 {
	addr := (*reflect.SliceHeader)(unsafe.Pointer(&b.ROData)).Data
	if addr == 0 || addr > 0x7fffffff-uintptr(len(b.ROData)) {
		panic("sanity check failed")
	}
	return int32(addr)
}

func (b *Buffer) Seal() (err error) {
	if b.Text != nil {
		err = syscall.Mprotect(b.Text, syscall.PROT_EXEC|syscall.PROT_READ)
		if err != nil {
			return
		}
	}

	if b.ROData != nil {
		err = syscall.Mprotect(b.ROData, syscall.PROT_READ)
		if err != nil {
			return
		}
	}

	return
}

func (b *Buffer) Close() (first error) {
	if b.Text != nil {
		if err := syscall.Munmap(b.Text); err != nil && first == nil {
			first = err
		}
	}

	if b.ROData != nil {
		if err := syscall.Munmap(b.ROData); err != nil && first == nil {
			first = err
		}
	}

	return
}

type runnable interface {
	getText() []byte
	getGlobals() []byte
	getData() []byte
	getStack() []byte
	writeStacktraceTo(w io.Writer, stack []byte) error
	exportStack(native []byte) (portable []byte, err error)
}

type Program struct {
	buf *Buffer

	globals   []byte
	data      []byte
	funcTypes []types.Function
	funcNames []string

	funcMap []byte
	callMap []byte

	funcAddrs map[int]int
	callSites map[int]callSite
}

func (b *Buffer) NewProgram(globals, data []byte, funcTypes []types.Function, funcNames []string) *Program {
	return &Program{
		buf:       b,
		globals:   globals,
		data:      data,
		funcTypes: funcTypes,
		funcNames: funcNames,
	}
}

func (p *Program) SetMaps(funcMap, callMap []byte) {
	p.funcMap = funcMap
	p.callMap = callMap
}

func (p *Program) getText() []byte {
	return p.buf.Text
}

func (p *Program) getGlobals() []byte {
	return p.globals
}

func (p *Program) getData() []byte {
	return p.data
}

func (p *Program) getStack() []byte {
	return nil
}

type Runner struct {
	prog runnable

	globalsOffset int
	memoryOffset  int
	memorySize    int
	globalsMemory []byte
	stack         []byte

	lastTrap     traps.Id
	lastStackPtr uintptr

	Snapshots []*Snapshot
}

func (p *Program) NewRunner(initMemorySize, growMemorySize, stackSize int) (r *Runner, err error) {
	return newRunner(p, initMemorySize, growMemorySize, stackSize)
}

func newRunner(prog runnable, initMemorySize, growMemorySize, stackSize int) (r *Runner, err error) {
	if (initMemorySize & (memoryIncrementSize - 1)) != 0 {
		err = fmt.Errorf("initial memory size is not multiple of %d", memoryIncrementSize)
		return
	}
	if (growMemorySize & (memoryIncrementSize - 1)) != 0 {
		err = fmt.Errorf("memory growth limit is not multiple of %d", memoryIncrementSize)
		return
	}

	if initMemorySize < len(prog.getData()) {
		err = errors.New("data does not fit in initial memory")
		return
	}
	if initMemorySize > growMemorySize {
		err = errors.New("initial memory exceeds memory growth limit")
		return
	}

	if initMemorySize > 0x7fffffff {
		err = errors.New("initial memory size must be below 2 GB")
		return
	}
	if growMemorySize > 0x7fffffff {
		err = errors.New("memory growth limit must be below 2 GB")
		return
	}

	padding := (systemPageSize - len(prog.getGlobals())) & (systemPageSize - 1)

	r = &Runner{
		prog:          prog,
		globalsOffset: padding,
		memoryOffset:  padding + len(prog.getGlobals()),
		memorySize:    initMemorySize,
	}

	r.globalsMemory, err = makeMemory(r.globalsOffset+growMemorySize, 0, 0)
	if err != nil {
		r.Close()
		return
	}

	r.stack, err = makeMemory(stackSize, 0, 0)
	if err != nil {
		r.Close()
		return
	}

	copy(r.globalsMemory[r.globalsOffset:], r.prog.getGlobals())
	copy(r.globalsMemory[r.memoryOffset:], r.prog.getData())
	return
}

func (r *Runner) Close() (first error) {
	if r.stack != nil {
		if err := syscall.Munmap(r.stack); err != nil && first == nil {
			first = err
		}
	}

	if r.globalsMemory != nil {
		if err := syscall.Munmap(r.globalsMemory); err != nil && first == nil {
			first = err
		}
	}

	return
}

func (r *Runner) Run(arg int, sigs map[int64]types.Function, printer io.Writer) (result int32, err error) {
	e := Executor{
		runner:  r,
		arg:     arg,
		sigs:    sigs,
		printer: printer,
	}
	e.run()
	result = e.result
	err = e.err
	return
}

type Executor struct {
	runner *Runner

	arg     int
	sigs    map[int64]types.Function
	printer io.Writer

	cont chan struct{}
	done chan struct{}

	result int32
	err    error
}

func (r *Runner) NewExecutor(arg int, sigs map[int64]types.Function, printer io.Writer) (e *Executor, trigger chan<- struct{}) {
	e = &Executor{
		runner:  r,
		arg:     arg,
		sigs:    sigs,
		printer: printer,
		cont:    make(chan struct{}),
		done:    make(chan struct{}),
	}

	start := make(chan struct{})

	go func() {
		<-start
		fmt.Fprintf(e.printer, "--- execution starting ---\n")
		defer close(e.done)
		e.run()
	}()

	trigger = start
	return
}

func (e *Executor) Wait() (result int32, err error) {
	fmt.Fprintf(e.printer, "--- executable complete ---\n")
	close(e.cont)

	<-e.done
	fmt.Fprintf(e.printer, "--- execution finished ---\n")

	result = e.result
	err = e.err
	return
}

func (e *Executor) run() {
	stackState := e.runner.prog.getStack()
	stackOffset := len(e.runner.stack) - len(stackState)
	copy(e.runner.stack[stackOffset:], stackState)

	resumeResult := 0 // don't resume
	if len(stackState) > 0 {
		resumeResult = -1 // resume; return this value to snapshot function caller
	}

	fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0)
	if err != nil {
		return
	}

	done := make(chan struct{})

	defer func() {
		syscall.Close(fds[1])
		<-done
	}()

	go func() {
		defer close(done)
		e.slave(fds[0], e.sigs, e.printer, e.cont)
	}()

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	memory := e.runner.globalsMemory[e.runner.memoryOffset:]

	result, trap, memorySize, stackPtr := run(e.runner.prog.getText(), e.runner.memorySize, memory, e.runner.stack, stackOffset, resumeResult, e.arg, fds[1])

	e.runner.memorySize = memorySize
	e.runner.lastTrap = traps.Id(trap)
	e.runner.lastStackPtr = stackPtr

	if trap == 0 {
		e.result = result
	} else {
		e.err = e.runner.lastTrap
	}
	return
}

func makeMemory(size int, extraProt, extraFlags int) (mem []byte, err error) {
	if size == 0 {
		return
	}

	return syscall.Mmap(-1, 0, size, syscall.PROT_READ|syscall.PROT_WRITE|extraProt, syscall.MAP_PRIVATE|syscall.MAP_ANONYMOUS|extraFlags)
}
<commit_msg>runner: text doesn't need to be readable<commit_after>package runner

import (
	"errors"
	"fmt"
	"io"
	"reflect"
	"runtime"
	"syscall"
	"unsafe"

	"github.com/tsavola/wag/internal/imports"
	"github.com/tsavola/wag/internal/types"
	"github.com/tsavola/wag/traps"
)

func run(text []byte, initialMemorySize int, memory, stack []byte, stackOffset, resumeResult, arg, slaveFd int) (result int32, trap int, currentMemorySize int, stackPtr uintptr)

func importSnapshot() int64
func importSpectestPrint() int64

const (
	memoryIncrementSize = 65536
)

var (
	systemPageSize = syscall.Getpagesize()
)

var Imports = map[string]map[string]imports.Function{
	"spectest": {
		"print": imports.Function{
			Variadic: true,
			Address:  importSpectestPrint(),
		},
	},
	"wag": {
		"snapshot": imports.Function{
			Function: types.Function{
				Result: types.I32,
			},
			Address: importSnapshot(),
		},
	},
}

type Buffer struct {
	Text   []byte
	ROData []byte
}

func NewBuffer(maxTextSize, maxRODataSize int) (b *Buffer, err error) {
	b = &Buffer{}

	b.Text, err = makeMemory(maxTextSize, syscall.PROT_EXEC, syscall.MAP_32BIT)
	if err != nil {
		b.Close()
		return
	}

	b.ROData, err = makeMemory(maxRODataSize, 0, syscall.MAP_32BIT)
	if err != nil {
		b.Close()
		return
	}

	return
}

func (b *Buffer) RODataAddr() int32 {
	addr := (*reflect.SliceHeader)(unsafe.Pointer(&b.ROData)).Data
	if addr == 0 || addr > 0x7fffffff-uintptr(len(b.ROData)) {
		panic("sanity check failed")
	}
	return int32(addr)
}

func (b *Buffer) Seal() (err error) {
	if b.Text != nil {
		err = syscall.Mprotect(b.Text, syscall.PROT_EXEC)
		if err != nil {
			return
		}
	}

	if b.ROData != nil {
		err = syscall.Mprotect(b.ROData, syscall.PROT_READ)
		if err != nil {
			return
		}
	}

	return
}

func (b *Buffer) Close() (first error) {
	if b.Text != nil {
		if err := syscall.Munmap(b.Text); err != nil && first == nil {
			first = err
		}
	}

	if b.ROData != nil {
		if err := syscall.Munmap(b.ROData); err != nil && first == nil {
			first = err
		}
	}

	return
}

type runnable interface {
	getText() []byte
	getGlobals() []byte
	getData() []byte
	getStack() []byte
	writeStacktraceTo(w io.Writer, stack []byte) error
	exportStack(native []byte) (portable []byte, err error)
}

type Program struct {
	buf *Buffer

	globals   []byte
	data      []byte
	funcTypes []types.Function
	funcNames []string

	funcMap []byte
	callMap []byte

	funcAddrs map[int]int
	callSites map[int]callSite
}

func (b *Buffer) NewProgram(globals, data []byte, funcTypes []types.Function, funcNames []string) *Program {
	return &Program{
		buf:       b,
		globals:   globals,
		data:      data,
		funcTypes: funcTypes,
		funcNames: funcNames,
	}
}

func (p *Program) SetMaps(funcMap, callMap []byte) {
	p.funcMap = funcMap
	p.callMap = callMap
}

func (p *Program) getText() []byte {
	return p.buf.Text
}

func (p *Program) getGlobals() []byte {
	return p.globals
}

func (p *Program) getData() []byte {
	return p.data
}

func (p *Program) getStack() []byte {
	return nil
}

type Runner struct {
	prog runnable

	globalsOffset int
	memoryOffset  int
	memorySize    int
	globalsMemory []byte
	stack         []byte

	lastTrap     traps.Id
	lastStackPtr uintptr

	Snapshots []*Snapshot
}

func (p *Program) NewRunner(initMemorySize, growMemorySize, stackSize int) (r *Runner, err error) {
	return newRunner(p, initMemorySize, growMemorySize, stackSize)
}

func newRunner(prog runnable, initMemorySize, growMemorySize, stackSize int) (r *Runner, err error) {
	if (initMemorySize & (memoryIncrementSize - 1)) != 0 {
		err = fmt.Errorf("initial memory size is not multiple of %d", memoryIncrementSize)
		return
	}
	if (growMemorySize & (memoryIncrementSize - 1)) != 0 {
		err = fmt.Errorf("memory growth limit is not multiple of %d", memoryIncrementSize)
		return
	}

	if initMemorySize < len(prog.getData()) {
		err = errors.New("data does not fit in initial memory")
		return
	}
	if initMemorySize > growMemorySize {
		err = errors.New("initial memory exceeds memory growth limit")
		return
	}

	if initMemorySize > 0x7fffffff {
		err = errors.New("initial memory size must be below 2 GB")
		return
	}
	if growMemorySize > 0x7fffffff {
		err = errors.New("memory growth limit must be below 2 GB")
		return
	}

	padding := (systemPageSize - len(prog.getGlobals())) & (systemPageSize - 1)

	r = &Runner{
		prog:          prog,
		globalsOffset: padding,
		memoryOffset:  padding + len(prog.getGlobals()),
		memorySize:    initMemorySize,
	}

	r.globalsMemory, err = makeMemory(r.globalsOffset+growMemorySize, 0, 0)
	if err != nil {
		r.Close()
		return
	}

	r.stack, err = makeMemory(stackSize, 0, 0)
	if err != nil {
		r.Close()
		return
	}

	copy(r.globalsMemory[r.globalsOffset:], r.prog.getGlobals())
	copy(r.globalsMemory[r.memoryOffset:], r.prog.getData())
	return
}

func (r *Runner) Close() (first error) {
	if r.stack != nil {
		if err := syscall.Munmap(r.stack); err != nil && first == nil {
			first = err
		}
	}

	if r.globalsMemory != nil {
		if err := syscall.Munmap(r.globalsMemory); err != nil && first == nil {
			first = err
		}
	}

	return
}

func (r *Runner) Run(arg int, sigs map[int64]types.Function, printer io.Writer) (result int32, err error) {
	e := Executor{
		runner:  r,
		arg:     arg,
		sigs:    sigs,
		printer: printer,
	}
	e.run()
	result = e.result
	err = e.err
	return
}

type Executor struct {
	runner *Runner

	arg     int
	sigs    map[int64]types.Function
	printer io.Writer

	cont chan struct{}
	done chan struct{}

	result int32
	err    error
}

func (r *Runner) NewExecutor(arg int, sigs map[int64]types.Function, printer io.Writer) (e *Executor, trigger chan<- struct{}) {
	e = &Executor{
		runner:  r,
		arg:     arg,
		sigs:    sigs,
		printer: printer,
		cont:    make(chan struct{}),
		done:    make(chan struct{}),
	}

	start := make(chan struct{})

	go func() {
		<-start
		fmt.Fprintf(e.printer, "--- execution starting ---\n")
		defer close(e.done)
		e.run()
	}()

	trigger = start
	return
}

func (e *Executor) Wait() (result int32, err error) {
	fmt.Fprintf(e.printer, "--- executable complete ---\n")
	close(e.cont)

	<-e.done
	fmt.Fprintf(e.printer, "--- execution finished ---\n")

	result = e.result
	err = e.err
	return
}

func (e *Executor) run() {
	stackState := e.runner.prog.getStack()
	stackOffset := len(e.runner.stack) - len(stackState)
	copy(e.runner.stack[stackOffset:], stackState)

	resumeResult := 0 // don't resume
	if len(stackState) > 0 {
		resumeResult = -1 // resume; return this value to snapshot function caller
	}

	fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0)
	if err != nil {
		return
	}

	done := make(chan struct{})

	defer func() {
		syscall.Close(fds[1])
		<-done
	}()

	go func() {
		defer close(done)
		e.slave(fds[0], e.sigs, e.printer, e.cont)
	}()

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	memory := e.runner.globalsMemory[e.runner.memoryOffset:]

	result, trap, memorySize, stackPtr := run(e.runner.prog.getText(), e.runner.memorySize, memory, e.runner.stack, stackOffset, resumeResult, e.arg, fds[1])

	e.runner.memorySize = memorySize
	e.runner.lastTrap = traps.Id(trap)
	e.runner.lastStackPtr = stackPtr

	if trap == 0 {
		e.result = result
	} else {
		e.err = e.runner.lastTrap
	}
	return
}

func makeMemory(size int, extraProt, extraFlags int) (mem []byte, err error) {
	if size == 0 {
		return
	}

	return syscall.Mmap(-1, 0, size, syscall.PROT_READ|syscall.PROT_WRITE|extraProt, syscall.MAP_PRIVATE|syscall.MAP_ANONYMOUS|extraFlags)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"github.com/containous/traefik/acme"
	"github.com/containous/traefik/provider"
	"github.com/containous/traefik/types"
	"regexp"
	"strings"
	"time"
)

// TraefikConfiguration holds GlobalConfiguration and other stuff
type TraefikConfiguration struct {
	GlobalConfiguration
	ConfigFile string `short:"c" description:"Timeout in seconds. Duration to give active requests a chance to finish during hot-reloads"`
}

// GlobalConfiguration holds global configuration (with providers, etc.).
// It's populated from the traefik configuration file passed as an argument to the binary.
type GlobalConfiguration struct {
	GraceTimeOut              int64       `short:"g" description:"Configuration file to use (TOML)."`
	Debug                     bool
	AccessLogsFile            string      `description:"Access logs file"`
	TraefikLogsFile           string      `description:"Traefik logs file"`
	LogLevel                  string      `short:"l" description:"Log level"`
	EntryPoints               EntryPoints `description:"Entrypoints definition using format: --entryPoints='Name:http Address::8000 Redirect.EntryPoint:https' --entryPoints='Name:https Address::4442 TLS:tests/traefik.crt,tests/traefik.key'"`
	ACME                      *acme.ACME
	DefaultEntryPoints        DefaultEntryPoints `description:"Entrypoints to be used by frontends that do not specify any entrypoint"`
	ProvidersThrottleDuration time.Duration      `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time."`
	MaxIdleConnsPerHost       int                `description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host.  If zero, DefaultMaxIdleConnsPerHost is used"`
	Retry                     *Retry
	Docker                    *provider.Docker        `description:"Enable Docker backend"`
	File                      *provider.File          `description:"Enable File backend"`
	Web                       *WebProvider            `description:"Enable Web backend"`
	Marathon                  *provider.Marathon      `description:"Enable Marathon backend"`
	Consul                    *provider.Consul        `description:"Enable Consul backend"`
	ConsulCatalog             *provider.ConsulCatalog `description:"Enable Consul catalog backend"`
	Etcd                      *provider.Etcd          `description:"Enable Etcd backend"`
	Zookeeper                 *provider.Zookepper     `description:"Enable Zookeeper backend"`
	Boltdb                    *provider.BoltDb        `description:"Enable Boltdb backend"`
	Kubernetes                *provider.Kubernetes    `description:"Enable Kubernetes backend"`
}

// DefaultEntryPoints holds default entry points
type DefaultEntryPoints []string

// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (dep *DefaultEntryPoints) String() string {
	//TODO :
	return fmt.Sprintf("%#v", dep)
}

// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (dep *DefaultEntryPoints) Set(value string) error {
	entrypoints := strings.Split(value, ",")
	if len(entrypoints) == 0 {
		return errors.New("Bad DefaultEntryPoints format: " + value)
	}
	for _, entrypoint := range entrypoints {
		*dep = append(*dep, entrypoint)
	}
	return nil
}

// Get return the EntryPoints map
func (dep *DefaultEntryPoints) Get() interface{} { return DefaultEntryPoints(*dep) }

// SetValue sets the EntryPoints map with val
func (dep *DefaultEntryPoints) SetValue(val interface{}) {
	*dep = DefaultEntryPoints(val.(DefaultEntryPoints))
}

// Type is type of the struct
func (dep *DefaultEntryPoints) Type() string {
	return fmt.Sprint("defaultentrypoints²")
}

// EntryPoints holds entry points configuration of the reverse proxy (ip, port, TLS...)
type EntryPoints map[string]*EntryPoint

// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (ep *EntryPoints) String() string {
	//TODO :
	return ""
}

// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (ep *EntryPoints) Set(value string) error {
	regex := regexp.MustCompile("(?:Name:(?P<Name>\\S*))\\s*(?:Address:(?P<Address>\\S*))?\\s*(?:TLS:(?P<TLS>\\S*))?\\s*(?:Redirect.EntryPoint:(?P<RedirectEntryPoint>\\S*))?\\s*(?:Redirect.Regex:(?P<RedirectRegex>\\S*))?\\s*(?:Redirect.Replacement:(?P<RedirectReplacement>\\S*))?")
	match := regex.FindAllStringSubmatch(value, -1)
	if match == nil {
		return errors.New("Bad EntryPoints format: " + value)
	}
	matchResult := match[0]
	result := make(map[string]string)
	for i, name := range regex.SubexpNames() {
		if i != 0 {
			result[name] = matchResult[i]
		}
	}
	var tls *TLS
	if len(result["TLS"]) > 0 {
		certs := Certificates{}
		if err := certs.Set(result["TLS"]); err != nil {
			return err
		}
		tls = &TLS{
			Certificates: certs,
		}
	}
	var redirect *Redirect
	if len(result["RedirectEntryPoint"]) > 0 || len(result["RedirectRegex"]) > 0 || len(result["RedirectReplacement"]) > 0 {
		redirect = &Redirect{
			EntryPoint:  result["RedirectEntryPoint"],
			Regex:       result["RedirectRegex"],
			Replacement: result["RedirectReplacement"],
		}
	}

	(*ep)[result["Name"]] = &EntryPoint{
		Address:  result["Address"],
		TLS:      tls,
		Redirect: redirect,
	}

	return nil
}

// Get return the EntryPoints map
func (ep *EntryPoints) Get() interface{} { return EntryPoints(*ep) }

// SetValue sets the EntryPoints map with val
func (ep *EntryPoints) SetValue(val interface{}) {
	*ep = EntryPoints(val.(EntryPoints))
}

// Type is type of the struct
func (ep *EntryPoints) Type() string {
	return fmt.Sprint("entrypoints²")
}

// EntryPoint holds an entry point configuration of the reverse proxy (ip, port, TLS...)
type EntryPoint struct {
	Network  string
	Address  string
	TLS      *TLS
	Redirect *Redirect
}

// Redirect configures a redirection of an entry point to another, or to an URL
type Redirect struct {
	EntryPoint  string
	Regex       string
	Replacement string
}

// TLS configures TLS for an entry point
type TLS struct {
	Certificates Certificates
}

// Certificates defines traefik certificates type
type Certificates []Certificate

// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (certs *Certificates) String() string {
	if len(*certs) == 0 {
		//TODO :
		return ""
	}
	return (*certs)[0].CertFile + "," + (*certs)[0].KeyFile
}

// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (certs *Certificates) Set(value string) error {
	files := strings.Split(value, ",")
	if len(files) != 2 {
		return errors.New("Bad certificates format: " + value)
	}
	*certs = append(*certs, Certificate{
		CertFile: files[0],
		KeyFile:  files[1],
	})
	return nil
}

// Type is type of the struct
func (certs *Certificates) Type() string {
	return fmt.Sprint("certificates")
}

// Certificate holds a SSL cert/key pair
type Certificate struct {
	CertFile string
	KeyFile  string
}

// Retry contains request retry config
type Retry struct {
	Attempts int
	MaxMem   int64
}

// NewTraefikPointersConfiguration creates a TraefikConfiguration with pointers default values
func NewTraefikPointersConfiguration() *TraefikConfiguration {
	//default Docker
	var defaultDocker provider.Docker
	defaultDocker.Watch = true
	defaultDocker.Endpoint = "unix:///var/run/docker.sock"
	defaultDocker.TLS = &provider.DockerTLS{}

	// default File
	var defaultFile provider.File
	defaultFile.Watch = true
	defaultFile.Filename = "" //needs equivalent to  viper.ConfigFileUsed()

	// default Web
	var defaultWeb WebProvider
	defaultWeb.Address = ":8080"

	// default Marathon
	var defaultMarathon provider.Marathon
	defaultMarathon.Watch = true
	defaultMarathon.Endpoint = "http://127.0.0.1:8080"
	defaultMarathon.ExposedByDefault = true

	// default Consul
	var defaultConsul provider.Consul
	defaultConsul.Watch = true
	defaultConsul.Endpoint = "127.0.0.1:8500"
	defaultConsul.Prefix = "/traefik"
	defaultConsul.TLS = &provider.KvTLS{}

	// default ConsulCatalog
	var defaultConsulCatalog provider.ConsulCatalog
	defaultConsulCatalog.Endpoint = "127.0.0.1:8500"

	// default Etcd
	var defaultEtcd provider.Etcd
	defaultEtcd.Watch = true
	defaultEtcd.Endpoint = "127.0.0.1:400"
	defaultEtcd.Prefix = "/traefik"
	defaultEtcd.TLS = &provider.KvTLS{}

	//default Zookeeper
	var defaultZookeeper provider.Zookepper
	defaultZookeeper.Watch = true
	defaultZookeeper.Endpoint = "127.0.0.1:2181"
	defaultZookeeper.Prefix = "/traefik"

	//default Boltdb
	var defaultBoltDb provider.BoltDb
	defaultBoltDb.Watch = true
	defaultBoltDb.Endpoint = "127.0.0.1:4001"
	defaultBoltDb.Prefix = "/traefik"

	//default Kubernetes
	var defaultKubernetes provider.Kubernetes
	defaultKubernetes.Watch = true
	defaultKubernetes.Endpoint = "127.0.0.1:8080"

	defaultConfiguration := GlobalConfiguration{
		Docker:        &defaultDocker,
		File:          &defaultFile,
		Web:           &defaultWeb,
		Marathon:      &defaultMarathon,
		Consul:        &defaultConsul,
		ConsulCatalog: &defaultConsulCatalog,
		Etcd:          &defaultEtcd,
		Zookeeper:     &defaultZookeeper,
		Boltdb:        &defaultBoltDb,
		Kubernetes:    &defaultKubernetes,
	}
	return &TraefikConfiguration{
		GlobalConfiguration: defaultConfiguration,
	}
}

// NewTraefikConfiguration creates a TraefikConfiguration with default values
func NewTraefikConfiguration() *TraefikConfiguration {
	return &TraefikConfiguration{
		GlobalConfiguration: GlobalConfiguration{
			GraceTimeOut:              10,
			AccessLogsFile:            "log/access.log",
			TraefikLogsFile:           "log/traefik.log",
			LogLevel:                  "ERROR",
			EntryPoints:               map[string]*EntryPoint{"http": &EntryPoint{Address: ":80"}},
			DefaultEntryPoints:        []string{"http"},
			ProvidersThrottleDuration: time.Duration(2 * time.Second),
			MaxIdleConnsPerHost:       200,
		},
		ConfigFile: "",
	}
}

type configs map[string]*types.Configuration
<commit_msg>fix default value<commit_after>package main

import (
	"errors"
	"fmt"
	"github.com/containous/traefik/acme"
	"github.com/containous/traefik/provider"
	"github.com/containous/traefik/types"
	"regexp"
	"strings"
	"time"
)

// TraefikConfiguration holds GlobalConfiguration and other stuff
type TraefikConfiguration struct {
	GlobalConfiguration
	ConfigFile string `short:"c" description:"Timeout in seconds. Duration to give active requests a chance to finish during hot-reloads"`
}

// GlobalConfiguration holds global configuration (with providers, etc.).
// It's populated from the traefik configuration file passed as an argument to the binary.
type GlobalConfiguration struct {
	GraceTimeOut              int64       `short:"g" description:"Configuration file to use (TOML)."`
	Debug                     bool
	AccessLogsFile            string      `description:"Access logs file"`
	TraefikLogsFile           string      `description:"Traefik logs file"`
	LogLevel                  string      `short:"l" description:"Log level"`
	EntryPoints               EntryPoints `description:"Entrypoints definition using format: --entryPoints='Name:http Address::8000 Redirect.EntryPoint:https' --entryPoints='Name:https Address::4442 TLS:tests/traefik.crt,tests/traefik.key'"`
	ACME                      *acme.ACME
	DefaultEntryPoints        DefaultEntryPoints `description:"Entrypoints to be used by frontends that do not specify any entrypoint"`
	ProvidersThrottleDuration time.Duration      `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time."`
	MaxIdleConnsPerHost       int                `description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host.  If zero, DefaultMaxIdleConnsPerHost is used"`
	Retry                     *Retry
	Docker                    *provider.Docker        `description:"Enable Docker backend"`
	File                      *provider.File          `description:"Enable File backend"`
	Web                       *WebProvider            `description:"Enable Web backend"`
	Marathon                  *provider.Marathon      `description:"Enable Marathon backend"`
	Consul                    *provider.Consul        `description:"Enable Consul backend"`
	ConsulCatalog             *provider.ConsulCatalog `description:"Enable Consul catalog backend"`
	Etcd                      *provider.Etcd          `description:"Enable Etcd backend"`
	Zookeeper                 *provider.Zookepper     `description:"Enable Zookeeper backend"`
	Boltdb                    *provider.BoltDb        `description:"Enable Boltdb backend"`
	Kubernetes                *provider.Kubernetes    `description:"Enable Kubernetes backend"`
}

// DefaultEntryPoints holds default entry points
type DefaultEntryPoints []string

// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (dep *DefaultEntryPoints) String() string {
	//TODO :
	return fmt.Sprintf("%#v", dep)
}

// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (dep *DefaultEntryPoints) Set(value string) error {
	entrypoints := strings.Split(value, ",")
	if len(entrypoints) == 0 {
		return errors.New("Bad DefaultEntryPoints format: " + value)
	}
	for _, entrypoint := range entrypoints {
		*dep = append(*dep, entrypoint)
	}
	return nil
}

// Get return the EntryPoints map
func (dep *DefaultEntryPoints) Get() interface{} { return DefaultEntryPoints(*dep) }

// SetValue sets the EntryPoints map with val
func (dep *DefaultEntryPoints) SetValue(val interface{}) {
	*dep = DefaultEntryPoints(val.(DefaultEntryPoints))
}

// Type is type of the struct
func (dep *DefaultEntryPoints) Type() string {
	return fmt.Sprint("defaultentrypoints²")
}

// EntryPoints holds entry points configuration of the reverse proxy (ip, port, TLS...)
type EntryPoints map[string]*EntryPoint

// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (ep *EntryPoints) String() string {
	//TODO :
	return ""
}

// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (ep *EntryPoints) Set(value string) error {
	regex := regexp.MustCompile("(?:Name:(?P<Name>\\S*))\\s*(?:Address:(?P<Address>\\S*))?\\s*(?:TLS:(?P<TLS>\\S*))?\\s*(?:Redirect.EntryPoint:(?P<RedirectEntryPoint>\\S*))?\\s*(?:Redirect.Regex:(?P<RedirectRegex>\\S*))?\\s*(?:Redirect.Replacement:(?P<RedirectReplacement>\\S*))?")
	match := regex.FindAllStringSubmatch(value, -1)
	if match == nil {
		return errors.New("Bad EntryPoints format: " + value)
	}
	matchResult := match[0]
	result := make(map[string]string)
	for i, name := range regex.SubexpNames() {
		if i != 0 {
			result[name] = matchResult[i]
		}
	}
	var tls *TLS
	if len(result["TLS"]) > 0 {
		certs := Certificates{}
		if err := certs.Set(result["TLS"]); err != nil {
			return err
		}
		tls = &TLS{
			Certificates: certs,
		}
	}
	var redirect *Redirect
	if len(result["RedirectEntryPoint"]) > 0 || len(result["RedirectRegex"]) > 0 || len(result["RedirectReplacement"]) > 0 {
		redirect = &Redirect{
			EntryPoint:  result["RedirectEntryPoint"],
			Regex:       result["RedirectRegex"],
			Replacement: result["RedirectReplacement"],
		}
	}

	(*ep)[result["Name"]] = &EntryPoint{
		Address:  result["Address"],
		TLS:      tls,
		Redirect: redirect,
	}

	return nil
}

// Get return the EntryPoints map
func (ep *EntryPoints) Get() interface{} { return EntryPoints(*ep) }

// SetValue sets the EntryPoints map with val
func (ep *EntryPoints) SetValue(val interface{}) {
	*ep = EntryPoints(val.(EntryPoints))
}

// Type is type of the struct
func (ep *EntryPoints) Type() string {
	return fmt.Sprint("entrypoints²")
}

// EntryPoint holds an entry point configuration of the reverse proxy (ip, port, TLS...)
type EntryPoint struct {
	Network  string
	Address  string
	TLS      *TLS
	Redirect *Redirect
}

// Redirect configures a redirection of an entry point to another, or to an URL
type Redirect struct {
	EntryPoint  string
	Regex       string
	Replacement string
}

// TLS configures TLS for an entry point
type TLS struct {
	Certificates Certificates
}

// Certificates defines traefik certificates type
type Certificates []Certificate

// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (certs *Certificates) String() string {
	if len(*certs) == 0 {
		//TODO :
		return ""
	}
	return (*certs)[0].CertFile + "," + (*certs)[0].KeyFile
}

// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (certs *Certificates) Set(value string) error {
	files := strings.Split(value, ",")
	if len(files) != 2 {
		return errors.New("Bad certificates format: " + value)
	}
	*certs = append(*certs, Certificate{
		CertFile: files[0],
		KeyFile:  files[1],
	})
	return nil
}

// Type is type of the struct
func (certs *Certificates) Type() string {
	return fmt.Sprint("certificates")
}

// Certificate holds a SSL cert/key pair
type Certificate struct {
	CertFile string
	KeyFile  string
}

// Retry contains request retry config
type Retry struct {
	Attempts int
	MaxMem   int64
}

// NewTraefikPointersConfiguration creates a TraefikConfiguration with pointers default values
func NewTraefikPointersConfiguration() *TraefikConfiguration {
	//default Docker
	var defaultDocker provider.Docker
	defaultDocker.Watch = true
	defaultDocker.Endpoint = "unix:///var/run/docker.sock"
	defaultDocker.TLS = &provider.DockerTLS{}

	// default File
	var defaultFile provider.File
	defaultFile.Watch = true
	defaultFile.Filename = "" //needs equivalent to  viper.ConfigFileUsed()

	// default Web
	var defaultWeb WebProvider
	defaultWeb.Address = ":8080"

	// default Marathon
	var defaultMarathon provider.Marathon
	defaultMarathon.Watch = true
	defaultMarathon.Endpoint = "http://127.0.0.1:8080"
	defaultMarathon.ExposedByDefault = true

	// default Consul
	var defaultConsul provider.Consul
	defaultConsul.Watch = true
	defaultConsul.Endpoint = "127.0.0.1:8500"
	defaultConsul.Prefix = "/traefik"
	defaultConsul.TLS = &provider.KvTLS{}

	// default ConsulCatalog
	var defaultConsulCatalog provider.ConsulCatalog
	defaultConsulCatalog.Endpoint = "127.0.0.1:8500"

	// default Etcd
	var defaultEtcd provider.Etcd
	defaultEtcd.Watch = true
	defaultEtcd.Endpoint = "127.0.0.1:400"
	defaultEtcd.Prefix = "/traefik"
	defaultEtcd.TLS = &provider.KvTLS{}

	//default Zookeeper
	var defaultZookeeper provider.Zookepper
	defaultZookeeper.Watch = true
	defaultZookeeper.Endpoint = "127.0.0.1:2181"
	defaultZookeeper.Prefix = "/traefik"

	//default Boltdb
	var defaultBoltDb provider.BoltDb
	defaultBoltDb.Watch = true
	defaultBoltDb.Endpoint = "127.0.0.1:4001"
	defaultBoltDb.Prefix = "/traefik"

	//default Kubernetes
	var defaultKubernetes provider.Kubernetes
	defaultKubernetes.Watch = true
	defaultKubernetes.Endpoint = "127.0.0.1:8080"

	defaultConfiguration := GlobalConfiguration{
		Docker:        &defaultDocker,
		File:          &defaultFile,
		Web:           &defaultWeb,
		Marathon:      &defaultMarathon,
		Consul:        &defaultConsul,
		ConsulCatalog: &defaultConsulCatalog,
		Etcd:          &defaultEtcd,
		Zookeeper:     &defaultZookeeper,
		Boltdb:        &defaultBoltDb,
		Kubernetes:    &defaultKubernetes,
	}
	return &TraefikConfiguration{
		GlobalConfiguration: defaultConfiguration,
	}
}

// NewTraefikConfiguration creates a TraefikConfiguration with default values
func NewTraefikConfiguration() *TraefikConfiguration {
	return &TraefikConfiguration{
		GlobalConfiguration: GlobalConfiguration{
			GraceTimeOut:              10,
			AccessLogsFile:            "",
			TraefikLogsFile:           "",
			LogLevel:                  "ERROR",
			EntryPoints:               map[string]*EntryPoint{"http": &EntryPoint{Address: ":80"}},
			DefaultEntryPoints:        []string{"http"},
			ProvidersThrottleDuration: time.Duration(2 * time.Second),
			MaxIdleConnsPerHost:       200,
		},
		ConfigFile: "",
	}
}

type configs map[string]*types.Configuration
<|endoftext|>