mirror of
https://github.com/retailcrm/mg-transport-core.git
synced 2024-11-25 14:46:02 +03:00
Merge pull request #1 from Neur0toxine/master
[improvement] fixes for several non-severe mistakes
This commit is contained in:
commit
868a927690
@ -1,3 +1,3 @@
|
|||||||
## MG Transport Library
|
## MG Transport Library
|
||||||
|
|
||||||
This library provides different functions like error-reporting, loggingm localization, etc. in order to make it easier to create transports
|
This library provides different functions like error-reporting, logging, localization, etc. in order to make it easier to create transports
|
||||||
|
@ -3,11 +3,23 @@ package core
|
|||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
credentialsTransport = []string{
|
||||||
|
"/api/integration-modules/{code}",
|
||||||
|
"/api/integration-modules/{code}/edit",
|
||||||
|
}
|
||||||
|
markdownSymbols = []string{"*", "_", "`", "["}
|
||||||
|
regCommandName = regexp.MustCompile(`^https://?[\da-z.-]+\.(retailcrm\.(ru|pro|es)|ecomlogic\.com|simlachat\.(com|ru))/?$`)
|
||||||
|
slashRegex = regexp.MustCompile(`/+$`)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
// ConfigInterface settings data structure
|
// ConfigInterface settings data structure
|
||||||
type ConfigInterface interface {
|
type ConfigInterface interface {
|
||||||
GetVersion() string
|
GetVersion() string
|
||||||
|
104
core/sentry.go
104
core/sentry.go
@ -1,14 +1,15 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/Neur0toxine/mg-transport-lib/internal"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/getsentry/raven-go"
|
"github.com/getsentry/raven-go"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
@ -227,7 +228,7 @@ func (s *Sentry) ErrorCaptureHandler() ErrorHandlerFunc {
|
|||||||
|
|
||||||
for _, err := range c.Errors {
|
for _, err := range c.Errors {
|
||||||
if s.Stacktrace {
|
if s.Stacktrace {
|
||||||
stacktrace := internal.NewRavenStackTrace(s.Client, err.Err, 0)
|
stacktrace := newRavenStackTrace(s.Client, err.Err, 0)
|
||||||
go s.Client.CaptureMessageAndWait(
|
go s.Client.CaptureMessageAndWait(
|
||||||
err.Error(),
|
err.Error(),
|
||||||
tags,
|
tags,
|
||||||
@ -380,3 +381,100 @@ func (t *SentryTaggedScalar) BuildTags(v interface{}) (items map[string]string,
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newRavenStackTrace generate stacktrace compatible with raven-go format
|
||||||
|
// It tries to extract better stacktrace from error from package "github.com/pkg/errors"
|
||||||
|
// In case of fail it will fallback to default stacktrace generation from raven-go.
|
||||||
|
// Default stacktrace highly likely will be useless, because it will not include call
|
||||||
|
// which returned error. This occurs because default stacktrace doesn't include any call
|
||||||
|
// before stacktrace generation, and raven-go will generate stacktrace here, which will end
|
||||||
|
// in trace to this file. But errors from "github.com/pkg/errors" will generate stacktrace
|
||||||
|
// immediately, it will include call which returned error, and we can fetch this trace.
|
||||||
|
// Also we can wrap default errors with error from this package, like this:
|
||||||
|
// errors.Wrap(err, err.Error)
|
||||||
|
func newRavenStackTrace(client *raven.Client, myerr error, skip int) *raven.Stacktrace {
|
||||||
|
st := getErrorStackTraceConverted(myerr, 3, client.IncludePaths())
|
||||||
|
if st == nil {
|
||||||
|
st = raven.NewStacktrace(skip, 3, client.IncludePaths())
|
||||||
|
}
|
||||||
|
return st
|
||||||
|
}
|
||||||
|
|
||||||
|
// getErrorStackTraceConverted will return converted stacktrace from custom error, or nil in case of default error
|
||||||
|
func getErrorStackTraceConverted(err error, context int, appPackagePrefixes []string) *raven.Stacktrace {
|
||||||
|
st := getErrorCauseStackTrace(err)
|
||||||
|
if st == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return convertStackTrace(st, context, appPackagePrefixes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getErrorCauseStackTrace tries to extract stacktrace from custom error, returns nil in case of failure
|
||||||
|
func getErrorCauseStackTrace(err error) errors.StackTrace {
|
||||||
|
// This code is inspired by github.com/pkg/errors.Cause().
|
||||||
|
var st errors.StackTrace
|
||||||
|
for err != nil {
|
||||||
|
s := getErrorStackTrace(err)
|
||||||
|
if s != nil {
|
||||||
|
st = s
|
||||||
|
}
|
||||||
|
err = getErrorCause(err)
|
||||||
|
}
|
||||||
|
return st
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertStackTrace converts github.com/pkg/errors.StackTrace to github.com/getsentry/raven-go.Stacktrace
|
||||||
|
func convertStackTrace(st errors.StackTrace, context int, appPackagePrefixes []string) *raven.Stacktrace {
|
||||||
|
// This code is borrowed from github.com/getsentry/raven-go.NewStacktrace().
|
||||||
|
var frames []*raven.StacktraceFrame
|
||||||
|
for _, f := range st {
|
||||||
|
frame := convertFrame(f, context, appPackagePrefixes)
|
||||||
|
if frame != nil {
|
||||||
|
frames = append(frames, frame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(frames) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for i, j := 0, len(frames)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
frames[i], frames[j] = frames[j], frames[i]
|
||||||
|
}
|
||||||
|
return &raven.Stacktrace{Frames: frames}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertFrame converts single frame from github.com/pkg/errors.Frame to github.com/pkg/errors.Frame
|
||||||
|
func convertFrame(f errors.Frame, context int, appPackagePrefixes []string) *raven.StacktraceFrame {
|
||||||
|
// This code is borrowed from github.com/pkg/errors.Frame.
|
||||||
|
pc := uintptr(f) - 1
|
||||||
|
fn := runtime.FuncForPC(pc)
|
||||||
|
var file string
|
||||||
|
var line int
|
||||||
|
if fn != nil {
|
||||||
|
file, line = fn.FileLine(pc)
|
||||||
|
} else {
|
||||||
|
file = "unknown"
|
||||||
|
}
|
||||||
|
return raven.NewStacktraceFrame(pc, file, line, context, appPackagePrefixes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getErrorStackTrace will try to extract stacktrace from error using StackTrace method (default errors doesn't have it)
|
||||||
|
func getErrorStackTrace(err error) errors.StackTrace {
|
||||||
|
ster, ok := err.(interface {
|
||||||
|
StackTrace() errors.StackTrace
|
||||||
|
})
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return ster.StackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
// getErrorCause will try to extract original error from wrapper - it is used only if stacktrace is not present
|
||||||
|
func getErrorCause(err error) error {
|
||||||
|
cer, ok := err.(interface {
|
||||||
|
Cause() error
|
||||||
|
})
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return cer.Cause()
|
||||||
|
}
|
@ -12,7 +12,6 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Neur0toxine/mg-transport-lib/internal"
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
@ -40,7 +39,7 @@ func NewUtils(awsConfig ConfigAWS, localizer *Localizer, logger *logging.Logger,
|
|||||||
Localizer: localizer,
|
Localizer: localizer,
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
TokenCounter: 0,
|
TokenCounter: 0,
|
||||||
slashRegex: internal.SlashRegex,
|
slashRegex: slashRegex,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +48,7 @@ func (u *Utils) resetUtils(awsConfig ConfigAWS, debug bool, tokenCounter uint32)
|
|||||||
u.TokenCounter = tokenCounter
|
u.TokenCounter = tokenCounter
|
||||||
u.ConfigAWS = awsConfig
|
u.ConfigAWS = awsConfig
|
||||||
u.IsDebug = debug
|
u.IsDebug = debug
|
||||||
u.slashRegex = internal.SlashRegex
|
u.slashRegex = slashRegex
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateToken will generate long pseudo-random string.
|
// GenerateToken will generate long pseudo-random string.
|
||||||
@ -73,29 +72,20 @@ func (u *Utils) GetAPIClient(url, key string) (*v5.Client, int, error) {
|
|||||||
|
|
||||||
if !cr.Success {
|
if !cr.Success {
|
||||||
u.Logger.Error(url, status, e.ApiErr, cr)
|
u.Logger.Error(url, status, e.ApiErr, cr)
|
||||||
return nil, http.StatusBadRequest, errors.New(u.Localizer.GetLocalizedMessage("incorrect_url_key"))
|
return nil, http.StatusBadRequest, errors.New("invalid credentials")
|
||||||
}
|
}
|
||||||
|
|
||||||
if res := u.checkCredentials(cr.Credentials); len(res) != 0 {
|
if res := u.checkCredentials(cr.Credentials); len(res) != 0 {
|
||||||
u.Logger.Error(url, status, res)
|
u.Logger.Error(url, status, res)
|
||||||
return nil,
|
return nil, http.StatusBadRequest, errors.New("missing credentials")
|
||||||
http.StatusBadRequest,
|
|
||||||
errors.New(
|
|
||||||
u.Localizer.GetLocalizedTemplateMessage(
|
|
||||||
"missing_credentials",
|
|
||||||
map[string]interface{}{
|
|
||||||
"Credentials": strings.Join(res, ", "),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return client, 0, nil
|
return client, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *Utils) checkCredentials(credential []string) []string {
|
func (u *Utils) checkCredentials(credential []string) []string {
|
||||||
rc := make([]string, len(internal.CredentialsTransport))
|
rc := make([]string, len(credentialsTransport))
|
||||||
copy(rc, internal.CredentialsTransport)
|
copy(rc, credentialsTransport)
|
||||||
|
|
||||||
for _, vc := range credential {
|
for _, vc := range credential {
|
||||||
for kn, vn := range rc {
|
for kn, vn := range rc {
|
||||||
@ -188,7 +178,7 @@ func GetEntitySHA1(v interface{}) (hash string, err error) {
|
|||||||
|
|
||||||
// ReplaceMarkdownSymbols will remove markdown symbols from text
|
// ReplaceMarkdownSymbols will remove markdown symbols from text
|
||||||
func ReplaceMarkdownSymbols(s string) string {
|
func ReplaceMarkdownSymbols(s string) string {
|
||||||
for _, v := range internal.MarkdownSymbols {
|
for _, v := range markdownSymbols {
|
||||||
s = strings.Replace(s, v, "\\"+v, -1)
|
s = strings.Replace(s, v, "\\"+v, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin/binding"
|
"github.com/gin-gonic/gin/binding"
|
||||||
"github.com/Neur0toxine/mg-transport-lib/internal"
|
|
||||||
"gopkg.in/go-playground/validator.v8"
|
"gopkg.in/go-playground/validator.v8"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,5 +19,5 @@ func validateCrmURL(
|
|||||||
v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
|
v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
|
||||||
field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
|
field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
|
||||||
) bool {
|
) bool {
|
||||||
return internal.RegCommandName.Match([]byte(field.Interface().(string)))
|
return regCommandName.Match([]byte(field.Interface().(string)))
|
||||||
}
|
}
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
package internal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/getsentry/raven-go"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewRavenStackTrace generate stacktrace compatible with raven-go format
|
|
||||||
// It tries to extract better stacktrace from error from package "github.com/pkg/errors"
|
|
||||||
// In case of fail it will fallback to default stacktrace generation from raven-go.
|
|
||||||
// Default stacktrace highly likely will be useless, because it will not include call
|
|
||||||
// which returned error. This occurs because default stacktrace doesn't include any call
|
|
||||||
// before stacktrace generation, and raven-go will generate stacktrace here, which will end
|
|
||||||
// in trace to this file. But errors from "github.com/pkg/errors" will generate stacktrace
|
|
||||||
// immediately, it will include call which returned error, and we can fetch this trace.
|
|
||||||
// Also we can wrap default errors with error from this package, like this:
|
|
||||||
// errors.Wrap(err, err.Error)
|
|
||||||
func NewRavenStackTrace(client *raven.Client, myerr error, skip int) *raven.Stacktrace {
|
|
||||||
st := getErrorStackTraceConverted(myerr, 3, client.IncludePaths())
|
|
||||||
if st == nil {
|
|
||||||
st = raven.NewStacktrace(skip, 3, client.IncludePaths())
|
|
||||||
}
|
|
||||||
return st
|
|
||||||
}
|
|
||||||
|
|
||||||
// getErrorStackTraceConverted will return converted stacktrace from custom error, or nil in case of default error
|
|
||||||
func getErrorStackTraceConverted(err error, context int, appPackagePrefixes []string) *raven.Stacktrace {
|
|
||||||
st := getErrorCauseStackTrace(err)
|
|
||||||
if st == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return convertStackTrace(st, context, appPackagePrefixes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getErrorCauseStackTrace tries to extract stacktrace from custom error, returns nil in case of failure
|
|
||||||
func getErrorCauseStackTrace(err error) errors.StackTrace {
|
|
||||||
// This code is inspired by github.com/pkg/errors.Cause().
|
|
||||||
var st errors.StackTrace
|
|
||||||
for err != nil {
|
|
||||||
s := getErrorStackTrace(err)
|
|
||||||
if s != nil {
|
|
||||||
st = s
|
|
||||||
}
|
|
||||||
err = getErrorCause(err)
|
|
||||||
}
|
|
||||||
return st
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertStackTrace converts github.com/pkg/errors.StackTrace to github.com/getsentry/raven-go.Stacktrace
|
|
||||||
func convertStackTrace(st errors.StackTrace, context int, appPackagePrefixes []string) *raven.Stacktrace {
|
|
||||||
// This code is borrowed from github.com/getsentry/raven-go.NewStacktrace().
|
|
||||||
var frames []*raven.StacktraceFrame
|
|
||||||
for _, f := range st {
|
|
||||||
frame := convertFrame(f, context, appPackagePrefixes)
|
|
||||||
if frame != nil {
|
|
||||||
frames = append(frames, frame)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(frames) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
for i, j := 0, len(frames)-1; i < j; i, j = i+1, j-1 {
|
|
||||||
frames[i], frames[j] = frames[j], frames[i]
|
|
||||||
}
|
|
||||||
return &raven.Stacktrace{Frames: frames}
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertFrame converts single frame from github.com/pkg/errors.Frame to github.com/pkg/errors.Frame
|
|
||||||
func convertFrame(f errors.Frame, context int, appPackagePrefixes []string) *raven.StacktraceFrame {
|
|
||||||
// This code is borrowed from github.com/pkg/errors.Frame.
|
|
||||||
pc := uintptr(f) - 1
|
|
||||||
fn := runtime.FuncForPC(pc)
|
|
||||||
var file string
|
|
||||||
var line int
|
|
||||||
if fn != nil {
|
|
||||||
file, line = fn.FileLine(pc)
|
|
||||||
} else {
|
|
||||||
file = "unknown"
|
|
||||||
}
|
|
||||||
return raven.NewStacktraceFrame(pc, file, line, context, appPackagePrefixes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getErrorStackTrace will try to extract stacktrace from error using StackTrace method (default errors doesn't have it)
|
|
||||||
func getErrorStackTrace(err error) errors.StackTrace {
|
|
||||||
ster, ok := err.(interface {
|
|
||||||
StackTrace() errors.StackTrace
|
|
||||||
})
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return ster.StackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
// getErrorCause will try to extract original error from wrapper - it is used only if stacktrace is not present
|
|
||||||
func getErrorCause(err error) error {
|
|
||||||
cer, ok := err.(interface {
|
|
||||||
Cause() error
|
|
||||||
})
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return cer.Cause()
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package internal
|
|
||||||
|
|
||||||
import "regexp"
|
|
||||||
|
|
||||||
// CredentialsTransport set of API methods for transport registration
|
|
||||||
var (
|
|
||||||
CredentialsTransport = []string{
|
|
||||||
"/api/integration-modules/{code}",
|
|
||||||
"/api/integration-modules/{code}/edit",
|
|
||||||
}
|
|
||||||
MarkdownSymbols = []string{"*", "_", "`", "["}
|
|
||||||
RegCommandName = regexp.MustCompile(`^https://?[\da-z.-]+\.(retailcrm\.(ru|pro|es)|ecomlogic\.com|simlachat\.(com|ru))/?$`)
|
|
||||||
SlashRegex = regexp.MustCompile(`/+$`)
|
|
||||||
)
|
|
Loading…
Reference in New Issue
Block a user