Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set SDK Name According Framework being used #694

Merged
merged 10 commits into from Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 36 additions & 7 deletions client.go
Expand Up @@ -17,6 +17,12 @@ import (
"github.com/getsentry/sentry-go/internal/debug"
)

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

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

// 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 +229,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 +332,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 +407,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 +572,24 @@ 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
}

func (client *Client) GetSDKVersion() string {
return client.sdkVersion
}

// 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,8 +675,8 @@ func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventMod

event.Platform = "go"
event.Sdk = SdkInfo{
Name: SDKIdentifier,
Version: SDKVersion,
Name: client.GetSDKIdentifier(),
Version: client.GetSDKVersion(),
Integrations: client.listIntegrations(),
Packages: []SdkPackage{{
Name: "sentry-go",
Expand Down Expand Up @@ -687,15 +716,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 @@ -713,3 +713,11 @@ 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")
}
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 in 0.25.0. Requests to /envelope are authenticated using the DSN in the envelope header itself.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cleptric marked this conversation as resolved.
Show resolved Hide resolved
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 @@
"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,8 +52,11 @@
if hub == nil {
hub = sentry.CurrentHub().Clone()
}

hub.Client().SetSDKIdentifier(sdkIdentifier)

hub.Scope().SetRequest(ctx.Request())
ctx.Set(valuesKey, hub)

Check warning on line 59 in echo/sentryecho.go

View check run for this annotation

Codecov / codecov/patch

echo/sentryecho.go#L56-L59

Added lines #L56 - L59 were not covered by tests
defer h.recoverWithSentry(hub, ctx.Request())
return next(ctx)
}
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 @@
"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 @@
if hub == nil {
hub = sentry.CurrentHub().Clone()
}

hub.Client().SetSDKIdentifier(sdkIdentifier)

Check warning on line 54 in martini/sentrymartini.go

View check run for this annotation

Codecov / codecov/patch

martini/sentrymartini.go#L53-L54

Added lines #L53 - L54 were not covered by tests
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 @@
"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 @@
if hub == nil {
hub = sentry.CurrentHub().Clone()
}

hub.Client().SetSDKIdentifier(sdkIdentifier)

Check warning on line 55 in negroni/sentrynegroni.go

View check run for this annotation

Codecov / codecov/patch

negroni/sentrynegroni.go#L54-L55

Added lines #L54 - L55 were not covered by tests
hub.Scope().SetRequest(r)
ctx = sentry.SetHubOnContext(
context.WithValue(ctx, sentry.RequestContextKey, r),
Expand Down
3 changes: 3 additions & 0 deletions scripts/bump-version.sh
Expand Up @@ -21,8 +21,11 @@ function replace() {
grep "$2" $3 # verify that replacement was successful
}

# SDKVersion is deprecated, remove prior 0.25.0
replace "const SDKVersion = \"[\w.-]+\"" "const SDKVersion = \"$NEW_VERSION\"" ./sentry.go

replace "const sdkVersion = \"[\w.-]+\"" "const sdkVersion = \"$NEW_VERSION\"" ./client.go

# Replace root module versions in submodules
GO_MOD_FILES=$(find . -type f -name 'go.mod' -not -path ./go.mod)
for GO_MOD in ${GO_MOD_FILES}; do
Expand Down
11 changes: 6 additions & 5 deletions sentry.go
Expand Up @@ -5,22 +5,23 @@ import (
"time"
)

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

// Version is the version of the SDK.
// The version of the SDK.
// Deprecated: To be removed in 0.25.0. Use Client.GetSDKVersion() instead.
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")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}()
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 @@ -356,6 +356,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