func (tracer *epsagonTracer) GetRunnerEvent() *protocol.Event {
	for _, event := range tracer.events {
		if event.Origin == "runner" {
			return event
		}
	}
	return nil
}
GetRunnerEvent Gets the runner event, nil if not found
package tracer
import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"runtime"
	"runtime/debug"
	"strconv"
	"strings"
	"sync"
	"time"
	"github.com/epsagon/epsagon-go/protocol"
	"github.com/golang/protobuf/jsonpb"
)
var (
	mutex sync.Mutex
	GlobalTracer Tracer
)
const DefaultMaxTraceSizeKB = 64
const DefaultMaxTraceSize = DefaultMaxTraceSizeKB * 1024
const MaxTraceSizeKB = 512
const MaxTraceSize = MaxTraceSizeKB * 1024
const MaxLabelsSize = 10 * 1024
const MaxTraceSizeEnvVar = "EPSAGON_MAX_TRACE_SIZE"
const LabelsKey = "labels"
const IsTrimmedKey = "is_trimmed"
const EpsagonHTTPTraceIDKey = "http_trace_id"
const EpsagonRequestTraceIDKey = "request_trace_id"
const AwsServiceKey = "aws.service"
var strongKeys = map[string]bool{
	EpsagonHTTPTraceIDKey:    true,
	EpsagonRequestTraceIDKey: true,
	AwsServiceKey:            true,
	LabelsKey:                true,
	"aws_account":            true,
	"region":                 true,
	"log_group_name":         true,
	"log_stream_name":        true,
	"sequence_number":        true,
	"item_hash":              true,
}
const DefaultLambdaTimeoutThresholdMs = 200
func GetLambdaTimeoutThresholdMs() int {
	timeoutThresholdMs := DefaultLambdaTimeoutThresholdMs
	userDefinedThreshold, ok := os.LookupEnv("EPSAGON_LAMBDA_TIMEOUT_THRESHOLD_MS")
	if ok {
		if userDefinedThreshold, err := strconv.Atoi(userDefinedThreshold); err == nil {
			timeoutThresholdMs = userDefinedThreshold
		}
	}
	return timeoutThresholdMs
}
type Tracer interface {
	AddEvent(*protocol.Event)
	AddException(*protocol.Exception)
	AddExceptionTypeAndMessage(string, string)
	AddLabel(string, interface{})
	AddError(string, interface{})
	GetRunnerEvent() *protocol.Event
	Start()
	Running() bool
	SendStopSignal()
	Stop()
	Stopped() bool
	GetConfig() *Config
}
type Config struct {
	ApplicationName string    
	Token           string    
	CollectorURL    string    
	MetadataOnly    bool      
	Debug           bool      
	SendTimeout     string    
	Disable         bool      
	TestMode        bool      
	IgnoredKeys     []string  
	MaxTraceSize    int       
}
type epsagonLabel struct {
	key   string
	value interface{}
}
type epsagonTracer struct {
	Config *Config
	eventsPipe          chan *protocol.Event
	events              []*protocol.Event
	runnerExceptionPipe chan *protocol.Exception
	exceptionsPipe      chan *protocol.Exception
	labelsPipe          chan epsagonLabel
	exceptions          []*protocol.Exception
	runnerException     *protocol.Exception
	labels              map[string]interface{}
	labelsSize          int
	closeCmd chan struct{}
	stopped  chan struct{}
	running  chan struct{}
}
func (tracer *epsagonTracer) Start() {
	go tracer.Run()
	timer := time.NewTimer(time.Second)
	select {
	case <-tracer.running:
		return
	case <-timer.C:
		log.Println("Epsagon Tracer couldn't start after one second timeout")
	}
}
func (tracer *epsagonTracer) maskIgnoredKeys() {
	for _, event := range tracer.events {
		tracer.maskEventIgnoredKeys(event, tracer.Config.IgnoredKeys)
	}
}
func (tracer *epsagonTracer) sendTraces() {
	tracer.maskIgnoredKeys()
	tracesReader, err := tracer.getTraceReader()
	if err != nil {
		log.Printf("Epsagon: Encountered an error while marshaling the traces: %v\n", err)
		return
	}
	sendTimeout, err := time.ParseDuration(tracer.Config.SendTimeout)
	if err != nil {
		if tracer.Config.Debug {
			log.Printf("Epsagon: Encountered an error while parsing send timeout: %v, using '1s'\n", err)
		}
		sendTimeout, _ = time.ParseDuration("1s")
	}
	client := &http.Client{Timeout: sendTimeout}
	if !tracer.Config.Disable {
		if len(tracer.Config.Token) == 0 {
			if tracer.Config.Debug {
				log.Printf("Epsagon: empty token, not sending traces\n")
			}
			return
		}
		req, err := http.NewRequest(http.MethodPost, tracer.Config.CollectorURL, tracesReader)
		if err == nil {
			req.Header.Set("Content-Type", "application/json")
			req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", tracer.Config.Token))
			HandleSendTracesResponse(client.Do(req))
		} else {
			if tracer.Config.Debug {
				log.Printf("Epsagon: Encountered an error while trying to send traces: %v\n", err)
			}
		}
	}
}
func HandleSendTracesResponse(resp *http.Response, err error) {
	if err != nil {
		log.Printf("Error while sending traces \n%v", err)
		return
	}
	defer resp.Body.Close()
	if resp.StatusCode >= http.StatusInternalServerError {
		respBody, _ := ioutil.ReadAll(resp.Body)
		log.Printf("Error while sending traces \n%v", string(respBody))
	}
}