Update dependencies
This commit is contained in:
368
vendor/github.com/getsentry/sentry-go/transport.go
generated
vendored
368
vendor/github.com/getsentry/sentry-go/transport.go
generated
vendored
@@ -2,6 +2,7 @@ package sentry
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -12,11 +13,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/getsentry/sentry-go/internal/debuglog"
|
||||
httpinternal "github.com/getsentry/sentry-go/internal/http"
|
||||
"github.com/getsentry/sentry-go/internal/protocol"
|
||||
"github.com/getsentry/sentry-go/internal/ratelimit"
|
||||
)
|
||||
|
||||
const defaultBufferSize = 30
|
||||
const defaultTimeout = time.Second * 30
|
||||
const (
|
||||
defaultBufferSize = 1000
|
||||
defaultTimeout = time.Second * 30
|
||||
)
|
||||
|
||||
// maxDrainResponseBytes is the maximum number of bytes that transport
|
||||
// implementations will read from response bodies when draining them.
|
||||
@@ -32,8 +38,10 @@ const maxDrainResponseBytes = 16 << 10
|
||||
// Transport is used by the Client to deliver events to remote server.
|
||||
type Transport interface {
|
||||
Flush(timeout time.Duration) bool
|
||||
FlushWithContext(ctx context.Context) bool
|
||||
Configure(options ClientOptions)
|
||||
SendEvent(event *Event)
|
||||
Close()
|
||||
}
|
||||
|
||||
func getProxyConfig(options ClientOptions) func(*http.Request) (*url.URL, error) {
|
||||
@@ -82,14 +90,14 @@ func getRequestBodyFromEvent(event *Event) []byte {
|
||||
}
|
||||
body, err = json.Marshal(event)
|
||||
if err == nil {
|
||||
Logger.Println(msg)
|
||||
debuglog.Println(msg)
|
||||
return body
|
||||
}
|
||||
|
||||
// This should _only_ happen when Event.Exception[0].Stacktrace.Frames[0].Vars is unserializable
|
||||
// Which won't ever happen, as we don't use it now (although it's the part of public interface accepted by Sentry)
|
||||
// Juuust in case something, somehow goes utterly wrong.
|
||||
Logger.Println("Event couldn't be marshaled, even with stripped contextual data. Skipping delivery. " +
|
||||
debuglog.Println("Event couldn't be marshaled, even with stripped contextual data. Skipping delivery. " +
|
||||
"Please notify the SDK owners with possibly broken payload.")
|
||||
return nil
|
||||
}
|
||||
@@ -142,6 +150,40 @@ func encodeEnvelopeItem(enc *json.Encoder, itemType string, body json.RawMessage
|
||||
return err
|
||||
}
|
||||
|
||||
func encodeEnvelopeLogs(enc *json.Encoder, count int, body json.RawMessage) error {
|
||||
err := enc.Encode(
|
||||
struct {
|
||||
Type string `json:"type"`
|
||||
ItemCount int `json:"item_count"`
|
||||
ContentType string `json:"content_type"`
|
||||
}{
|
||||
Type: logEvent.Type,
|
||||
ItemCount: count,
|
||||
ContentType: logEvent.ContentType,
|
||||
})
|
||||
if err == nil {
|
||||
err = enc.Encode(body)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func encodeEnvelopeMetrics(enc *json.Encoder, count int, body json.RawMessage) error {
|
||||
err := enc.Encode(
|
||||
struct {
|
||||
Type string `json:"type"`
|
||||
ItemCount int `json:"item_count"`
|
||||
ContentType string `json:"content_type"`
|
||||
}{
|
||||
Type: traceMetricEvent.Type,
|
||||
ItemCount: count,
|
||||
ContentType: traceMetricEvent.ContentType,
|
||||
})
|
||||
if err == nil {
|
||||
err = enc.Encode(body)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func envelopeFromBody(event *Event, dsn *Dsn, sentAt time.Time, body json.RawMessage) (*bytes.Buffer, error) {
|
||||
var b bytes.Buffer
|
||||
enc := json.NewEncoder(&b)
|
||||
@@ -175,11 +217,17 @@ func envelopeFromBody(event *Event, dsn *Dsn, sentAt time.Time, body json.RawMes
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if event.Type == transactionType || event.Type == checkInType {
|
||||
switch event.Type {
|
||||
case transactionType, checkInType:
|
||||
err = encodeEnvelopeItem(enc, event.Type, body)
|
||||
} else {
|
||||
case logEvent.Type:
|
||||
err = encodeEnvelopeLogs(enc, len(event.Logs), body)
|
||||
case traceMetricEvent.Type:
|
||||
err = encodeEnvelopeMetrics(enc, len(event.Metrics), body)
|
||||
default:
|
||||
err = encodeEnvelopeItem(enc, eventType, body)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -191,66 +239,51 @@ func envelopeFromBody(event *Event, dsn *Dsn, sentAt time.Time, body json.RawMes
|
||||
}
|
||||
}
|
||||
|
||||
// Profile data
|
||||
if event.sdkMetaData.transactionProfile != nil {
|
||||
body, err = json.Marshal(event.sdkMetaData.transactionProfile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = encodeEnvelopeItem(enc, profileType, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &b, nil
|
||||
}
|
||||
|
||||
func getRequestFromEvent(event *Event, dsn *Dsn) (r *http.Request, err error) {
|
||||
func getRequestFromEvent(ctx context.Context, event *Event, dsn *Dsn) (r *http.Request, err error) {
|
||||
defer func() {
|
||||
if r != nil {
|
||||
r.Header.Set("User-Agent", fmt.Sprintf("%s/%s", event.Sdk.Name, event.Sdk.Version))
|
||||
r.Header.Set("Content-Type", "application/x-sentry-envelope")
|
||||
|
||||
auth := fmt.Sprintf("Sentry sentry_version=%s, "+
|
||||
"sentry_client=%s/%s, sentry_key=%s", apiVersion, event.Sdk.Name, event.Sdk.Version, dsn.publicKey)
|
||||
"sentry_client=%s/%s, sentry_key=%s", apiVersion, event.Sdk.Name, event.Sdk.Version, dsn.GetPublicKey())
|
||||
|
||||
// The key sentry_secret is effectively deprecated and no longer needs to be set.
|
||||
// However, since it was required in older self-hosted versions,
|
||||
// it should still passed through to Sentry if set.
|
||||
if dsn.secretKey != "" {
|
||||
auth = fmt.Sprintf("%s, sentry_secret=%s", auth, dsn.secretKey)
|
||||
if dsn.GetSecretKey() != "" {
|
||||
auth = fmt.Sprintf("%s, sentry_secret=%s", auth, dsn.GetSecretKey())
|
||||
}
|
||||
|
||||
r.Header.Set("X-Sentry-Auth", auth)
|
||||
}
|
||||
}()
|
||||
|
||||
body := getRequestBodyFromEvent(event)
|
||||
if body == nil {
|
||||
return nil, errors.New("event could not be marshaled")
|
||||
}
|
||||
|
||||
envelope, err := envelopeFromBody(event, dsn, time.Now(), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return http.NewRequest(
|
||||
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
|
||||
return http.NewRequestWithContext(
|
||||
ctx,
|
||||
http.MethodPost,
|
||||
dsn.GetAPIURL().String(),
|
||||
envelope,
|
||||
)
|
||||
}
|
||||
|
||||
func categoryFor(eventType string) ratelimit.Category {
|
||||
switch eventType {
|
||||
case "":
|
||||
return ratelimit.CategoryError
|
||||
case transactionType:
|
||||
return ratelimit.CategoryTransaction
|
||||
default:
|
||||
return ratelimit.Category(eventType)
|
||||
}
|
||||
}
|
||||
|
||||
// ================================
|
||||
// HTTPTransport
|
||||
// ================================
|
||||
@@ -281,7 +314,8 @@ type HTTPTransport struct {
|
||||
// current in-flight items and starts a new batch for subsequent events.
|
||||
buffer chan batch
|
||||
|
||||
start sync.Once
|
||||
startOnce sync.Once
|
||||
closeOnce sync.Once
|
||||
|
||||
// Size of the transport buffer. Defaults to 30.
|
||||
BufferSize int
|
||||
@@ -290,6 +324,9 @@ type HTTPTransport struct {
|
||||
|
||||
mu sync.RWMutex
|
||||
limits ratelimit.Map
|
||||
|
||||
// receiving signal will terminate worker.
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
// NewHTTPTransport returns a new pre-configured instance of HTTPTransport.
|
||||
@@ -297,7 +334,7 @@ func NewHTTPTransport() *HTTPTransport {
|
||||
transport := HTTPTransport{
|
||||
BufferSize: defaultBufferSize,
|
||||
Timeout: defaultTimeout,
|
||||
limits: make(ratelimit.Map),
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
return &transport
|
||||
}
|
||||
@@ -306,7 +343,7 @@ func NewHTTPTransport() *HTTPTransport {
|
||||
func (t *HTTPTransport) Configure(options ClientOptions) {
|
||||
dsn, err := NewDsn(options.Dsn)
|
||||
if err != nil {
|
||||
Logger.Printf("%v\n", err)
|
||||
debuglog.Printf("%v\n", err)
|
||||
return
|
||||
}
|
||||
t.dsn = dsn
|
||||
@@ -339,24 +376,29 @@ func (t *HTTPTransport) Configure(options ClientOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
t.start.Do(func() {
|
||||
t.startOnce.Do(func() {
|
||||
go t.worker()
|
||||
})
|
||||
}
|
||||
|
||||
// SendEvent assembles a new packet out of Event and sends it to remote server.
|
||||
// SendEvent assembles a new packet out of Event and sends it to the remote server.
|
||||
func (t *HTTPTransport) SendEvent(event *Event) {
|
||||
t.SendEventWithContext(context.Background(), event)
|
||||
}
|
||||
|
||||
// SendEventWithContext assembles a new packet out of Event and sends it to the remote server.
|
||||
func (t *HTTPTransport) SendEventWithContext(ctx context.Context, event *Event) {
|
||||
if t.dsn == nil {
|
||||
return
|
||||
}
|
||||
|
||||
category := categoryFor(event.Type)
|
||||
category := event.toCategory()
|
||||
|
||||
if t.disabled(category) {
|
||||
return
|
||||
}
|
||||
|
||||
request, err := getRequestFromEvent(event, t.dsn)
|
||||
request, err := getRequestFromEvent(ctx, event, t.dsn)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -383,17 +425,17 @@ func (t *HTTPTransport) SendEvent(event *Event) {
|
||||
if event.Type == transactionType {
|
||||
eventType = "transaction"
|
||||
} else {
|
||||
eventType = fmt.Sprintf("%s event", event.Level)
|
||||
eventType = fmt.Sprintf("%s event", event.Type)
|
||||
}
|
||||
Logger.Printf(
|
||||
debuglog.Printf(
|
||||
"Sending %s [%s] to %s project: %s",
|
||||
eventType,
|
||||
event.EventID,
|
||||
t.dsn.host,
|
||||
t.dsn.projectID,
|
||||
t.dsn.GetHost(),
|
||||
t.dsn.GetProjectID(),
|
||||
)
|
||||
default:
|
||||
Logger.Println("Event dropped due to transport buffer being full.")
|
||||
debuglog.Println("Event dropped due to transport buffer being full.")
|
||||
}
|
||||
|
||||
t.buffer <- b
|
||||
@@ -410,8 +452,17 @@ func (t *HTTPTransport) SendEvent(event *Event) {
|
||||
// have the SDK send events over the network synchronously, configure it to use
|
||||
// the HTTPSyncTransport in the call to Init.
|
||||
func (t *HTTPTransport) Flush(timeout time.Duration) bool {
|
||||
toolate := time.After(timeout)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
return t.FlushWithContext(ctx)
|
||||
}
|
||||
|
||||
// FlushWithContext works like Flush, but it accepts a context.Context instead of a timeout.
|
||||
func (t *HTTPTransport) FlushWithContext(ctx context.Context) bool {
|
||||
return t.flushInternal(ctx.Done())
|
||||
}
|
||||
|
||||
func (t *HTTPTransport) flushInternal(timeout <-chan struct{}) bool {
|
||||
// Wait until processing the current batch has started or the timeout.
|
||||
//
|
||||
// We must wait until the worker has seen the current batch, because it is
|
||||
@@ -419,6 +470,7 @@ func (t *HTTPTransport) Flush(timeout time.Duration) bool {
|
||||
// possible execution flow in which b.done is never closed, and the only way
|
||||
// out of Flush would be waiting for the timeout, which is undesired.
|
||||
var b batch
|
||||
|
||||
for {
|
||||
select {
|
||||
case b = <-t.buffer:
|
||||
@@ -428,7 +480,7 @@ func (t *HTTPTransport) Flush(timeout time.Duration) bool {
|
||||
default:
|
||||
t.buffer <- b
|
||||
}
|
||||
case <-toolate:
|
||||
case <-timeout:
|
||||
goto fail
|
||||
}
|
||||
}
|
||||
@@ -447,17 +499,28 @@ started:
|
||||
// Wait until the current batch is done or the timeout.
|
||||
select {
|
||||
case <-b.done:
|
||||
Logger.Println("Buffer flushed successfully.")
|
||||
debuglog.Println("Buffer flushed successfully.")
|
||||
return true
|
||||
case <-toolate:
|
||||
case <-timeout:
|
||||
goto fail
|
||||
}
|
||||
|
||||
fail:
|
||||
Logger.Println("Buffer flushing reached the timeout.")
|
||||
debuglog.Println("Buffer flushing was canceled or timed out.")
|
||||
return false
|
||||
}
|
||||
|
||||
// Close will terminate events sending loop.
|
||||
// It useful to prevent goroutines leak in case of multiple HTTPTransport instances initiated.
|
||||
//
|
||||
// Close should be called after Flush and before terminating the program
|
||||
// otherwise some events may be lost.
|
||||
func (t *HTTPTransport) Close() {
|
||||
t.closeOnce.Do(func() {
|
||||
close(t.done)
|
||||
})
|
||||
}
|
||||
|
||||
func (t *HTTPTransport) worker() {
|
||||
for b := range t.buffer {
|
||||
// Signal that processing of the current batch has started.
|
||||
@@ -468,23 +531,44 @@ func (t *HTTPTransport) worker() {
|
||||
t.buffer <- b
|
||||
|
||||
// Process all batch items.
|
||||
for item := range b.items {
|
||||
if t.disabled(item.category) {
|
||||
continue
|
||||
}
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-t.done:
|
||||
return
|
||||
case item, open := <-b.items:
|
||||
if !open {
|
||||
break loop
|
||||
}
|
||||
if t.disabled(item.category) {
|
||||
continue
|
||||
}
|
||||
|
||||
response, err := t.client.Do(item.request)
|
||||
if err != nil {
|
||||
Logger.Printf("There was an issue with sending an event: %v", err)
|
||||
continue
|
||||
response, err := t.client.Do(item.request)
|
||||
if err != nil {
|
||||
debuglog.Printf("There was an issue with sending an event: %v", err)
|
||||
continue
|
||||
}
|
||||
if response.StatusCode >= 400 && response.StatusCode <= 599 {
|
||||
b, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
debuglog.Printf("Error while reading response code: %v", err)
|
||||
}
|
||||
debuglog.Printf("Sending %s failed with the following error: %s", eventType, string(b))
|
||||
}
|
||||
|
||||
t.mu.Lock()
|
||||
if t.limits == nil {
|
||||
t.limits = make(ratelimit.Map)
|
||||
}
|
||||
t.limits.Merge(ratelimit.FromResponse(response))
|
||||
t.mu.Unlock()
|
||||
|
||||
// Drain body up to a limit and close it, allowing the
|
||||
// transport to reuse TCP connections.
|
||||
_, _ = io.CopyN(io.Discard, response.Body, maxDrainResponseBytes)
|
||||
response.Body.Close()
|
||||
}
|
||||
t.mu.Lock()
|
||||
t.limits.Merge(ratelimit.FromResponse(response))
|
||||
t.mu.Unlock()
|
||||
// Drain body up to a limit and close it, allowing the
|
||||
// transport to reuse TCP connections.
|
||||
_, _ = io.CopyN(io.Discard, response.Body, maxDrainResponseBytes)
|
||||
response.Body.Close()
|
||||
}
|
||||
|
||||
// Signal that processing of the batch is done.
|
||||
@@ -497,7 +581,7 @@ func (t *HTTPTransport) disabled(c ratelimit.Category) bool {
|
||||
defer t.mu.RUnlock()
|
||||
disabled := t.limits.IsRateLimited(c)
|
||||
if disabled {
|
||||
Logger.Printf("Too many requests for %q, backing off till: %v", c, t.limits.Deadline(c))
|
||||
debuglog.Printf("Too many requests for %q, backing off till: %v", c, t.limits.Deadline(c))
|
||||
}
|
||||
return disabled
|
||||
}
|
||||
@@ -543,7 +627,7 @@ func NewHTTPSyncTransport() *HTTPSyncTransport {
|
||||
func (t *HTTPSyncTransport) Configure(options ClientOptions) {
|
||||
dsn, err := NewDsn(options.Dsn)
|
||||
if err != nil {
|
||||
Logger.Printf("%v\n", err)
|
||||
debuglog.Printf("%v\n", err)
|
||||
return
|
||||
}
|
||||
t.dsn = dsn
|
||||
@@ -567,41 +651,67 @@ func (t *HTTPSyncTransport) Configure(options ClientOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
// SendEvent assembles a new packet out of Event and sends it to remote server.
|
||||
// SendEvent assembles a new packet out of Event and sends it to the remote server.
|
||||
func (t *HTTPSyncTransport) SendEvent(event *Event) {
|
||||
t.SendEventWithContext(context.Background(), event)
|
||||
}
|
||||
|
||||
func (t *HTTPSyncTransport) Close() {}
|
||||
|
||||
// SendEventWithContext assembles a new packet out of Event and sends it to the remote server.
|
||||
func (t *HTTPSyncTransport) SendEventWithContext(ctx context.Context, event *Event) {
|
||||
if t.dsn == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if t.disabled(categoryFor(event.Type)) {
|
||||
if t.disabled(event.toCategory()) {
|
||||
return
|
||||
}
|
||||
|
||||
request, err := getRequestFromEvent(event, t.dsn)
|
||||
request, err := getRequestFromEvent(ctx, event, t.dsn)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var eventType string
|
||||
if event.Type == transactionType {
|
||||
eventType = "transaction"
|
||||
} else {
|
||||
eventType = fmt.Sprintf("%s event", event.Level)
|
||||
var eventIdentifier string
|
||||
switch event.Type {
|
||||
case errorType:
|
||||
eventIdentifier = "error"
|
||||
case transactionType:
|
||||
eventIdentifier = "transaction"
|
||||
case logEvent.Type:
|
||||
eventIdentifier = fmt.Sprintf("%d log events", len(event.Logs))
|
||||
case traceMetricEvent.Type:
|
||||
eventIdentifier = fmt.Sprintf("%d metric events", len(event.Metrics))
|
||||
default:
|
||||
eventIdentifier = fmt.Sprintf("%s event", event.Type)
|
||||
}
|
||||
Logger.Printf(
|
||||
debuglog.Printf(
|
||||
"Sending %s [%s] to %s project: %s",
|
||||
eventType,
|
||||
eventIdentifier,
|
||||
event.EventID,
|
||||
t.dsn.host,
|
||||
t.dsn.projectID,
|
||||
t.dsn.GetHost(),
|
||||
t.dsn.GetProjectID(),
|
||||
)
|
||||
|
||||
response, err := t.client.Do(request)
|
||||
if err != nil {
|
||||
Logger.Printf("There was an issue with sending an event: %v", err)
|
||||
debuglog.Printf("There was an issue with sending an event: %v", err)
|
||||
return
|
||||
}
|
||||
if response.StatusCode >= 400 && response.StatusCode <= 599 {
|
||||
b, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
debuglog.Printf("Error while reading response code: %v", err)
|
||||
}
|
||||
debuglog.Printf("Sending %s failed with the following error: %s", eventIdentifier, string(b))
|
||||
}
|
||||
|
||||
t.mu.Lock()
|
||||
if t.limits == nil {
|
||||
t.limits = make(ratelimit.Map)
|
||||
}
|
||||
|
||||
t.limits.Merge(ratelimit.FromResponse(response))
|
||||
t.mu.Unlock()
|
||||
|
||||
@@ -616,12 +726,17 @@ func (t *HTTPSyncTransport) Flush(_ time.Duration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// FlushWithContext is a no-op for HTTPSyncTransport. It always returns true immediately.
|
||||
func (t *HTTPSyncTransport) FlushWithContext(_ context.Context) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (t *HTTPSyncTransport) disabled(c ratelimit.Category) bool {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
disabled := t.limits.IsRateLimited(c)
|
||||
if disabled {
|
||||
Logger.Printf("Too many requests for %q, backing off till: %v", c, t.limits.Deadline(c))
|
||||
debuglog.Printf("Too many requests for %q, backing off till: %v", c, t.limits.Deadline(c))
|
||||
}
|
||||
return disabled
|
||||
}
|
||||
@@ -637,13 +752,98 @@ type noopTransport struct{}
|
||||
var _ Transport = noopTransport{}
|
||||
|
||||
func (noopTransport) Configure(ClientOptions) {
|
||||
Logger.Println("Sentry client initialized with an empty DSN. Using noopTransport. No events will be delivered.")
|
||||
debuglog.Println("Sentry client initialized with an empty DSN. Using noopTransport. No events will be delivered.")
|
||||
}
|
||||
|
||||
func (noopTransport) SendEvent(*Event) {
|
||||
Logger.Println("Event dropped due to noopTransport usage.")
|
||||
debuglog.Println("Event dropped due to noopTransport usage.")
|
||||
}
|
||||
|
||||
func (noopTransport) Flush(time.Duration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (noopTransport) FlushWithContext(context.Context) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (noopTransport) Close() {}
|
||||
|
||||
// ================================
|
||||
// Internal Transport Adapters
|
||||
// ================================
|
||||
|
||||
// newInternalAsyncTransport creates a new AsyncTransport from internal/http
|
||||
// wrapped to satisfy the Transport interface.
|
||||
//
|
||||
// This is not yet exposed in the public API and is for internal experimentation.
|
||||
func newInternalAsyncTransport() Transport {
|
||||
return &internalAsyncTransportAdapter{}
|
||||
}
|
||||
|
||||
// internalAsyncTransportAdapter wraps the internal AsyncTransport to implement
|
||||
// the root-level Transport interface.
|
||||
type internalAsyncTransportAdapter struct {
|
||||
transport protocol.TelemetryTransport
|
||||
dsn *protocol.Dsn
|
||||
}
|
||||
|
||||
func (a *internalAsyncTransportAdapter) Configure(options ClientOptions) {
|
||||
transportOptions := httpinternal.TransportOptions{
|
||||
Dsn: options.Dsn,
|
||||
HTTPClient: options.HTTPClient,
|
||||
HTTPTransport: options.HTTPTransport,
|
||||
HTTPProxy: options.HTTPProxy,
|
||||
HTTPSProxy: options.HTTPSProxy,
|
||||
CaCerts: options.CaCerts,
|
||||
}
|
||||
|
||||
a.transport = httpinternal.NewAsyncTransport(transportOptions)
|
||||
|
||||
if options.Dsn != "" {
|
||||
dsn, err := protocol.NewDsn(options.Dsn)
|
||||
if err != nil {
|
||||
debuglog.Printf("Failed to parse DSN in adapter: %v\n", err)
|
||||
} else {
|
||||
a.dsn = dsn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *internalAsyncTransportAdapter) SendEvent(event *Event) {
|
||||
header := &protocol.EnvelopeHeader{EventID: string(event.EventID), SentAt: time.Now(), Sdk: &protocol.SdkInfo{Name: event.Sdk.Name, Version: event.Sdk.Version}}
|
||||
if a.dsn != nil {
|
||||
header.Dsn = a.dsn.String()
|
||||
}
|
||||
if header.EventID == "" {
|
||||
header.EventID = protocol.GenerateEventID()
|
||||
}
|
||||
envelope := protocol.NewEnvelope(header)
|
||||
item, err := event.ToEnvelopeItem()
|
||||
if err != nil {
|
||||
debuglog.Printf("Failed to convert event to envelope item: %v", err)
|
||||
return
|
||||
}
|
||||
envelope.AddItem(item)
|
||||
|
||||
for _, attachment := range event.Attachments {
|
||||
attachmentItem := protocol.NewAttachmentItem(attachment.Filename, attachment.ContentType, attachment.Payload)
|
||||
envelope.AddItem(attachmentItem)
|
||||
}
|
||||
|
||||
if err := a.transport.SendEnvelope(envelope); err != nil {
|
||||
debuglog.Printf("Error sending envelope: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *internalAsyncTransportAdapter) Flush(timeout time.Duration) bool {
|
||||
return a.transport.Flush(timeout)
|
||||
}
|
||||
|
||||
func (a *internalAsyncTransportAdapter) FlushWithContext(ctx context.Context) bool {
|
||||
return a.transport.FlushWithContext(ctx)
|
||||
}
|
||||
|
||||
func (a *internalAsyncTransportAdapter) Close() {
|
||||
a.transport.Close()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user