From c79b3b0c0f9a363d616b6f27bdd07461ee68eaf7 Mon Sep 17 00:00:00 2001 From: Neur0toxine Date: Thu, 12 Nov 2020 10:23:27 +0300 Subject: [PATCH] Sentry update, go 1.15 support * Clone() method in Localizer component allows to clone it just like LocalizationMiddleware does. * RavenClientInterface contains all *raven.Client method, which allows external use without type casting. * Tests and godoc fix for Go 1.15. --- .travis.yml | 1 + core/localizer.go | 28 +++++++++++++++-------- core/localizer_test.go | 13 +++++++++++ core/sentry_test.go | 4 +++- core/stacktrace/raven_client_interface.go | 21 +++++++++++++++++ 5 files changed, 57 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2a5133b..80853a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ go: - '1.12' - '1.13' - '1.14' + - '1.15' before_install: - go mod tidy script: diff --git a/core/localizer.go b/core/localizer.go index 084895a..68f6f4a 100644 --- a/core/localizer.go +++ b/core/localizer.go @@ -85,6 +85,23 @@ func DefaultLocalizerMatcher() language.Matcher { return language.NewMatcher(DefaultLanguages) } +// Clone *core.Localizer. Clone shares it's translations with the parent localizer. Language tag will not be shared. +// Because of that you can change clone's language without affecting parent localizer. +// This method should be used when LocalizationMiddleware is not feasible (outside of *gin.HandlerFunc). +func (l *Localizer) Clone() *Localizer { + clone := &Localizer{ + i18nStorage: l.i18nStorage, + TranslationsBox: l.TranslationsBox, + LocaleMatcher: l.LocaleMatcher, + LanguageTag: l.LanguageTag, + TranslationsPath: l.TranslationsPath, + loadMutex: l.loadMutex, + } + clone.SetLanguage(DefaultLanguage) + + return clone +} + // LocalizationMiddleware returns gin.HandlerFunc which will set localizer language by Accept-Language header // Result Localizer instance will share it's internal data (translations, bundles, etc) with instance which was used // to append middleware to gin. @@ -92,18 +109,11 @@ func DefaultLocalizerMatcher() language.Matcher { // i18n.Bundle methods (those aren't goroutine-safe to use). // Usage: // engine := gin.New() -// localizer := NewLocalizer("en", DefaultLocalizerBundle(), DefaultLocalizerMatcher(), "translations") +// localizer := NewLocalizer("en", DefaultLocalizerMatcher(), "translations") // engine.Use(localizer.LocalizationMiddleware()) func (l *Localizer) LocalizationMiddleware() gin.HandlerFunc { return func(c *gin.Context) { - clone := &Localizer{ - i18nStorage: l.i18nStorage, - TranslationsBox: l.TranslationsBox, - LocaleMatcher: l.LocaleMatcher, - LanguageTag: l.LanguageTag, - TranslationsPath: l.TranslationsPath, - loadMutex: l.loadMutex, - } + clone := l.Clone() clone.SetLocale(c.GetHeader("Accept-Language")) c.Set(LocalizerContextKey, clone) } diff --git a/core/localizer_test.go b/core/localizer_test.go index 6ffba21..f05dd80 100644 --- a/core/localizer_test.go +++ b/core/localizer_test.go @@ -157,6 +157,19 @@ func (l *LocalizerTest) Test_GetLocalizedMessage() { assert.Equal(l.T(), "Test message", message) } +func (l *LocalizerTest) Test_Clone() { + defer func() { + require.Nil(l.T(), recover()) + }() + + localizer := l.localizer.Clone() + localizer.SetLanguage(language.Russian) + + assert.NotEqual(l.T(), l.localizer.LanguageTag, localizer.LanguageTag) + assert.Equal(l.T(), "Test message", l.localizer.GetLocalizedMessage("message")) + assert.Equal(l.T(), "Тестовое сообщение", localizer.GetLocalizedMessage("message")) +} + func (l *LocalizerTest) Test_GetLocalizedTemplateMessage() { defer func() { require.Nil(l.T(), recover()) diff --git a/core/sentry_test.go b/core/sentry_test.go index 1600f7c..7df14ba 100644 --- a/core/sentry_test.go +++ b/core/sentry_test.go @@ -6,6 +6,7 @@ import ( "math/rand" "net/http" "net/http/httptest" + "strconv" "sync" "testing" "time" @@ -61,6 +62,7 @@ func (r ravenPacket) getRequest() (*raven.Http, bool) { } type ravenClientMock struct { + raven.Client captured []ravenPacket mu sync.RWMutex wg sync.WaitGroup @@ -92,7 +94,7 @@ func (r *ravenClientMock) CaptureMessageAndWait(message string, tags map[string] r.mu.Lock() defer r.mu.Unlock() defer r.wg.Done() - eventID := string(rand.Uint64()) + eventID := strconv.FormatUint(rand.Uint64(), 10) r.captured = append(r.captured, ravenPacket{ EventID: eventID, Message: message, diff --git a/core/stacktrace/raven_client_interface.go b/core/stacktrace/raven_client_interface.go index d3c916d..ec281d8 100644 --- a/core/stacktrace/raven_client_interface.go +++ b/core/stacktrace/raven_client_interface.go @@ -4,7 +4,28 @@ import "github.com/getsentry/raven-go" // RavenClientInterface includes all necessary calls from *raven.Client. Therefore, it can be mocked or replaced. type RavenClientInterface interface { + SetIgnoreErrors(errs []string) error + SetDSN(dsn string) error + SetRelease(release string) + SetEnvironment(environment string) + SetDefaultLoggerName(name string) + SetSampleRate(rate float32) error + Capture(packet *raven.Packet, captureTags map[string]string) (eventID string, ch chan error) + CaptureMessage(message string, tags map[string]string, interfaces ...raven.Interface) string CaptureMessageAndWait(message string, tags map[string]string, interfaces ...raven.Interface) string + CaptureError(err error, tags map[string]string, interfaces ...raven.Interface) string CaptureErrorAndWait(err error, tags map[string]string, interfaces ...raven.Interface) string + CapturePanic(f func(), tags map[string]string, interfaces ...raven.Interface) (err interface{}, errorID string) + CapturePanicAndWait(f func(), tags map[string]string, interfaces ...raven.Interface) (err interface{}, errorID string) + Close() + Wait() + URL() string + ProjectID() string + Release() string IncludePaths() []string + SetIncludePaths(p []string) + SetUserContext(u *raven.User) + SetHttpContext(h *raven.Http) + SetTagsContext(t map[string]string) + ClearContext() }