You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
3.4 KiB
145 lines
3.4 KiB
package agent |
|
|
|
import ( |
|
"fmt" |
|
"io" |
|
"runtime" |
|
"strings" |
|
"time" |
|
|
|
"github.com/golang/protobuf/proto" |
|
"go-common/app/service/main/dapper/conf" |
|
"go-common/app/service/main/dapper/pkg/deliver" |
|
"go-common/app/service/main/dapper/pkg/diskqueue" |
|
"go-common/app/service/main/dapper/server/udpcollect" |
|
"go-common/library/log" |
|
spanpb "go-common/library/net/trace/proto" |
|
) |
|
|
|
// Agent dapper collect agent |
|
type Agent struct { |
|
queue diskqueue.DiskQueue |
|
clt *udpcollect.UDPCollect |
|
dlv *deliver.Deliver |
|
} |
|
|
|
// New agent |
|
func New(cfg *conf.AgentConfig, debug bool) (*Agent, error) { |
|
var options []diskqueue.Option |
|
if cfg.Queue.BucketBytes != 0 { |
|
options = append(options, diskqueue.SetBucketByte(cfg.Queue.BucketBytes)) |
|
} |
|
if cfg.Queue.MemBuckets != 0 { |
|
options = append(options, diskqueue.SetDynamicMemBucket(cfg.Queue.MemBuckets)) |
|
} |
|
queue, err := diskqueue.New(cfg.Queue.CacheDir, options...) |
|
if err != nil { |
|
return nil, err |
|
} |
|
workers := cfg.UDPCollect.Workers |
|
if workers == 0 { |
|
if runtime.NumCPU() > 4 { |
|
workers = 4 |
|
} else { |
|
workers = runtime.NumCPU() |
|
} |
|
} |
|
clt, err := udpcollect.New(cfg.UDPCollect.Addr, workers, queue.Push) |
|
if err != nil { |
|
return nil, fmt.Errorf("new udpcollect error: %s", err) |
|
} |
|
if err := clt.Start(); err != nil { |
|
return nil, err |
|
} |
|
ag := &Agent{queue: queue, clt: clt} |
|
if !debug { |
|
ag.dlv, err = deliver.New(cfg.Servers, ag.BlockReadFn) |
|
} else { |
|
go ag.debugPrinter() |
|
} |
|
return ag, err |
|
} |
|
|
|
// Reload config, only support reload servers config |
|
func (a *Agent) Reload(cfg *conf.AgentConfig) error { |
|
dlv, err := deliver.New(cfg.Servers, a.BlockReadFn) |
|
if err != nil { |
|
return err |
|
} |
|
if err := a.dlv.Close(); err != nil { |
|
log.Warn("close old deliver error: %s", err) |
|
} |
|
a.dlv = dlv |
|
return nil |
|
} |
|
|
|
// Close agent service |
|
func (a *Agent) Close() error { |
|
var messages []string |
|
if err := a.clt.Close(); err != nil { |
|
messages = append(messages, err.Error()) |
|
} |
|
if a.dlv != nil { |
|
if err := a.dlv.Close(); err != nil { |
|
messages = append(messages, err.Error()) |
|
} |
|
} |
|
if err := a.queue.Close(); err != nil { |
|
messages = append(messages, err.Error()) |
|
} |
|
if len(messages) == 0 { |
|
return nil |
|
} |
|
return fmt.Errorf("close agent error: %s", strings.Join(messages, "\n")) |
|
} |
|
|
|
// BlockReadFn wrap queue.Pop block |
|
func (a *Agent) BlockReadFn() ([]byte, error) { |
|
data, err := a.queue.Pop() |
|
if err != io.EOF { |
|
return data, err |
|
} |
|
tick := time.NewTicker(100 * time.Millisecond) |
|
defer tick.Stop() |
|
for { |
|
select { |
|
case <-tick.C: |
|
} |
|
data, err = a.queue.Pop() |
|
if err != io.EOF { |
|
return data, err |
|
} |
|
} |
|
} |
|
|
|
func (a *Agent) debugPrinter() { |
|
for { |
|
data, err := a.BlockReadFn() |
|
if err != nil { |
|
log.Error("read data error: %s", err) |
|
continue |
|
} |
|
span := new(spanpb.Span) |
|
if err = proto.Unmarshal(data, span); err != nil { |
|
log.Error("unmarshal error: %s, data: %s", err, data) |
|
continue |
|
} |
|
fmt.Printf("received span: %s\n", span) |
|
var kind bool |
|
var component bool |
|
for _, tag := range span.Tags { |
|
if tag.Key == "span.kind" { |
|
kind = true |
|
} |
|
if tag.Key == "component" { |
|
component = true |
|
} |
|
} |
|
if !kind { |
|
fmt.Printf("tag span.kind missing, Either \"client\" or \"server\" for the appropriate roles in an RPC, and \"producer\" or \"consumer\" for the appropriate roles in a messaging scenario.") |
|
} |
|
if !component { |
|
fmt.Printf("tag component missing, The software package, framework, library, or module that generated the associated Span. E.g., \"grpc\", \"django\", \"JDBI\".") |
|
} |
|
} |
|
}
|
|
|