Skip to content

Commit

Permalink
support mux (#61)
Browse files Browse the repository at this point in the history
* support mux

* fix muzzle check
  • Loading branch information
123liuziming authored Aug 23, 2024
1 parent 962e108 commit 6c55fa0
Show file tree
Hide file tree
Showing 27 changed files with 562 additions and 3 deletions.
35 changes: 35 additions & 0 deletions pkg/rules/mux/mux_data_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) 2024 Alibaba Group Holding Ltd.
//
// Licensed 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.
//go:build ignore

package rule

import (
"net/http"
"net/url"
)

type muxHttpRequest struct {
method string
url *url.URL
host string
isTls bool
header http.Header
version string
}

type muxHttpResponse struct {
statusCode int
header http.Header
}
121 changes: 121 additions & 0 deletions pkg/rules/mux/mux_otel_instrumenter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Copyright (c) 2024 Alibaba Group Holding Ltd.
//
// Licensed 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.
//go:build ignore

package rule

import (
"strconv"

"github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/inst-api-semconv/instrumenter/http"
"github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/inst-api-semconv/instrumenter/net"
"github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/inst-api/instrumenter"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
)

type muxHttpServerAttrsGetter struct {
}

func (n muxHttpServerAttrsGetter) GetRequestMethod(request muxHttpRequest) string {
return request.method
}

func (n muxHttpServerAttrsGetter) GetHttpRequestHeader(request muxHttpRequest, name string) []string {
return request.header.Values(name)
}

func (n muxHttpServerAttrsGetter) GetHttpResponseStatusCode(request muxHttpRequest, response muxHttpResponse, err error) int {
return response.statusCode
}

func (n muxHttpServerAttrsGetter) GetHttpResponseHeader(request muxHttpRequest, response muxHttpResponse, name string) []string {
return response.header.Values(name)
}

func (n muxHttpServerAttrsGetter) GetErrorType(request muxHttpRequest, response muxHttpResponse, err error) string {
return ""
}

func (n muxHttpServerAttrsGetter) GetUrlScheme(request muxHttpRequest) string {
return request.url.Scheme
}

func (n muxHttpServerAttrsGetter) GetUrlPath(request muxHttpRequest) string {
return request.url.Path
}

func (n muxHttpServerAttrsGetter) GetUrlQuery(request muxHttpRequest) string {
return request.url.RawQuery
}

func (n muxHttpServerAttrsGetter) GetNetworkType(request muxHttpRequest, response muxHttpResponse) string {
return "ipv4"
}

func (n muxHttpServerAttrsGetter) GetNetworkTransport(request muxHttpRequest, response muxHttpResponse) string {
return "tcp"
}

func (n muxHttpServerAttrsGetter) GetNetworkProtocolName(request muxHttpRequest, response muxHttpResponse) string {
if request.isTls == false {
return "http"
} else {
return "https"
}
}

func (n muxHttpServerAttrsGetter) GetNetworkProtocolVersion(request muxHttpRequest, response muxHttpResponse) string {
return request.version
}

func (n muxHttpServerAttrsGetter) GetNetworkLocalInetAddress(request muxHttpRequest, response muxHttpResponse) string {
return ""
}

func (n muxHttpServerAttrsGetter) GetNetworkLocalPort(request muxHttpRequest, response muxHttpResponse) int {
return 0
}

func (n muxHttpServerAttrsGetter) GetNetworkPeerInetAddress(request muxHttpRequest, response muxHttpResponse) string {
return request.host
}

func (n muxHttpServerAttrsGetter) GetNetworkPeerPort(request muxHttpRequest, response muxHttpResponse) int {
port, err := strconv.Atoi(request.url.Port())
if err != nil {
return 0
}
return port
}

func (n muxHttpServerAttrsGetter) GetHttpRoute(request muxHttpRequest) string {
return request.url.Path
}

func BuildMuxHttpServerOtelInstrumenter() *instrumenter.PropagatingFromUpstreamInstrumenter[muxHttpRequest, muxHttpResponse] {
builder := instrumenter.Builder[muxHttpRequest, muxHttpResponse]{}
serverGetter := muxHttpServerAttrsGetter{}
commonExtractor := http.HttpCommonAttrsExtractor[muxHttpRequest, muxHttpResponse, muxHttpServerAttrsGetter, muxHttpServerAttrsGetter]{HttpGetter: serverGetter, NetGetter: serverGetter, Converter: &http.ServerHttpStatusCodeConverter{}}
networkExtractor := net.NetworkAttrsExtractor[muxHttpRequest, muxHttpResponse, muxHttpServerAttrsGetter]{Getter: serverGetter}
urlExtractor := net.UrlAttrsExtractor[muxHttpRequest, muxHttpResponse, muxHttpServerAttrsGetter]{Getter: serverGetter}
return builder.Init().SetSpanNameExtractor(&http.HttpServerSpanNameExtractor[muxHttpRequest, muxHttpResponse]{Getter: serverGetter}).
SetSpanKindExtractor(&instrumenter.AlwaysServerExtractor[muxHttpRequest]{}).
AddAttributesExtractor(&http.HttpServerAttrsExtractor[muxHttpRequest, muxHttpResponse, muxHttpServerAttrsGetter, muxHttpServerAttrsGetter, muxHttpServerAttrsGetter]{Base: commonExtractor, NetworkExtractor: networkExtractor, UrlExtractor: urlExtractor}).BuildPropagatingFromUpstreamInstrumenter(func(n muxHttpRequest) propagation.TextMapCarrier {
if n.header == nil {
return nil
}
return propagation.HeaderCarrier(n.header)
}, otel.GetTextMapPropagator())
}
80 changes: 80 additions & 0 deletions pkg/rules/mux/mux_server_setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//go:build ignore

package rule

import (
"bufio"
"context"
"fmt"
mux "github.com/gorilla/mux"
"net"
"net/http"
"strconv"
)

var muxInstrumenter = BuildMuxHttpServerOtelInstrumenter()

func muxServerOnEnter(call mux.CallContext, router *mux.Router, w http.ResponseWriter, req *http.Request) {
muxRequest := muxHttpRequest{
method: req.Method,
url: req.URL,
header: req.Header,
version: strconv.Itoa(req.ProtoMajor) + "." + strconv.Itoa(req.ProtoMinor),
host: req.Host,
isTls: req.TLS != nil,
}
ctx := muxInstrumenter.Start(req.Context(), muxRequest)
x := call.GetParam(1).(http.ResponseWriter)
x1 := &muxWriterWrapper{ResponseWriter: x, statusCode: http.StatusOK}
call.SetParam(1, x1)
call.SetParam(2, req.WithContext(ctx))
call.SetKeyData("ctx", ctx)
call.SetKeyData("request", muxRequest)
return
}

func muxServerOnExit(call mux.CallContext) {
c := call.GetKeyData("ctx")
if c == nil {
return
}
ctx, ok := c.(context.Context)
if !ok {
return
}
m := call.GetKeyData("request")
if m == nil {
return
}
muxRequest, ok := m.(muxHttpRequest)
if !ok {
return
}
if p, ok := call.GetParam(1).(http.ResponseWriter); ok {
if w1, ok := p.(*muxWriterWrapper); ok {
muxInstrumenter.End(ctx, muxRequest, muxHttpResponse{
statusCode: w1.statusCode,
}, nil)
}
}
return
}

type muxWriterWrapper struct {
http.ResponseWriter
statusCode int
}

func (w *muxWriterWrapper) WriteHeader(statusCode int) {
// cache the status code
w.statusCode = statusCode

w.ResponseWriter.WriteHeader(statusCode)
}

func (w *muxWriterWrapper) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
if h, ok := w.ResponseWriter.(http.Hijacker); ok {
return h.Hijack()
}
return nil, nil, fmt.Errorf("responseWriter does not implement http.Hijacker")
}
12 changes: 12 additions & 0 deletions pkg/rules/mux/rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package rule

import (
"github.com/alibaba/opentelemetry-go-auto-instrumentation/api"
)

func init() {
api.NewRule("github.com/gorilla/mux", "ServeHTTP", "*Router", "muxServerOnEnter", "muxServerOnExit").
WithVersion("[1.3.0,1.8.2)").
WithFileDeps("mux_data_type.go", "mux_otel_instrumenter.go").
Register()
}
1 change: 1 addition & 0 deletions rule_enabler.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
_ "github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/rules/http"
_ "github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/rules/logrus"
_ "github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/rules/mongo"
_ "github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/rules/mux"
_ "github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/rules/otsdk"
_ "github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/rules/runtime"
_ "github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/rules/test"
Expand Down
1 change: 1 addition & 0 deletions test/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// 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 test

import "testing"
Expand Down
1 change: 1 addition & 0 deletions test/databasesql_tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// 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 test

import (
Expand Down
1 change: 1 addition & 0 deletions test/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// 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 test

import (
Expand Down
1 change: 1 addition & 0 deletions test/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// 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 test

import (
Expand Down
14 changes: 14 additions & 0 deletions test/gin_tests.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
// Copyright (c) 2024 Alibaba Group Holding Ltd.
//
// Licensed 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 test

import "testing"
Expand Down
14 changes: 14 additions & 0 deletions test/gorm_tests.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
// Copyright (c) 2024 Alibaba Group Holding Ltd.
//
// Licensed 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 test

import (
Expand Down
1 change: 1 addition & 0 deletions test/helloworld_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// 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 test

import (
Expand Down
1 change: 1 addition & 0 deletions test/httpclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// 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 test

import (
Expand Down
1 change: 1 addition & 0 deletions test/infra.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// 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 test

import (
Expand Down
Loading

0 comments on commit 6c55fa0

Please sign in to comment.