Skip to content

Commit

Permalink
support OpenTelemetry tracing (#576)
Browse files Browse the repository at this point in the history
  • Loading branch information
Somiacao authored Nov 12, 2022
1 parent e2ab769 commit 9003ee2
Show file tree
Hide file tree
Showing 35 changed files with 1,726 additions and 1,113 deletions.
11 changes: 11 additions & 0 deletions base/log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package log
import (
"github.com/emicklei/go-restful/v3"
"github.com/go-sql-driver/mysql"
"go.opentelemetry.io/otel"
"go.uber.org/zap"
"net/url"
"os"
Expand Down Expand Up @@ -105,3 +106,13 @@ func RedactDBURL(rawURL string) string {
return parsed.String()
}
}

func GetErrorHandler() otel.ErrorHandler {
return &errorHandler{}
}

type errorHandler struct{}

func (h *errorHandler) Handle(err error) {
Logger().Error("opentelemetry failure", zap.Error(err))
}
7 changes: 7 additions & 0 deletions base/log/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ package log
import (
"github.com/stretchr/testify/assert"
"os"
"runtime"
"testing"
)

func TestSetDevelopmentLogger(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip()
}
temp, err := os.MkdirTemp("", "test_gorse")
assert.NoError(t, err)
// set existed path
Expand All @@ -41,6 +45,9 @@ func TestSetDevelopmentLogger(t *testing.T) {
}

func TestSetProductionLogger(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip()
}
temp, err := os.MkdirTemp("", "test_gorse")
assert.NoError(t, err)
// set existed path
Expand Down
58 changes: 31 additions & 27 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@
package client

import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"

"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)

type GorseClient struct {
Expand All @@ -28,64 +31,65 @@ type GorseClient struct {
httpClient http.Client
}

func NewGorseClient(EntryPoint, ApiKey string) *GorseClient {
func NewGorseClient(entryPoint, apiKey string) *GorseClient {
return &GorseClient{
entryPoint: EntryPoint,
apiKey: ApiKey,
entryPoint: entryPoint,
apiKey: apiKey,
httpClient: http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)},
}
}

func (c *GorseClient) InsertFeedback(feedbacks []Feedback) (RowAffected, error) {
return request[RowAffected](c, "POST", c.entryPoint+"/api/feedback", feedbacks)
func (c *GorseClient) InsertFeedback(ctx context.Context, feedbacks []Feedback) (RowAffected, error) {
return request[RowAffected](ctx, c, "POST", c.entryPoint+"/api/feedback", feedbacks)
}

func (c *GorseClient) ListFeedbacks(feedbackType, userId string) ([]Feedback, error) {
return request[[]Feedback, any](c, "GET", c.entryPoint+fmt.Sprintf("/api/user/"+userId+"/feedback/"+feedbackType), nil)
func (c *GorseClient) ListFeedbacks(ctx context.Context, feedbackType, userId string) ([]Feedback, error) {
return request[[]Feedback, any](ctx, c, "GET", c.entryPoint+fmt.Sprintf("/api/user/"+userId+"/feedback/"+feedbackType), nil)
}

func (c *GorseClient) GetRecommend(userId string, category string, n int) ([]string, error) {
return request[[]string, any](c, "GET", c.entryPoint+fmt.Sprintf("/api/recommend/%s/%s?n=%d", userId, category, n), nil)
func (c *GorseClient) GetRecommend(ctx context.Context, userId string, category string, n int) ([]string, error) {
return request[[]string, any](ctx, c, "GET", c.entryPoint+fmt.Sprintf("/api/recommend/%s/%s?n=%d", userId, category, n), nil)
}

func (c *GorseClient) SessionRecommend(feedbacks []Feedback, n int) ([]Score, error) {
return request[[]Score](c, "POST", c.entryPoint+fmt.Sprintf("/api/session/recommend?n=%d", n), feedbacks)
func (c *GorseClient) SessionRecommend(ctx context.Context, feedbacks []Feedback, n int) ([]Score, error) {
return request[[]Score](ctx, c, "POST", c.entryPoint+fmt.Sprintf("/api/session/recommend?n=%d", n), feedbacks)
}

func (c *GorseClient) GetNeighbors(itemId string, n int) ([]Score, error) {
return request[[]Score, any](c, "GET", c.entryPoint+fmt.Sprintf("/api/item/%s/neighbors?n=%d", itemId, n), nil)
func (c *GorseClient) GetNeighbors(ctx context.Context, itemId string, n int) ([]Score, error) {
return request[[]Score, any](ctx, c, "GET", c.entryPoint+fmt.Sprintf("/api/item/%s/neighbors?n=%d", itemId, n), nil)
}

func (c *GorseClient) InsertUser(user User) (RowAffected, error) {
return request[RowAffected](c, "POST", c.entryPoint+"/api/user", user)
func (c *GorseClient) InsertUser(ctx context.Context, user User) (RowAffected, error) {
return request[RowAffected](ctx, c, "POST", c.entryPoint+"/api/user", user)
}

func (c *GorseClient) GetUser(userId string) (User, error) {
return request[User, any](c, "GET", c.entryPoint+fmt.Sprintf("/api/user/%s", userId), nil)
func (c *GorseClient) GetUser(ctx context.Context, userId string) (User, error) {
return request[User, any](ctx, c, "GET", c.entryPoint+fmt.Sprintf("/api/user/%s", userId), nil)
}

func (c *GorseClient) DeleteUser(userId string) (RowAffected, error) {
return request[RowAffected, any](c, "DELETE", c.entryPoint+fmt.Sprintf("/api/user/%s", userId), nil)
func (c *GorseClient) DeleteUser(ctx context.Context, userId string) (RowAffected, error) {
return request[RowAffected, any](ctx, c, "DELETE", c.entryPoint+fmt.Sprintf("/api/user/%s", userId), nil)
}

func (c *GorseClient) InsertItem(item Item) (RowAffected, error) {
return request[RowAffected](c, "POST", c.entryPoint+"/api/item", item)
func (c *GorseClient) InsertItem(ctx context.Context, item Item) (RowAffected, error) {
return request[RowAffected](ctx, c, "POST", c.entryPoint+"/api/item", item)
}

func (c *GorseClient) GetItem(itemId string) (Item, error) {
return request[Item, any](c, "GET", c.entryPoint+fmt.Sprintf("/api/item/%s", itemId), nil)
func (c *GorseClient) GetItem(ctx context.Context, itemId string) (Item, error) {
return request[Item, any](ctx, c, "GET", c.entryPoint+fmt.Sprintf("/api/item/%s", itemId), nil)
}

func (c *GorseClient) DeleteItem(itemId string) (RowAffected, error) {
return request[RowAffected, any](c, "DELETE", c.entryPoint+fmt.Sprintf("/api/item/%s", itemId), nil)
func (c *GorseClient) DeleteItem(ctx context.Context, itemId string) (RowAffected, error) {
return request[RowAffected, any](ctx, c, "DELETE", c.entryPoint+fmt.Sprintf("/api/item/%s", itemId), nil)
}

func request[Response any, Body any](c *GorseClient, method, url string, body Body) (result Response, err error) {
func request[Response any, Body any](ctx context.Context, c *GorseClient, method, url string, body Body) (result Response, err error) {
bodyByte, marshalErr := json.Marshal(body)
if marshalErr != nil {
return result, marshalErr
}
var req *http.Request
req, err = http.NewRequest(method, url, strings.NewReader(string(bodyByte)))
req, err = http.NewRequestWithContext(ctx, method, url, strings.NewReader(string(bodyByte)))
if err != nil {
return result, err
}
Expand Down
34 changes: 19 additions & 15 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ func (suite *GorseClientTestSuite) TearDownSuite() {
}

func (suite *GorseClientTestSuite) TestFeedback() {
ctx := context.TODO()
timestamp := time.Unix(1660459054, 0).UTC().Format(time.RFC3339)
userId := "800"
insertFeedbackResp, err := suite.client.InsertFeedback([]Feedback{{
insertFeedbackResp, err := suite.client.InsertFeedback(ctx, []Feedback{{
FeedbackType: "like",
UserId: userId,
Timestamp: timestamp,
Expand All @@ -60,7 +61,7 @@ func (suite *GorseClientTestSuite) TestFeedback() {
suite.NoError(err)
suite.Equal(1, insertFeedbackResp.RowAffected)

insertFeedbacksResp, err := suite.client.InsertFeedback([]Feedback{{
insertFeedbacksResp, err := suite.client.InsertFeedback(ctx, []Feedback{{
FeedbackType: "read",
UserId: userId,
Timestamp: timestamp,
Expand All @@ -74,7 +75,7 @@ func (suite *GorseClientTestSuite) TestFeedback() {
suite.NoError(err)
suite.Equal(2, insertFeedbacksResp.RowAffected)

feedbacks, err := suite.client.ListFeedbacks("read", userId)
feedbacks, err := suite.client.ListFeedbacks(ctx, "read", userId)
suite.NoError(err)
suite.ElementsMatch([]Feedback{
{
Expand All @@ -92,7 +93,8 @@ func (suite *GorseClientTestSuite) TestFeedback() {
}

func (suite *GorseClientTestSuite) TestRecommend() {
suite.redis.ZAddArgs(context.Background(), "offline_recommend/100", redis.ZAddArgs{
ctx := context.TODO()
suite.redis.ZAddArgs(ctx, "offline_recommend/100", redis.ZAddArgs{
Members: []redis.Z{
{
Score: 1,
Expand All @@ -108,7 +110,7 @@ func (suite *GorseClientTestSuite) TestRecommend() {
},
},
})
resp, err := suite.client.GetRecommend("100", "", 10)
resp, err := suite.client.GetRecommend(ctx, "100", "", 10)
suite.NoError(err)
suite.Equal([]string{"3", "2", "1"}, resp)
}
Expand Down Expand Up @@ -191,7 +193,7 @@ func (suite *GorseClientTestSuite) TestSessionRecommend() {
feedbackType := "like"
userId := "0"
timestamp := time.Unix(1660459054, 0).UTC().Format(time.RFC3339)
resp, err := suite.client.SessionRecommend([]Feedback{
resp, err := suite.client.SessionRecommend(ctx, []Feedback{
{
FeedbackType: feedbackType,
UserId: userId,
Expand Down Expand Up @@ -258,7 +260,7 @@ func (suite *GorseClientTestSuite) TestNeighbors() {
})

itemId := "100"
resp, err := suite.client.GetNeighbors(itemId, 3)
resp, err := suite.client.GetNeighbors(ctx, itemId, 3)
suite.NoError(err)
suite.Equal([]Score{
{
Expand All @@ -275,29 +277,31 @@ func (suite *GorseClientTestSuite) TestNeighbors() {
}

func (suite *GorseClientTestSuite) TestUsers() {
ctx := context.TODO()
user := User{
UserId: "100",
Labels: []string{"a", "b", "c"},
Subscribe: []string{"d", "e"},
Comment: "comment",
}
rowAffected, err := suite.client.InsertUser(user)
rowAffected, err := suite.client.InsertUser(ctx, user)
suite.NoError(err)
suite.Equal(1, rowAffected.RowAffected)

userResp, err := suite.client.GetUser("100")
userResp, err := suite.client.GetUser(ctx, "100")
suite.NoError(err)
suite.Equal(user, userResp)

deleteAffect, err := suite.client.DeleteUser("100")
deleteAffect, err := suite.client.DeleteUser(ctx, "100")
suite.NoError(err)
suite.Equal(1, deleteAffect.RowAffected)

_, err = suite.client.GetUser("100")
_, err = suite.client.GetUser(ctx, "100")
suite.Equal("100: user not found", err.Error())
}

func (suite *GorseClientTestSuite) TestItems() {
ctx := context.TODO()
timestamp := time.Unix(1660459054, 0).UTC().Format(time.RFC3339)
item := Item{
ItemId: "100",
Expand All @@ -307,19 +311,19 @@ func (suite *GorseClientTestSuite) TestItems() {
Timestamp: timestamp,
Comment: "comment",
}
rowAffected, err := suite.client.InsertItem(item)
rowAffected, err := suite.client.InsertItem(ctx, item)
suite.NoError(err)
suite.Equal(1, rowAffected.RowAffected)

itemResp, err := suite.client.GetItem("100")
itemResp, err := suite.client.GetItem(ctx, "100")
suite.NoError(err)
suite.Equal(item, itemResp)

deleteAffect, err := suite.client.DeleteItem("100")
deleteAffect, err := suite.client.DeleteItem(ctx, "100")
suite.NoError(err)
suite.Equal(1, deleteAffect.RowAffected)

_, err = suite.client.GetItem("100")
_, err = suite.client.GetItem(ctx, "100")
suite.Equal("100: item not found", err.Error())
}

Expand Down
6 changes: 3 additions & 3 deletions cmd/gorse-in-one/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ var oneCommand = &cobra.Command{
}

fmt.Println()
fmt.Printf(" Dashboard: http://%s:%d/overview\n", conf.Master.HttpHost, conf.Master.HttpPort)
fmt.Printf(" RESTful APIs: http://%s:%d/apidocs\n", conf.Master.HttpHost, conf.Master.HttpPort)
fmt.Printf(" Documentation: https://docs.gorse.io/\n")
fmt.Printf(" Dashboard: http://127.0.0.1:%d/overview\n", conf.Master.HttpPort)
fmt.Printf(" RESTful APIs: http://127.0.0.1:%d/apidocs\n", conf.Master.HttpPort)
fmt.Printf(" Documentation: https://gorse.io/docs\n")
fmt.Println()
} else {
configPath, _ := cmd.PersistentFlags().GetString("config")
Expand Down
Loading

0 comments on commit 9003ee2

Please sign in to comment.