Skip to content
This repository has been archived by the owner on Jun 14, 2023. It is now read-only.

Commit

Permalink
feat: add mongo plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
yuanyou committed Nov 15, 2022
1 parent 79cf2aa commit 72cbd83
Show file tree
Hide file tree
Showing 13 changed files with 800 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ jobs:
- { name: 'kratos', plugin_dir: 'kratos', go_version: '1.16' }
- { name: 'sql', plugin_dir: 'sql', go_version: '1.16' }
- { name: 'zap', plugin_dir: 'zap', go_version: '1.13' }
- { name: 'mongo', plugin_dir: 'mongo', go_version: '1.18' }
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v2
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/plugin_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ jobs:
kafkareporter/test/go_kafka_reporter_plugin_test.yaml: kafkareporter/**
dubbo-go/test/dubbo_go_plugin_test.yaml: dubbo-go/**
gorm/test/gorm_plugin_test.yaml: gorm/**
mongo/test/mongo_plugin_test.yaml: mongo/**
PluginsTest:
name: Plugin
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The plugins of [go2sky](https://github.com/SkyAPM/go2sky)
1. [sql](sql/README.md)
1. [dubbo-go](dubbo-go/README.md)
1. [gorm](gorm/README.md)
1. [mongodb](mongo/README.md)

### Log Plugins

Expand Down
39 changes: 39 additions & 0 deletions mongo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Go2Sky with Mongo

## Installation

```bash
go get -u github.com/SkyAPM/go2sky-plugins/mongo
```

## Usage

```go
import (
"github.com/SkyAPM/go2sky"
"github.com/SkyAPM/go2sky/reporter"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"

mongoPlugin "go2sky-plugins/mongo"
)

// init reporter
re, err := reporter.NewLogReporter()
defer re.Close()

// init tracer
tracer, err := go2sky.NewTracer("service-name", go2sky.WithReporter(re))
if err != nil {
log.Fatalf("init tracer error: %v", err)
}

// init connect mongodb.
client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(dsn).SetMonitor(mongoPlugin.Middleware(tracer)))
if err != nil {
log.Fatalf("connect mongodb error %v \n", err)
}

...

```
17 changes: 17 additions & 0 deletions mongo/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Copyright 2022 SkyAPM org
//
// 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 mongo
30 changes: 30 additions & 0 deletions mongo/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module go2sky-plugins/mongo

go 1.18

require (
github.com/SkyAPM/go2sky v1.5.0
go.mongodb.org/mongo-driver v1.11.0
skywalking.apache.org/repo/goapi v0.0.0-20220401015832-2c9eee9481eb
)

require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect
github.com/xdg-go/stringprep v1.0.3 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02 // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/genproto v0.0.0-20211112145013-271947fe86fd // indirect
google.golang.org/grpc v1.42.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
)
208 changes: 208 additions & 0 deletions mongo/go.sum

Large diffs are not rendered by default.

76 changes: 76 additions & 0 deletions mongo/mongo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//
// Copyright 2022 SkyAPM org
//
// 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 mongo

import (
"context"

"github.com/SkyAPM/go2sky"
"go.mongodb.org/mongo-driver/event"
agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
)

const (
// ComponentMongo ComponentID.
ComponentMongo int32 = 42

// ComponentMongoDB db.type.
ComponentMongoDB string = "MongoDB"
)

// Option custom option.
type Option func(span go2sky.Span, evt *event.CommandStartedEvent)

// Middleware mongo monitor.
func Middleware(tracer *go2sky.Tracer, peer string, opts ...Option) *event.CommandMonitor {
spanMap := make(map[int64]go2sky.Span)
apmMonitor := &event.CommandMonitor{
Started: func(ctx context.Context, evt *event.CommandStartedEvent) {
span, _, err := tracer.CreateLocalSpan(ctx,
go2sky.WithSpanType(go2sky.SpanTypeExit),
go2sky.WithOperationName(GetOpName(evt.CommandName)),
)
if err != nil {
return
}
span.SetPeer(peer)
span.SetComponent(ComponentMongo)
span.SetSpanLayer(agentv3.SpanLayer_Database)
span.Tag(go2sky.TagDBType, ComponentMongoDB)
for _, opt := range opts {
opt(span, evt)
}
spanMap[evt.RequestID] = span
},
Succeeded: func(ctx context.Context, evt *event.CommandSucceededEvent) {
if span, ok := spanMap[evt.RequestID]; ok {
span.End()
}
},
Failed: func(ctx context.Context, evt *event.CommandFailedEvent) {
if span, ok := spanMap[evt.RequestID]; ok {
span.End()
}
},
}
return apmMonitor
}

// GetOpName get operation name.
func GetOpName(operation string) string {
return "MongoDB/Go2Sky/" + operation
}
26 changes: 26 additions & 0 deletions mongo/test/Dockerfile.client
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#
# Copyright 2022 SkyAPM org
#
# 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.
#

FROM golang:1.16

ADD . /go2sky
WORKDIR /go2sky

EXPOSE 8080

ENTRYPOINT ["go"]

CMD ["run", "test/client.go"]
161 changes: 161 additions & 0 deletions mongo/test/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
//
// Copyright 2022 SkyAPM org
//
// 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 main

import (
"context"
"log"
"net/http"

"github.com/SkyAPM/go2sky"
httpPlugin "github.com/SkyAPM/go2sky/plugins/http"
"github.com/SkyAPM/go2sky/reporter"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"

mongoPlugin "go2sky-plugins/mongo"
)

type testFunc func(ctx context.Context, client *mongo.Client) error

const (
oap = "mockoap:19876"
service = "mongo-client"
dsn = "mongodb://user:password@mongo:27017"
addr = ":8080"
db = "database"
peer = "mongo:27017"
)

// User model.
type User struct {
ID primitive.ObjectID `bson:"_id,omitempty"`
Name string `bson:"name"`
Age int `bson:"age"`
}

func main() {
re, err := reporter.NewGRPCReporter(oap)
if err != nil {
log.Fatalf("create grpc reporter error: %v \n", err)
}

tracer, err := go2sky.NewTracer(service, go2sky.WithReporter(re))
if err != nil {
log.Fatalf("crate tracer error: %v \n", err)
}

ctx := context.Background()
middleware := mongoPlugin.Middleware(tracer, peer)
/* middleware := mongoPlugin.Middleware(tracer, func(span go2sky.Span, peer, evt *event.CommandStartedEvent) {
span.Tag(go2sky.TagDBStatement, evt.Command.String())
}) */
// init connect mongodb.
client, err := mongo.Connect(ctx, options.Client().ApplyURI(dsn).SetMonitor(middleware))
if err != nil {
log.Fatalf("connect mongodb error %v \n", err)
}

route := http.NewServeMux()
route.HandleFunc("/execute", func(res http.ResponseWriter, req *http.Request) {
tests := []struct {
name string
fn testFunc
}{
{"create_collection", TestCreateCollection},
{"create", TestCreate},
{"query", TestQuery},
{"update", TestUpdate},
{"delete", TestDelete},
}

for _, test := range tests {
log.Printf("excute test case %s", test.name)
if err = test.fn(req.Context(), client); err != nil {
log.Fatalf("test case %s failed: %v", test.name, err)
}
}
_, _ = res.Write([]byte("execute success"))
})

sm, err := httpPlugin.NewServerMiddleware(tracer)
if err != nil {
log.Fatalf("create client error %v \n", err)
}

log.Println("start client")
err = http.ListenAndServe(addr, sm(route))
if err != nil {
log.Fatalf("client start error: %v \n", err)
}
}

// TestCreateCollection create collection.
func TestCreateCollection(ctx context.Context, client *mongo.Client) error {
return client.Database(db).CreateCollection(ctx, "users")
}

// TestCreate create model.
func TestCreate(ctx context.Context, client *mongo.Client) error {
collection := client.Database(db).Collection("users")
_, err := collection.InsertOne(ctx, &User{
Name: "Elza2",
Age: 18,
})
return err
}

// TestQuery query model.
func TestQuery(ctx context.Context, client *mongo.Client) error {
collection := client.Database(db).Collection("users")
var user User
err := collection.FindOne(ctx, bson.D{
{Key: "name", Value: "Elza2"},
}).Decode(&user)

return err
}

// TestUpdate update model.
func TestUpdate(ctx context.Context, client *mongo.Client) error {
collection := client.Database(db).Collection("users")

var user User
err := collection.FindOne(ctx, bson.D{
{Key: "name", Value: "Elza2"},
}).Decode(&user)
if err != nil {
return err
}

_, err = collection.UpdateByID(ctx, user.ID, primitive.D{{
Key: "$set", Value: primitive.D{
{Key: "age", Value: 22},
},
}})
return err
}

// TestDelete delete model.
func TestDelete(ctx context.Context, client *mongo.Client) error {
collection := client.Database(db).Collection("users")

_, err := collection.DeleteOne(ctx, primitive.D{{Key: "name", Value: "Elza2"}})
return err
}
Loading

0 comments on commit 72cbd83

Please sign in to comment.