Skip to content

Commit

Permalink
Set SDK Name According Framework being used (#694)
Browse files Browse the repository at this point in the history
Co-authored-by: Anton Ovchinnikov <anton@tonyo.info>
  • Loading branch information
cleptric and tonyo committed Aug 29, 2023
1 parent 82a00ab commit 5f86090
Show file tree
Hide file tree
Showing 14 changed files with 93 additions and 20 deletions.
34 changes: 28 additions & 6 deletions client.go
Expand Up @@ -17,6 +17,9 @@ import (
"github.com/getsentry/sentry-go/internal/debug"
)

// The identifier of the SDK.
const sdkIdentifier = "sentry.go"

// maxErrorDepth is the maximum number of errors reported in a chain of errors.
// This protects the SDK from an arbitrarily long chain of wrapped errors.
//
Expand Down Expand Up @@ -223,10 +226,13 @@ type ClientOptions struct {
// Client is the underlying processor that is used by the main API and Hub
// instances. It must be created with NewClient.
type Client struct {
mu sync.RWMutex
options ClientOptions
dsn *Dsn
eventProcessors []EventProcessor
integrations []Integration
sdkIdentifier string
sdkVersion string
// Transport is read-only. Replacing the transport of an existing client is
// not supported, create a new client instead.
Transport Transport
Expand Down Expand Up @@ -323,8 +329,10 @@ func NewClient(options ClientOptions) (*Client, error) {
}

client := Client{
options: options,
dsn: dsn,
options: options,
dsn: dsn,
sdkIdentifier: sdkIdentifier,
sdkVersion: SDKVersion,
}

client.setupTransport()
Expand Down Expand Up @@ -396,7 +404,7 @@ func (client *Client) AddEventProcessor(processor EventProcessor) {
}

// Options return ClientOptions for the current Client.
func (client Client) Options() ClientOptions {
func (client *Client) Options() ClientOptions {
// Note: internally, consider using `client.options` instead of `client.Options()` to avoid copying the object each time.
return client.options
}
Expand Down Expand Up @@ -561,6 +569,20 @@ func (client *Client) EventFromCheckIn(checkIn *CheckIn, monitorConfig *MonitorC
return event
}

func (client *Client) SetSDKIdentifier(identifier string) {
client.mu.Lock()
defer client.mu.Unlock()

client.sdkIdentifier = identifier
}

func (client *Client) GetSDKIdentifier() string {
client.mu.RLock()
defer client.mu.RUnlock()

return client.sdkIdentifier
}

// reverse reverses the slice a in place.
func reverse(a []Exception) {
for i := len(a)/2 - 1; i >= 0; i-- {
Expand Down Expand Up @@ -646,7 +668,7 @@ func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventMod

event.Platform = "go"
event.Sdk = SdkInfo{
Name: SDKIdentifier,
Name: client.GetSDKIdentifier(),
Version: SDKVersion,
Integrations: client.listIntegrations(),
Packages: []SdkPackage{{
Expand Down Expand Up @@ -687,15 +709,15 @@ func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventMod
return event
}

func (client Client) listIntegrations() []string {
func (client *Client) listIntegrations() []string {
integrations := make([]string, len(client.integrations))
for i, integration := range client.integrations {
integrations[i] = integration.Name()
}
return integrations
}

func (client Client) integrationAlreadyInstalled(name string) bool {
func (client *Client) integrationAlreadyInstalled(name string) bool {
for _, integration := range client.integrations {
if integration.Name() == name {
return true
Expand Down
8 changes: 8 additions & 0 deletions client_test.go
Expand Up @@ -717,6 +717,14 @@ func TestCustomMaxSpansProperty(t *testing.T) {
assertEqual(t, properClient.Options().MaxSpans, 3000)
}

func TestSDKIdentifier(t *testing.T) {
client, _, _ := setupClientTest()
assertEqual(t, client.GetSDKIdentifier(), "sentry.go")

client.SetSDKIdentifier("sentry.go.test")
assertEqual(t, client.GetSDKIdentifier(), "sentry.go.test")
}

func TestClientSetsUpTransport(t *testing.T) {
client, _ := NewClient(ClientOptions{Dsn: testDsn})
require.IsType(t, &HTTPTransport{}, client.Transport)
Expand Down
1 change: 1 addition & 0 deletions dsn.go
Expand Up @@ -197,6 +197,7 @@ func (dsn Dsn) GetAPIURL() *url.URL {
}

// RequestHeaders returns all the necessary headers that have to be used in the transport.
// Deprecated: To be removed after 0.25.0, but no earlier than December 1, 2023. Requests to /envelope are authenticated using the DSN in the envelope header itself.
func (dsn Dsn) RequestHeaders() map[string]string {
auth := fmt.Sprintf("Sentry sentry_version=%s, sentry_timestamp=%d, "+
"sentry_client=sentry.go/%s, sentry_key=%s", apiVersion, time.Now().Unix(), Version, dsn.publicKey)
Expand Down
6 changes: 6 additions & 0 deletions echo/sentryecho.go
Expand Up @@ -9,6 +9,9 @@ import (
"github.com/labstack/echo/v4"
)

// The identifier of the Echo SDK.
const sdkIdentifier = "sentry.go.echo"

const valuesKey = "sentry"

type handler struct {
Expand Down Expand Up @@ -49,6 +52,9 @@ func (h *handler) handle(next echo.HandlerFunc) echo.HandlerFunc {
if hub == nil {
hub = sentry.CurrentHub().Clone()
}

hub.Client().SetSDKIdentifier(sdkIdentifier)

hub.Scope().SetRequest(ctx.Request())
ctx.Set(valuesKey, hub)
defer h.recoverWithSentry(hub, ctx.Request())
Expand Down
6 changes: 6 additions & 0 deletions fasthttp/sentryfasthttp.go
Expand Up @@ -13,6 +13,9 @@ import (
"github.com/valyala/fasthttp"
)

// The identifier of the FastHTTP SDK.
const sdkIdentifier = "sentry.go.fasthttp"

type contextKey int

const ContextKey = contextKey(1)
Expand Down Expand Up @@ -58,6 +61,9 @@ func (h *Handler) Handle(handler fasthttp.RequestHandler) fasthttp.RequestHandle
// standard net/http.Request and because fasthttp.RequestCtx implements
// context.Context but requires string keys.
hub := sentry.CurrentHub().Clone()

hub.Client().SetSDKIdentifier(sdkIdentifier)

scope := hub.Scope()
scope.SetRequest(convert(ctx))
scope.SetRequestBody(ctx.Request.Body())
Expand Down
6 changes: 6 additions & 0 deletions gin/sentrygin.go
Expand Up @@ -13,6 +13,9 @@ import (
"github.com/gin-gonic/gin"
)

// The identifier of the Gin SDK.
const sdkIdentifier = "sentry.go.gin"

const valuesKey = "sentry"

type handler struct {
Expand Down Expand Up @@ -54,6 +57,9 @@ func (h *handler) handle(c *gin.Context) {
hub = sentry.CurrentHub().Clone()
ctx = sentry.SetHubOnContext(ctx, hub)
}

hub.Client().SetSDKIdentifier(sdkIdentifier)

options := []sentry.SpanOption{
sentry.WithOpName("http.server"),
sentry.ContinueFromRequest(c.Request),
Expand Down
6 changes: 6 additions & 0 deletions http/sentryhttp.go
Expand Up @@ -11,6 +11,9 @@ import (
"github.com/getsentry/sentry-go"
)

// The identifier of the Gin SDK.
const sdkIdentifier = "sentry.go.http"

// A Handler is an HTTP middleware factory that provides integration with
// Sentry.
type Handler struct {
Expand Down Expand Up @@ -86,6 +89,9 @@ func (h *Handler) handle(handler http.Handler) http.HandlerFunc {
hub = sentry.CurrentHub().Clone()
ctx = sentry.SetHubOnContext(ctx, hub)
}

hub.Client().SetSDKIdentifier(sdkIdentifier)

options := []sentry.SpanOption{
sentry.WithOpName("http.server"),
sentry.ContinueFromRequest(r),
Expand Down
6 changes: 6 additions & 0 deletions iris/sentryiris.go
Expand Up @@ -12,6 +12,9 @@ import (
"github.com/kataras/iris/v12"
)

// The identifier of the Iris SDK.
const sdkIdentifier = "sentry.go.iris"

const valuesKey = "sentry"

type handler struct {
Expand Down Expand Up @@ -51,6 +54,9 @@ func (h *handler) handle(ctx iris.Context) {
if hub == nil {
hub = sentry.CurrentHub().Clone()
}

hub.Client().SetSDKIdentifier(sdkIdentifier)

hub.Scope().SetRequest(ctx.Request())
ctx.Values().Set(valuesKey, hub)
defer h.recoverWithSentry(hub, ctx.Request())
Expand Down
6 changes: 6 additions & 0 deletions logrus/logrusentry.go
Expand Up @@ -10,6 +10,9 @@ import (
"github.com/sirupsen/logrus"
)

// The identifier of the Logrus SDK.
const sdkIdentifier = "sentry.go.logrus"

// These default log field keys are used to pass specific metadata in a way that
// Sentry understands. If they are found in the log fields, and the value is of
// the expected datatype, it will be converted from a generic field, into Sentry
Expand Down Expand Up @@ -52,6 +55,9 @@ func New(levels []logrus.Level, opts sentry.ClientOptions) (*Hook, error) {
if err != nil {
return nil, err
}

client.SetSDKIdentifier(sdkIdentifier)

return NewFromClient(levels, client), nil
}

Expand Down
6 changes: 6 additions & 0 deletions martini/sentrymartini.go
Expand Up @@ -9,6 +9,9 @@ import (
"github.com/go-martini/martini"
)

// The identifier of the Martini SDK.
const sdkIdentifier = "sentry.go.martini"

type handler struct {
repanic bool
waitForDelivery bool
Expand Down Expand Up @@ -46,6 +49,9 @@ func (h *handler) handle(rw http.ResponseWriter, r *http.Request, ctx martini.Co
if hub == nil {
hub = sentry.CurrentHub().Clone()
}

hub.Client().SetSDKIdentifier(sdkIdentifier)

hub.Scope().SetRequest(r)
ctx.Map(hub)
defer h.recoverWithSentry(hub, r)
Expand Down
6 changes: 6 additions & 0 deletions negroni/sentrynegroni.go
Expand Up @@ -9,6 +9,9 @@ import (
"github.com/urfave/negroni"
)

// The identifier of the Negroni SDK.
const sdkIdentifier = "sentry.go.negroni"

type handler struct {
repanic bool
waitForDelivery bool
Expand Down Expand Up @@ -47,6 +50,9 @@ func (h *handler) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.H
if hub == nil {
hub = sentry.CurrentHub().Clone()
}

hub.Client().SetSDKIdentifier(sdkIdentifier)

hub.Scope().SetRequest(r)
ctx = sentry.SetHubOnContext(
context.WithValue(ctx, sentry.RequestContextKey, r),
Expand Down
10 changes: 5 additions & 5 deletions sentry.go
Expand Up @@ -5,22 +5,22 @@ import (
"time"
)

// Deprecated: Use SDKVersion instead.
// The version of the SDK.
// Deprecated: To be removed in 0.25.0. Use SDKVersion instead.
const Version = SDKVersion

// Version is the version of the SDK.
// The version of the SDK.
const SDKVersion = "0.23.0"

// The identifier of the SDK.
// Deprecated: To be removed in 0.25.0. Use Client.GetSDKIdentifier() instead.
const SDKIdentifier = "sentry.go"

// apiVersion is the minimum version of the Sentry API compatible with the
// sentry-go SDK.
// Deprecated: To be removed in 0.25.0.
const apiVersion = "7"

// userAgent is the User-Agent of outgoing HTTP requests.
const userAgent = "sentry-go/" + SDKVersion

// Init initializes the SDK with options. The returned error is non-nil if
// options is invalid, for instance if a malformed DSN is provided.
func Init(options ClientOptions) error {
Expand Down
11 changes: 2 additions & 9 deletions transport.go
Expand Up @@ -209,7 +209,8 @@ func envelopeFromBody(event *Event, dsn *Dsn, sentAt time.Time, body json.RawMes
func getRequestFromEvent(event *Event, dsn *Dsn) (r *http.Request, err error) {
defer func() {
if r != nil {
r.Header.Set("User-Agent", userAgent)
r.Header.Set("User-Agent", fmt.Sprintf("%s/%s", event.Sdk.Name, event.Sdk.Version))
r.Header.Set("Content-Type", "application/x-sentry-envelope")
}
}()
body := getRequestBodyFromEvent(event)
Expand Down Expand Up @@ -348,10 +349,6 @@ func (t *HTTPTransport) SendEvent(event *Event) {
return
}

for headerKey, headerValue := range t.dsn.RequestHeaders() {
request.Header.Set(headerKey, headerValue)
}

// <-t.buffer is equivalent to acquiring a lock to access the current batch.
// A few lines below, t.buffer <- b releases the lock.
//
Expand Down Expand Up @@ -573,10 +570,6 @@ func (t *HTTPSyncTransport) SendEvent(event *Event) {
return
}

for headerKey, headerValue := range t.dsn.RequestHeaders() {
request.Header.Set(headerKey, headerValue)
}

var eventType string
if event.Type == transactionType {
eventType = "transaction"
Expand Down
1 change: 1 addition & 0 deletions transport_test.go
Expand Up @@ -357,6 +357,7 @@ func TestGetRequestFromEvent(t *testing.T) {
t.Errorf("Incorrect API URL. want: %s, got: %s", test.apiURL, req.URL.String())
}

userAgent := fmt.Sprintf("%s/%s", test.event.Sdk.Name, test.event.Sdk.Version)
if ua := req.UserAgent(); ua != userAgent {
t.Errorf("got User-Agent = %q, want %q", ua, userAgent)
}
Expand Down

0 comments on commit 5f86090

Please sign in to comment.