<commit_before>package lightstep

import (
	"bytes"
	"fmt"
	"github.com/golang/protobuf/proto"
	"github.com/lightstep/lightstep-tracer-go/collectorpb"
	"golang.org/x/net/context"
	"golang.org/x/net/http2"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"
)

var (
	acceptHeader      = http.CanonicalHeaderKey("Accept")
	contentTypeHeader = http.CanonicalHeaderKey("Content-Type")
)

const (
	collectorHttpMethod = "POST"
	collectorHttpPath   = "/api/v2/reports"
	protoContentType    = "application/octet-stream"
)

// grpcCollectorClient specifies how to send reports back to a LightStep
// collector via grpc.
type httpCollectorClient struct {
	// auth and runtime information
	reporterID  uint64
	accessToken string // accessToken is the access token used for explicit trace collection requests.
	attributes  map[string]string

	reportTimeout time.Duration

	// Remote service that will receive reports.
	url    *url.URL
	client *http.Client

	// converters
	converter *protoConverter
}

type transportCloser struct {
	transport http2.Transport
}

func (closer *transportCloser) Close() error {
	closer.transport.CloseIdleConnections()

	return nil
}

func newHttpCollectorClient(
	opts Options,
	reporterID uint64,
	attributes map[string]string,
) (*httpCollectorClient, error) {
	url, err := url.Parse(opts.Collector.HostPort())
	if err != nil {
		fmt.Println("collector config does not produce valid url", err)
		return nil, err
	}
	url.Path = collectorHttpPath

	return &httpCollectorClient{
		reporterID:    reporterID,
		accessToken:   opts.AccessToken,
		attributes:    attributes,
		reportTimeout: opts.ReportTimeout,
		url:           url,
		converter:     newProtoConverter(opts),
	}, nil
}

func (client *httpCollectorClient) ConnectClient() (Connection, error) {
	transport := &http2.Transport{}

	client.client = &http.Client{
		Transport: transport,
		Timeout:   client.reportTimeout,
	}

	return &transportCloser{}, nil
}

func (client *httpCollectorClient) ShouldReconnect() bool {
	// http2 will handle connection reuse under the hood
	return false
}

func (client *httpCollectorClient) Report(context context.Context, buffer *reportBuffer) (collectorResponse, error) {
	httpRequest, err := client.toRequest(context, buffer)
	if err != nil {
		return nil, err
	}

	httpResponse, err := client.client.Do(httpRequest)
	if err != nil {
		return nil, err
	}
	defer httpResponse.Body.Close()<commit_msg>Add scheme to the url (http or https) and allow http for http schemes. (#118)<commit_after>package lightstep

import (
	"bytes"
	"fmt"
	"github.com/golang/protobuf/proto"
	"github.com/lightstep/lightstep-tracer-go/collectorpb"
	"golang.org/x/net/context"
	"golang.org/x/net/http2"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"
)

var (
	acceptHeader      = http.CanonicalHeaderKey("Accept")
	contentTypeHeader = http.CanonicalHeaderKey("Content-Type")
)

const (
	collectorHttpMethod = "POST"
	collectorHttpPath   = "/api/v2/reports"
	protoContentType    = "application/octet-stream"
)

// grpcCollectorClient specifies how to send reports back to a LightStep
// collector via grpc.
type httpCollectorClient struct {
	// auth and runtime information
	reporterID  uint64
	accessToken string // accessToken is the access token used for explicit trace collection requests.
	attributes  map[string]string

	reportTimeout time.Duration

	// Remote service that will receive reports.
	url    *url.URL
	client *http.Client

	// converters
	converter *protoConverter
}

type transportCloser struct {
	transport http2.Transport
}

func (closer *transportCloser) Close() error {
	closer.transport.CloseIdleConnections()

	return nil
}

func newHttpCollectorClient(
	opts Options,
	reporterID uint64,
	attributes map[string]string,
) (*httpCollectorClient, error) {
	url, err := url.Parse(opts.Collector.URL())
	if err != nil {
		fmt.Println("collector config does not produce valid url", err)
		return nil, err
	}
	url.Path = collectorHttpPath

	return &httpCollectorClient{
		reporterID:    reporterID,
		accessToken:   opts.AccessToken,
		attributes:    attributes,
		reportTimeout: opts.ReportTimeout,
		url:           url,
		converter:     newProtoConverter(opts),
	}, nil
}

func (client *httpCollectorClient) ConnectClient() (Connection, error) {
	transport := &http2.Transport{
		AllowHTTP: true,
	}

	client.client = &http.Client{
		Transport: transport,
		Timeout:   client.reportTimeout,
	}

	return &transportCloser{}, nil
}

func (client *httpCollectorClient) ShouldReconnect() bool {
	// http2 will handle connection reuse under the hood
	return false
}

func (client *httpCollectorClient) Report(context context.Context, buffer *reportBuffer) (collectorResponse, error) {
	httpRequest, err := client.toRequest(context, buffer)
	if err != nil {
		return nil, err
	}

	httpResponse, err := client.client.Do(httpRequest)
	if err != nil {
		return nil, err
	}
	defer httpResponse.Body.Close()
{'fraction_non_alphanumeric': 0.10448979591836735, 'fraction_numerical': 0.004285714285714286, 'mean_word_length': 4.385714285714286, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4086719', 'n_tokens_mistral': 1621, 'n_tokens_neox': 1551, 'n_words': 407}