<commit_before>// Package lightstep implements the LightStep OpenTracing client for Go.
package lightstep

import (
	"context"
	"fmt"
	"runtime"
	"sync"
	"time"

	"github.com/opentracing/opentracing-go"
)

// Tracer extends the `opentracing.Tracer` interface with methods for manual
// flushing and closing. To access these methods, you can take the global
// tracer and typecast it to a `lightstep.Tracer`. As a convenience, the
// lightstep package provides static functions which perform the typecasting.
type Tracer interface {
	opentracing.Tracer

	// Close flushes and then terminates the LightStep collector
	Close(context.Context)
	// Flush sends all spans currently in the buffer to the LighStep collector
	Flush(context.Context)
	// Options gets the Options used in New() or NewWithOptions().
	Options() Options
	// Disable prevents the tracer from recording spans or flushing
	Disable()
}

// Implements the `Tracer` interface. Buffers spans and forwards to a Lightstep collector.
type tracerImpl struct {
	//////////////////////////////////////////////////////////////
	// IMMUTABLE IMMUTABLE IMMUTABLE IMMUTABLE IMMUTABLE IMMUTABLE
	//////////////////////////////////////////////////////////////

	// Note: there may be a desire to update some of these fields
	// at runtime, in which case suitable changes may be needed
	// for variables accessed during Flush.

	reporterID uint64 // the LightStep tracer guid
	opts       Options

	// report loop management
	closeOnce               sync.Once
	closeReportLoopChannel  chan struct{}
	reportLoopClosedChannel chan struct{}

	converter   *protoConverter
	accessToken string
	attributes  map[string]string

	//////////////////////////////////////////////////////////
	// MUTABLE MUTABLE MUTABLE MUTABLE MUTABLE MUTABLE MUTABLE
	//////////////////////////////////////////////////////////

	// the following fields are modified under `lock`.
	lock sync.Mutex

	// Remote service that will receive reports.
	client     collectorClient
	connection Connection

	// Two buffers of data.
	buffer   reportBuffer
	flushing reportBuffer

	// Flush state.
	flushingLock      sync.Mutex
	reportInFlight    bool
	lastReportAttempt time.Time

	// Meta Event Reporting can be enabled at tracer creation or on-demand by satellite
	metaEventReportingEnabled bool
	// Set to true on first report
	firstReportHasRun bool

	// We allow our remote peer to disable this instrumentation at any
	// time, turning all potentially costly runtime operations into
	// no-ops.
	//
	// TODO this should use atomic load/store to test disabled
	// prior to taking the lock, do please.
	disabled bool

	// Map of propagators used to determine the correct propagator to use
	// based on the format passed into Inject/Extract. Supports one
	// propagator for each of the formats: TextMap, HTTPHeaders, Binary
	propagators map[opentracing.BuiltinFormat]Propagator
}

// NewTracer creates and starts a new Lightstep Tracer.
func NewTracer(opts Options) Tracer {
	err := opts.Initialize()
	if err != nil {
		emitEvent(newEventStartError(err))
		return nil
	}

	attributes := map[string]string{}
	for k, v := range opts.Tags {
		attributes[k] = fmt.Sprint(v)
	}
	// Don't let the GrpcOptions override these values. That would be confusing.
	attributes[TracerPlatformKey] = TracerPlatformValue
	attributes[TracerPlatformVersionKey] = runtime.Version()
	attributes[TracerVersionKey] = TracerVersionValue

	now := time.Now()
	impl := &tracerImpl{
		opts:                    opts,
		reporterID:              genSeededGUID(),
		buffer:                  newSpansBuffer(opts.MaxBufferedSpans),
		flushing:                newSpansBuffer(opts.MaxBufferedSpans),
		closeReportLoopChannel:  make(chan struct{}),
		reportLoopClosedChannel: make(chan struct{}),
		converter:               newProtoConverter(opts),
		accessToken:             opts.AccessToken,
		attributes:              attributes,
	}

	impl.buffer.setCurrent(now)

	impl.client, err = newCollectorClient(opts)
	if err != nil {
		fmt.Println("Failed to create to Collector client!", err)
		return nil
	}

	conn, err := impl.client.ConnectClient()
	if err != nil {
		emitEvent(newEventStartError(err))
		return nil
	}
	impl.connection = conn

	// set meta reporting to defined option
	impl.metaEventReportingEnabled = opts.MetaEventReportingEnabled
	impl.firstReportHasRun = false

	go impl.reportLoop()

	impl.propagators = map[opentracing.BuiltinFormat]Propagator{
		opentracing.TextMap:     theLightStepPropagator,
		opentracing.HTTPHeaders: theLightStepPropagator,
		opentracing.Binary:      theBinaryPropagator,
	}

	if opts.Propagator == "b3" {
		impl.propagators[opentracing.TextMap] = theB3Propagator
		impl.propagators[opentracing.HTTPHeaders] = theB3Propagator
	}

	return impl
}

func (tracer *tracerImpl) Options() Options {
	return tracer.opts
}
<commit_msg>Added new constructor for tracer that propagates error. (#228)<commit_after>// Package lightstep implements the LightStep OpenTracing client for Go.
package lightstep

import (
	"context"
	"fmt"
	"runtime"
	"sync"
	"time"

	"github.com/opentracing/opentracing-go"
)

// Tracer extends the `opentracing.Tracer` interface with methods for manual
// flushing and closing. To access these methods, you can take the global
// tracer and typecast it to a `lightstep.Tracer`. As a convenience, the
// lightstep package provides static functions which perform the typecasting.
type Tracer interface {
	opentracing.Tracer

	// Close flushes and then terminates the LightStep collector
	Close(context.Context)
	// Flush sends all spans currently in the buffer to the LighStep collector
	Flush(context.Context)
	// Options gets the Options used in New() or NewWithOptions().
	Options() Options
	// Disable prevents the tracer from recording spans or flushing
	Disable()
}

// Implements the `Tracer` interface. Buffers spans and forwards to a Lightstep collector.
type tracerImpl struct {
	//////////////////////////////////////////////////////////////
	// IMMUTABLE IMMUTABLE IMMUTABLE IMMUTABLE IMMUTABLE IMMUTABLE
	//////////////////////////////////////////////////////////////

	// Note: there may be a desire to update some of these fields
	// at runtime, in which case suitable changes may be needed
	// for variables accessed during Flush.

	reporterID uint64 // the LightStep tracer guid
	opts       Options

	// report loop management
	closeOnce               sync.Once
	closeReportLoopChannel  chan struct{}
	reportLoopClosedChannel chan struct{}

	converter   *protoConverter
	accessToken string
	attributes  map[string]string

	//////////////////////////////////////////////////////////
	// MUTABLE MUTABLE MUTABLE MUTABLE MUTABLE MUTABLE MUTABLE
	//////////////////////////////////////////////////////////

	// the following fields are modified under `lock`.
	lock sync.Mutex

	// Remote service that will receive reports.
	client     collectorClient
	connection Connection

	// Two buffers of data.
	buffer   reportBuffer
	flushing reportBuffer

	// Flush state.
	flushingLock      sync.Mutex
	reportInFlight    bool
	lastReportAttempt time.Time

	// Meta Event Reporting can be enabled at tracer creation or on-demand by satellite
	metaEventReportingEnabled bool
	// Set to true on first report
	firstReportHasRun bool

	// We allow our remote peer to disable this instrumentation at any
	// time, turning all potentially costly runtime operations into
	// no-ops.
	//
	// TODO this should use atomic load/store to test disabled
	// prior to taking the lock, do please.
	disabled bool

	// Map of propagators used to determine the correct propagator to use
	// based on the format passed into Inject/Extract. Supports one
	// propagator for each of the formats: TextMap, HTTPHeaders, Binary
	propagators map[opentracing.BuiltinFormat]Propagator
}

// NewTracer creates and starts a new Lightstep Tracer.
// In case of error, we emit event and return nil.
func NewTracer(opts Options) Tracer {
	tr, err := CreateTracer(opts)
	if err != nil  {
		emitEvent(newEventStartError(err))
		return nil
	}
	return tr
}

// CreateTracer creates and starts a new Lightstep Tracer.
// It is meant to replace NewTracer which does not propagate the error.
func CreateTracer(opts Options) (Tracer, error) {
	if err := opts.Initialize(); err != nil {
		return nil, fmt.Errorf("init; err: %v", err)
	}

	attributes := map[string]string{}
	for k, v := range opts.Tags {
		attributes[k] = fmt.Sprint(v)
	}
	// Don't let the GrpcOptions override these values. That would be confusing.
	attributes[TracerPlatformKey] = TracerPlatformValue
	attributes[TracerPlatformVersionKey] = runtime.Version()
	attributes[TracerVersionKey] = TracerVersionValue

	now := time.Now()
	impl := &tracerImpl{
		opts:                    opts,
		reporterID:              genSeededGUID(),
		buffer:                  newSpansBuffer(opts.MaxBufferedSpans),
		flushing:                newSpansBuffer(opts.MaxBufferedSpans),
		closeReportLoopChannel:  make(chan struct{}),
		reportLoopClosedChannel: make(chan struct{}),
		converter:               newProtoConverter(opts),
		accessToken:             opts.AccessToken,
		attributes:              attributes,
	}

	impl.buffer.setCurrent(now)

	var err error
	impl.client, err = newCollectorClient(opts)
	if err != nil {
		return nil, fmt.Errorf("create collector client; err: %v", err)
	}

	conn, err := impl.client.ConnectClient()
	if err != nil {
		return nil, err
	}
	impl.connection = conn

	// set meta reporting to defined option
	impl.metaEventReportingEnabled = opts.MetaEventReportingEnabled
	impl.firstReportHasRun = false

	go impl.reportLoop()

	impl.propagators = map[opentracing.BuiltinFormat]Propagator{
		opentracing.TextMap:     theLightStepPropagator,
		opentracing.HTTPHeaders: theLightStepPropagator,
		opentracing.Binary:      theBinaryPropagator,
	}

	if opts.Propagator == "b3" {
		impl.propagators[opentracing.TextMap] = theB3Propagator
		impl.propagators[opentracing.HTTPHeaders] = theB3Propagator
	}

	return impl, nil
}

func (tracer *tracerImpl) Options() Options {
	return tracer.opts
}

{'fraction_non_alphanumeric': 0.12063996820033787, 'fraction_numerical': 0.001291861273973964, 'mean_word_length': 2.9952362048431915, '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': '6215532', 'n_tokens_mistral': 2939, 'n_tokens_neox': 2802, 'n_words': 954}