savsgio/atreugo

Sentry APM Middleware

kunal-saini opened this issue · 1 comments

Hey @savsgio, thank you for building atreugo, I have been using it in one of my projects. though recently I have been trying to integrate sentry APM but could not find any middleware built so I forked https://github.com/getsentry/sentry-go and made changes relevant to atreugo and committed here: https://github.com/kunal-saini/sentry-go/tree/mergeable

module: https://github.com/kunal-saini/sentry-go/tree/mergeable/atreugo
example: https://github.com/kunal-saini/sentry-go/tree/mergeable/example/atreugo

Let me know if the changes look good to you or if you have any input. I will raise a PR to the official sentry package.

Hi @kunal-saini,

Sorry for my delayed answer but i'm so busy lately and thanks for use Atreugo in your project, i'm so glad about that 😃.

I reviewed your middleware and you could change this line with:

r := new(http.Request)
if err := fasthttpadaptor.ConvertRequest(ctx.RequestCtx, r, true); err != nil {
	// handle the error as you want
}

and remove this function.

About the HandleTracer middleware, a better option it's create a wapper that implements a io.Closer and save the tracer into the wrapper, that's saved on RequestCtx, because all user values that implements io.Closer will automatically close, and remove the unnecessary HandleTracer middleware in declaration on the global server after middlewares.

For example:

type tracerCloser struct {
	ctx  *fasthttp.RequestCtx // you must use here the inherit fasthttp.RequestCtx
	span *sentry.Span
}

func newTracerCloser(ctx *atreugo.RequestCtx, span *sentry.Span) *tracerCloser {
	return &tracerCloser{
		ctx:  ctx.RequestCtx, // you must use here the inherit fasthttp.RequestCtx
		span: span,
	}
}

func (tc *tracerCloser) Close() error {
	if tracerSpan := getTracerFromContext(tc.ctx); tracerSpan != nil {
		tracerSpan.Finish()
	}

	return nil
}

func getTracerFromContext(ctx *fasthttp.RequestCtx) *sentry.Span {
	tracer := ctx.UserValue(tracerKey)
	if tracer, ok := tracer.(*tracerCloser); ok {
		return tracer.span
	}
	return nil
}
// func (h *Handler) Handle(ctx *atreugo.RequestCtx) error {
    // ...
    if h.tracer {
        // ....
        ctx.SetUserValue(tracerKey, newTracerCloser(ctx, span))
    //....