This is an automated email from the ASF dual-hosted git repository. liuhan pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/skywalking-go.git
The following commit(s) were added to refs/heads/main by this push: new 5d7bd5e fix: when not route is found, the gin operation name is "http.Method:", example: "GET:". (#190) 5d7bd5e is described below commit 5d7bd5e8e435ec5ab1a61793cd08e6a403893a55 Author: Hair1ossTeenager <45008570+hair1ossteena...@users.noreply.github.com> AuthorDate: Tue Aug 6 12:26:11 2024 +0800 fix: when not route is found, the gin operation name is "http.Method:", example: "GET:". (#190) --- CHANGES.md | 1 + plugins/gin/intercepter.go | 6 +++- plugins/gin/intercepter_test.go | 39 ++++++++++++++++++++++++++ test/plugins/scenarios/gin/config/excepted.yml | 36 ++++++++++++++++++++++++ test/plugins/scenarios/gin/main.go | 14 +++++++++ 5 files changed, 95 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index e7080b9..b68bb56 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,7 @@ Release Notes. ### Bug Fixes * Fix panic error when root span finished. +* Fix when not route is found, the gin operation name is "http.Method:", example: "GET:". 0.4.0 ------------------ diff --git a/plugins/gin/intercepter.go b/plugins/gin/intercepter.go index c1a74a0..754dd8b 100644 --- a/plugins/gin/intercepter.go +++ b/plugins/gin/intercepter.go @@ -36,8 +36,12 @@ func (h *ContextInterceptor) BeforeInvoke(invocation operator.Invocation) error return nil } context := invocation.CallerInstance().(*gin.Context) + fullPath := context.FullPath() + if fullPath == "" { + fullPath = context.Request.URL.Path + } s, err := tracing.CreateEntrySpan( - fmt.Sprintf("%s:%s", context.Request.Method, context.FullPath()), func(headerKey string) (string, error) { + fmt.Sprintf("%s:%s", context.Request.Method, fullPath), func(headerKey string) (string, error) { return context.Request.Header.Get(headerKey), nil }, tracing.WithLayer(tracing.SpanLayerHTTP), diff --git a/plugins/gin/intercepter_test.go b/plugins/gin/intercepter_test.go index d5ba898..2c9b44b 100644 --- a/plugins/gin/intercepter_test.go +++ b/plugins/gin/intercepter_test.go @@ -18,6 +18,7 @@ package gin import ( + "fmt" "net/http" "reflect" "testing" @@ -117,3 +118,41 @@ func TestCollectHeaders(t *testing.T) { assert.Less(t, index, 4, "the index should be less than 4") assert.Equal(t, "h1=h1-value\nh2=h2", spans[0].Tags()[index].Value, "the tag Value should be h1=h1-value\nh2=h2-value") } + +type notFoundWriter struct { + gin.ResponseWriter +} + +func (i *notFoundWriter) Status() int { + return http.StatusNotFound +} + +func TestPathNotFoundInvoke(t *testing.T) { + defer core.ResetTracingContext() + + path := "/skywalking/trace/f4dd2255-e3be-4636-b2e7-fc1d407a30d3" + interceptor := &ContextInterceptor{} + request, err := http.NewRequest("GET", fmt.Sprintf("http://localhost%s", path), http.NoBody) + assert.Nil(t, err, "new request error should be nil") + + c := &gin.Context{ + Request: request, + Writer: ¬FoundWriter{}, + } + + invocation := operator.NewInvocation(c) + err = interceptor.BeforeInvoke(invocation) + assert.Nil(t, err, "before invoke error should be nil") + assert.NotNil(t, invocation.GetContext(), "context should not be nil") + + time.Sleep(100 * time.Millisecond) + + err = interceptor.AfterInvoke(invocation) + assert.Nil(t, err, "after invoke error should be nil") + + time.Sleep(100 * time.Millisecond) + spans := core.GetReportedSpans() + assert.NotNil(t, spans, "spans should not be nil") + assert.Equal(t, 1, len(spans), "spans length should be 1") + assert.Equal(t, fmt.Sprintf("GET:%s", path), spans[0].OperationName(), fmt.Sprintf("operation name should be GET:%s", path)) +} diff --git a/test/plugins/scenarios/gin/config/excepted.yml b/test/plugins/scenarios/gin/config/excepted.yml index d1a3c09..e2a3e36 100644 --- a/test/plugins/scenarios/gin/config/excepted.yml +++ b/test/plugins/scenarios/gin/config/excepted.yml @@ -40,6 +40,27 @@ segmentItems: - {parentEndpoint: 'GET:/consumer', networkAddress: 'localhost:8080', refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: gin, traceId: not null} + - segmentId: not null + spans: + - operationName: GET:/notFound + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 5006 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: http.method, value: GET} + - {key: url, value: 'localhost:8080/notFound'} + - {key: status_code, value: '404'} + refs: + - {parentEndpoint: 'GET:/consumer', networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not null, + parentService: gin, traceId: not null} - segmentId: not null spans: - operationName: GET:/provider @@ -57,6 +78,21 @@ segmentItems: - {key: http.method, value: GET} - {key: url, value: 'localhost:8080/provider'} - {key: status_code, value: '200'} + - operationName: GET:/notFound + parentSpanId: 0 + spanId: 2 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 5005 + isError: false + spanType: Exit + peer: localhost:8080 + skipAnalysis: false + tags: + - {key: http.method, value: GET} + - {key: url, value: 'localhost:8080/notFound'} + - {key: status_code, value: '404'} - operationName: GET:/consumer parentSpanId: -1 spanId: 0 diff --git a/test/plugins/scenarios/gin/main.go b/test/plugins/scenarios/gin/main.go index 8298f99..018eca3 100644 --- a/test/plugins/scenarios/gin/main.go +++ b/test/plugins/scenarios/gin/main.go @@ -55,6 +55,20 @@ func main() { context.Status(http.StatusInternalServerError) return } + + notFoundRequest, err := http.NewRequest(http.MethodGet, "http://localhost:8080/notFound", nil) + if err != nil { + log.Print(err) + context.Status(http.StatusInternalServerError) + return + } + _, err = client.Do(notFoundRequest) + if err != nil { + log.Print(err) + context.Status(http.StatusInternalServerError) + return + } + context.String(200, string(body)) })