|
|
|
|
@ -10,13 +10,18 @@ package logpolicy |
|
|
|
|
import ( |
|
|
|
|
"bytes" |
|
|
|
|
"context" |
|
|
|
|
"crypto/tls" |
|
|
|
|
"encoding/json" |
|
|
|
|
"fmt" |
|
|
|
|
"io/ioutil" |
|
|
|
|
"log" |
|
|
|
|
"net" |
|
|
|
|
"net/http" |
|
|
|
|
"os" |
|
|
|
|
"path/filepath" |
|
|
|
|
"runtime" |
|
|
|
|
"strconv" |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"github.com/klauspost/compress/zstd" |
|
|
|
|
"golang.org/x/crypto/ssh/terminal" |
|
|
|
|
@ -182,6 +187,7 @@ func New(collection string) *Policy { |
|
|
|
|
} |
|
|
|
|
return w |
|
|
|
|
}, |
|
|
|
|
HTTPC: &http.Client{Transport: newLogtailTransport()}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
filchBuf, filchErr := filch.New(filepath.Join(dir, version.CmdName()), filch.Options{}) |
|
|
|
|
@ -220,3 +226,48 @@ func (p *Policy) Shutdown(ctx context.Context) error { |
|
|
|
|
} |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// newLogtailTransport returns the HTTP Transport we use for uploading logs.
|
|
|
|
|
func newLogtailTransport() *http.Transport { |
|
|
|
|
// Start with a copy of http.DefaultTransport and tweak it a bit.
|
|
|
|
|
tr := http.DefaultTransport.(*http.Transport).Clone() |
|
|
|
|
|
|
|
|
|
// We do our own zstd compression on uploads, and responses never contain any payload,
|
|
|
|
|
// so don't send "Accept-Encoding: gzip" to save a few bytes on the wire, since there
|
|
|
|
|
// will never be any body to decompress:
|
|
|
|
|
tr.DisableCompression = true |
|
|
|
|
|
|
|
|
|
// Log whenever we dial:
|
|
|
|
|
tr.DialContext = func(ctx context.Context, netw, addr string) (net.Conn, error) { |
|
|
|
|
nd := &net.Dialer{ |
|
|
|
|
Timeout: 30 * time.Second, |
|
|
|
|
KeepAlive: 30 * time.Second, |
|
|
|
|
DualStack: true, |
|
|
|
|
} |
|
|
|
|
t0 := time.Now() |
|
|
|
|
c, err := nd.DialContext(ctx, netw, addr) |
|
|
|
|
d := time.Since(t0).Round(time.Millisecond) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Printf("logtail: dial %q failed: %v (in %v)", addr, err, d) |
|
|
|
|
} else { |
|
|
|
|
log.Printf("logtail: dialed %q in %v", addr, d) |
|
|
|
|
} |
|
|
|
|
return c, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// We're contacting exactly 1 hostname, so the default's 100
|
|
|
|
|
// max idle conns is very high for our needs. Even 2 is
|
|
|
|
|
// probably double what we need:
|
|
|
|
|
tr.MaxIdleConns = 2 |
|
|
|
|
|
|
|
|
|
// Provide knob to force HTTP/1 for log uploads.
|
|
|
|
|
// TODO(bradfitz): remove this debug knob once we've decided
|
|
|
|
|
// to upload via HTTP/1 or HTTP/2 (probably HTTP/1). Or we might just enforce
|
|
|
|
|
// it server-side.
|
|
|
|
|
if h1, _ := strconv.ParseBool(os.Getenv("TS_DEBUG_FORCE_H1_LOGS")); h1 { |
|
|
|
|
tr.TLSClientConfig = nil // DefaultTransport's was already initialized w/ h2
|
|
|
|
|
tr.ForceAttemptHTTP2 = false |
|
|
|
|
tr.TLSNextProto = map[string]func(authority string, c *tls.Conn) http.RoundTripper{} |
|
|
|
|
} |
|
|
|
|
return tr |
|
|
|
|
} |
|
|
|
|
|