Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Alipebt authored Aug 5, 2023
2 parents 13b1b54 + e5fbe62 commit 1af96b9
Show file tree
Hide file tree
Showing 18 changed files with 487 additions and 3 deletions.
1 change: 1 addition & 0 deletions .github/workflows/plugin-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ jobs:
- plugin_exclusion
- runtime_metrics
- grpc
- mux
steps:
- uses: actions/checkout@v2
with:
Expand Down
15 changes: 15 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@ Changes by Version
==================
Release Notes.

0.3.0
------------------
#### Features

#### Plugins
* Support [mux](https://github.com/gorilla/mux) HTTP server framework.

#### Documentation

#### Bug Fixes

#### Issues and PR
- All issues are [here](https://github.com/apache/skywalking/milestone/189?closed=1)
- All and pull requests are [here](https://github.com/apache/skywalking-go/milestone/3?closed=1)

0.2.0
------------------
#### Features
Expand Down
1 change: 1 addition & 0 deletions docs/en/agent/support-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ metrics based on the tracing data.
* `gin`: [Gin](https://github.com/gin-gonic/gin) tested v1.7.0 to v1.9.0.
* `http`: [Native HTTP](https://pkg.go.dev/net/http) tested go v1.17 to go v1.20.
* `go-restfulv3`: [Go-Restful](https://github.com/emicklei/go-restful) tested v3.7.1 to 3.10.2.
* `mux`: [Mux](https://github.com/gorilla/mux) tested v1.7.0 to v1.8.0.
* HTTP Client
* `http`: [Native HTTP](https://pkg.go.dev/net/http) tested go v1.17 to go v1.20.
* RPC Frameworks
Expand Down
2 changes: 2 additions & 0 deletions go.work
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use (
./plugins/sql
./plugins/runtimemetrics
./plugins/grpc
./plugins/mux

./test/benchmark-codebase/consumer
./test/benchmark-codebase/provider
Expand All @@ -37,6 +38,7 @@ use (
./test/plugins/scenarios/logrus
./test/plugins/scenarios/zap
./test/plugins/scenarios/grpc
./test/plugins/scenarios/mux

./test/plugins/scenarios/plugin_exclusion
./test/plugins/scenarios/runtime_metrics
Expand Down
5 changes: 5 additions & 0 deletions plugins/mux/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/apache/skywalking-go/plugins/mux

go 1.18

require github.com/gorilla/mux v1.8.0 // indirect
2 changes: 2 additions & 0 deletions plugins/mux/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
72 changes: 72 additions & 0 deletions plugins/mux/instrument.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package mux

import (
"embed"

"github.com/apache/skywalking-go/plugins/core/instrument"
)

//go:embed *
var fs embed.FS

//skywalking:nocopy
type Instrument struct {
}

func NewInstrument() *Instrument {
return &Instrument{}
}

func (i *Instrument) Name() string {
return "mux"
}

func (i *Instrument) BasePackage() string {
return "github.com/gorilla/mux"
}

func (i *Instrument) VersionChecker(version string) bool {
return true
}

func (i *Instrument) Points() []*instrument.Point {
return []*instrument.Point{
{
PackagePath: "",
At: instrument.NewMethodEnhance("*Router", "ServeHTTP",
instrument.WithArgsCount(2),
instrument.WithArgType(0, "http.ResponseWriter"), instrument.WithArgType(1, "*http.Request"),
instrument.WithResultCount(0)),
Interceptor: "ServeHTTPInterceptor",
},
{
PackagePath: "",
At: instrument.NewMethodEnhance("*Router", "Match",
instrument.WithArgsCount(2),
instrument.WithArgType(0, "*http.Request"), instrument.WithArgType(1, "*RouteMatch"),
instrument.WithResultCount(1), instrument.WithResultType(0, "bool")),
Interceptor: "MatchInterceptor",
},
}
}

func (i *Instrument) FS() *embed.FS {
return &fs
}
73 changes: 73 additions & 0 deletions plugins/mux/match_interceptor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package mux

import (
"net/http"

"github.com/apache/skywalking-go/plugins/core/operator"
"github.com/apache/skywalking-go/plugins/core/tracing"
)

type MatchInterceptor struct {
}

func (n *MatchInterceptor) BeforeInvoke(invocation operator.Invocation) error {
return nil
}

func (n *MatchInterceptor) AfterInvoke(invocation operator.Invocation, results ...interface{}) error {
// only process with matched route
if matched, ok := results[0].(bool); !ok || !matched {
return nil
}
match, ok := invocation.Args()[1].(*RouteMatch)
req := invocation.Args()[0].(*http.Request)
if !ok || match == nil || match.Route == nil || req == nil {
return nil
}

span := tracing.ActiveSpan()
if span == nil {
return nil
}

// find matched template
var routePrefix, routePath string
for _, matcher := range match.Route.matchers {
if regexp, ok := matcher.(*routeRegexp); ok && regexp != nil {
if regexp.regexpType == 2 {
routePrefix = regexp.template
} else if regexp.regexpType == 0 {
routePath = regexp.template
}
}
}

opName := routePrefix
if routePath != "" {
opName = routePath
}

// re-set the operation name if route path/prefix not empty
if opName != "" {
span.SetOperationName(req.Method + ":" + opName)
}

return nil
}
70 changes: 70 additions & 0 deletions plugins/mux/serve_interceptor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package mux

import (
"fmt"
"net/http"

"github.com/apache/skywalking-go/plugins/core/operator"
"github.com/apache/skywalking-go/plugins/core/tracing"
)

type ServeHTTPInterceptor struct {
}

func (n *ServeHTTPInterceptor) BeforeInvoke(invocation operator.Invocation) error {
request := invocation.Args()[1].(*http.Request)
s, err := tracing.CreateEntrySpan(fmt.Sprintf("%s:%s", request.Method, request.RequestURI), func(headerKey string) (string, error) {
return request.Header.Get(headerKey), nil
}, tracing.WithLayer(tracing.SpanLayerHTTP),
tracing.WithComponent(5017),
tracing.WithTag(tracing.TagHTTPMethod, request.Method),
tracing.WithTag(tracing.TagURL, request.Host+request.URL.Path))
if err != nil {
return err
}

writer := invocation.Args()[0].(http.ResponseWriter)
invocation.ChangeArg(0, &writerWrapper{ResponseWriter: writer, statusCode: http.StatusOK})
invocation.SetContext(s)
return nil
}

func (n *ServeHTTPInterceptor) AfterInvoke(invocation operator.Invocation, results ...interface{}) error {
if invocation.GetContext() == nil {
return nil
}
span := invocation.GetContext().(tracing.Span)
if wrapped, ok := invocation.Args()[0].(*writerWrapper); ok {
span.Tag(tracing.TagStatusCode, fmt.Sprintf("%d", wrapped.statusCode))
}
span.End()
return nil
}

type writerWrapper struct {
http.ResponseWriter
statusCode int
}

func (w *writerWrapper) WriteHeader(statusCode int) {
// cache the status code
w.statusCode = statusCode
w.ResponseWriter.WriteHeader(statusCode)
}
37 changes: 37 additions & 0 deletions plugins/mux/structures.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package mux

//skywalking:native github.com/gorilla/mux RouteMatch
type RouteMatch struct {
Route *Route
}

type Route struct {
routeConf
}

type routeConf struct {
matchers []interface{}
}

//skywalking:native github.com/gorilla/mux routeRegexp
type routeRegexp struct {
template string
regexpType int
}
8 changes: 5 additions & 3 deletions test/plugins/scenarios/kratosv2/config/excepted.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@ segmentItems:
- operationName: /helloworld.Greeter/SayHello
parentSpanId: -1
spanId: 0
spanLayer: RPCFramework
spanLayer: Http
startTime: nq 0
endTime: nq 0
componentId: 5010
componentId: 5017
isError: false
spanType: Entry
peer: ''
skipAnalysis: false
tags:
- {key: transport, value: HTTP}
- { key: http.method, value: GET }
- { key: url, value: 'localhost:8000/helloworld/test' }
- {key: status_code, value: '200'}
refs:
- {parentEndpoint: 'GET:/consumer', networkAddress: 'localhost:8000', refType: CrossProcess,
parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not null,
Expand Down
22 changes: 22 additions & 0 deletions test/plugins/scenarios/mux/bin/startup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

home="$(cd "$(dirname $0)"; pwd)"
go build ${GO_BUILD_OPTS} -o mux

./mux
Loading

0 comments on commit 1af96b9

Please sign in to comment.