Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["pointwrite_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = ["//app/service/main/dapper/model:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["pointwrite.go"],
importpath = "go-common/app/service/main/dapper/pkg/pointwrite",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/dapper/model:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,139 @@
package pointwrite
import (
"context"
"fmt"
"strings"
"sync"
"time"
"go-common/app/service/main/dapper/model"
"go-common/library/log"
)
// WriteFn .
type WriteFn func(ctx context.Context, points []*model.SpanPoint) error
// PointWriter writer span point
type PointWriter interface {
WriteSpan(span *model.Span) error
Close() error
}
// New PointWriter
func New(fn WriteFn, precision int64, timeout time.Duration) PointWriter {
pw := &pointwriter{
precision: precision,
current: make(map[string]*model.SpanPoint),
timeout: timeout,
// TODO make it configurable
tk: time.NewTicker(time.Second * 30),
fn: fn,
}
go pw.start()
return pw
}
type pointwriter struct {
closed bool
rmx sync.RWMutex
precision int64
timeout time.Duration
current map[string]*model.SpanPoint
fn WriteFn
tk *time.Ticker
}
func (p *pointwriter) start() {
for range p.tk.C {
err := p.flush()
if err != nil {
log.Error("flush pointwriter error: %s", err)
}
}
}
func (p *pointwriter) flush() error {
p.rmx.Lock()
current := p.current
p.current = make(map[string]*model.SpanPoint)
p.rmx.Unlock()
points := make([]*model.SpanPoint, 0, len(current))
for _, point := range current {
points = append(points, point)
}
if len(points) == 0 {
return nil
}
ctx, cancel := context.WithTimeout(context.Background(), p.timeout)
defer cancel()
return p.fn(ctx, points)
}
// WriteSpan writespan
func (p *pointwriter) WriteSpan(span *model.Span) error {
if p.closed {
return fmt.Errorf("pointwriter already closed")
}
kind := "client"
if span.IsServer() {
kind = "server"
}
// NOTE: ingored sample ponit if is legacy span, DELETE it futrue
if kind == "client" && !strings.Contains(span.ServiceName, ".") {
return nil
}
peerService, ok := span.Tags["peer.service"].(string)
if !ok {
peerService = "unknown"
}
timestamp := span.StartTime.Unix() - (span.StartTime.Unix() % p.precision)
key := fmt.Sprintf("%d_%s_%s_%s_%s",
timestamp,
span.ServiceName,
span.OperationName,
peerService,
kind,
)
p.rmx.Lock()
defer p.rmx.Unlock()
point, ok := p.current[key]
if !ok {
point = &model.SpanPoint{
Timestamp: timestamp,
ServiceName: span.ServiceName,
OperationName: span.OperationName,
PeerService: peerService,
SpanKind: kind,
AvgDuration: model.SamplePoint{TraceID: span.TraceID, SpanID: span.SpanID, Value: int64(span.Duration)},
}
p.current[key] = point
}
duration := int64(span.Duration)
if duration > point.MaxDuration.Value {
point.MaxDuration.TraceID = span.TraceID
point.MaxDuration.SpanID = span.SpanID
point.MaxDuration.Value = duration
}
if point.MinDuration.Value == 0 || duration < point.MinDuration.Value {
point.MinDuration.TraceID = span.TraceID
point.MinDuration.SpanID = span.SpanID
point.MinDuration.Value = duration
}
if span.IsError() {
point.Errors = append(point.Errors, model.SamplePoint{
TraceID: span.TraceID,
SpanID: span.SpanID,
Value: duration,
})
}
return nil
}
// Close pointwriter
func (p *pointwriter) Close() error {
p.closed = true
p.tk.Stop()
return p.flush()
}

View File

@@ -0,0 +1,76 @@
package pointwrite
import (
"context"
"testing"
"time"
"go-common/app/service/main/dapper/model"
)
func TestPointWrite(t *testing.T) {
var data []*model.SpanPoint
mockFn := func(ctx context.Context, points []*model.SpanPoint) error {
data = append(data, points...)
return nil
}
pw := &pointwriter{
fn: mockFn,
current: make(map[string]*model.SpanPoint),
precision: 5,
timeout: time.Second,
tk: time.NewTicker(time.Second * time.Duration(5)),
}
spans := []*model.Span{
&model.Span{
ServiceName: "test1",
StartTime: time.Unix(100, 0),
},
&model.Span{
ServiceName: "test1",
StartTime: time.Unix(110, 0),
},
}
for _, span := range spans {
if err := pw.WriteSpan(span); err != nil {
t.Error(err)
}
}
if len(pw.current) != 2 {
t.Errorf("expect 2 point get %d", len(pw.current))
}
pw.flush()
if len(data) != 2 {
t.Errorf("expect 2 point get %d", len(data))
}
}
func TestPointWriteFlush(t *testing.T) {
var data []*model.SpanPoint
wait := make(chan bool, 1)
mockFn := func(ctx context.Context, points []*model.SpanPoint) error {
data = append(data, points...)
wait <- true
return nil
}
pw := New(mockFn, 1, time.Second)
spans := []*model.Span{
&model.Span{
ServiceName: "test1",
StartTime: time.Unix(100, 0),
},
&model.Span{
ServiceName: "test1",
StartTime: time.Unix(110, 0),
},
}
for _, span := range spans {
if err := pw.WriteSpan(span); err != nil {
t.Error(err)
}
}
<-wait
if len(data) != 2 {
t.Errorf("expect 2 point get %d", len(data))
}
}