xmaker: add more xmaker metrics and profiles

This commit is contained in:
c9s 2024-10-09 11:47:10 +08:00
parent a8f163bfd3
commit e70899a35d
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
5 changed files with 36 additions and 9 deletions

View File

@ -9,7 +9,7 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/time/rate" "golang.org/x/time/rate"
"github.com/c9s/bbgo/pkg/util" "github.com/c9s/bbgo/pkg/profile/timeprofile"
) )
var log = logrus.WithField("component", "batch") var log = logrus.WithField("component", "batch")
@ -56,7 +56,7 @@ func (q *AsyncTimeRangedBatchQuery) Query(ctx context.Context, ch interface{}, s
log.Debugf("batch querying %T: %v <=> %v", q.Type, startTime, endTime) log.Debugf("batch querying %T: %v <=> %v", q.Type, startTime, endTime)
queryProfiler := util.StartTimeProfile("remoteQuery") queryProfiler := timeprofile.Start("remoteQuery")
sliceInf, err := q.Q(startTime, endTime) sliceInf, err := q.Q(startTime, endTime)
if err != nil { if err != nil {

View File

@ -1,34 +1,43 @@
package util package timeprofile
import ( import (
"time" "time"
) )
type logFunction func(format string, args ...interface{})
type TimeProfile struct { type TimeProfile struct {
Name string Name string
StartTime, EndTime time.Time StartTime, EndTime time.Time
Duration time.Duration Duration time.Duration
} }
func StartTimeProfile(args ...string) TimeProfile { func Start(args ...string) TimeProfile {
name := "" name := ""
if len(args) > 0 { if len(args) > 0 {
name = args[0] name = args[0]
} }
return TimeProfile{StartTime: time.Now(), Name: name} return TimeProfile{StartTime: time.Now(), Name: name}
} }
// TilNow returns the duration from the start time to now
func (p *TimeProfile) TilNow() time.Duration { func (p *TimeProfile) TilNow() time.Duration {
return time.Since(p.StartTime) return time.Since(p.StartTime)
} }
// Stop stops the time profile, set the end time and returns the duration
func (p *TimeProfile) Stop() time.Duration { func (p *TimeProfile) Stop() time.Duration {
p.EndTime = time.Now() p.EndTime = time.Now()
p.Duration = p.EndTime.Sub(p.StartTime) p.Duration = p.EndTime.Sub(p.StartTime)
return p.Duration return p.Duration
} }
type logFunction func(format string, args ...interface{}) // Do runs the function f and stops the time profile
func (p *TimeProfile) Do(f func()) {
defer p.Stop()
f()
}
func (p *TimeProfile) StopAndLog(f logFunction) { func (p *TimeProfile) StopAndLog(f logFunction) {
duration := p.Stop() duration := p.Stop()

View File

@ -18,10 +18,10 @@ import (
"github.com/c9s/bbgo/pkg/core" "github.com/c9s/bbgo/pkg/core"
"github.com/c9s/bbgo/pkg/exchange/retry" "github.com/c9s/bbgo/pkg/exchange/retry"
"github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/profile/timeprofile"
"github.com/c9s/bbgo/pkg/sigchan" "github.com/c9s/bbgo/pkg/sigchan"
"github.com/c9s/bbgo/pkg/style" "github.com/c9s/bbgo/pkg/style"
"github.com/c9s/bbgo/pkg/types" "github.com/c9s/bbgo/pkg/types"
"github.com/c9s/bbgo/pkg/util"
) )
//go:generate bash symbols.sh //go:generate bash symbols.sh
@ -675,7 +675,7 @@ func (s *Strategy) iocOrderExecution(
} }
func (s *Strategy) waitWebSocketOrderDone(ctx context.Context, orderID uint64, timeoutDuration time.Duration) (*types.Order, error) { func (s *Strategy) waitWebSocketOrderDone(ctx context.Context, orderID uint64, timeoutDuration time.Duration) (*types.Order, error) {
prof := util.StartTimeProfile("waitWebSocketOrderDone") prof := timeprofile.Start("waitWebSocketOrderDone")
defer prof.StopAndLog(log.Infof) defer prof.StopAndLog(log.Infof)
if order, ok := s.orderStore.Get(orderID); ok { if order, ok := s.orderStore.Get(orderID); ok {
@ -869,7 +869,7 @@ func (s *Strategy) calculateRanks(minRatio float64, method func(p *Path) float64
func waitForOrderFilled( func waitForOrderFilled(
ctx context.Context, ex types.ExchangeOrderQueryService, order types.Order, timeout time.Duration, ctx context.Context, ex types.ExchangeOrderQueryService, order types.Order, timeout time.Duration,
) (*types.Order, error) { ) (*types.Order, error) {
prof := util.StartTimeProfile("waitForOrderFilled") prof := timeprofile.Start("waitForOrderFilled")
defer prof.StopAndLog(log.Infof) defer prof.StopAndLog(log.Infof)
timeoutC := time.After(timeout) timeoutC := time.After(timeout)
@ -880,7 +880,7 @@ func waitForOrderFilled(
return nil, fmt.Errorf("order wait timeout %s", timeout) return nil, fmt.Errorf("order wait timeout %s", timeout)
default: default:
p := util.StartTimeProfile("queryOrder") p := timeprofile.Start("queryOrder")
remoteOrder, err2 := ex.QueryOrder(ctx, types.OrderQuery{ remoteOrder, err2 := ex.QueryOrder(ctx, types.OrderQuery{
Symbol: order.Symbol, Symbol: order.Symbol,
OrderID: strconv.FormatUint(order.OrderID, 10), OrderID: strconv.FormatUint(order.OrderID, 10),

View File

@ -2,6 +2,18 @@ package xmaker
import "github.com/prometheus/client_golang/prometheus" import "github.com/prometheus/client_golang/prometheus"
var cancelOrderDurationMetrics = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "xmaker_cancel_order_duration_milliseconds",
Help: "cancel order duration in milliseconds",
}, []string{"strategy_type", "strategy_id", "exchange", "symbol"})
var makerOrderPlacementDurationMetrics = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "xmaker_maker_order_placement_duration_milliseconds",
Help: "maker order placement duration in milliseconds",
}, []string{"strategy_type", "strategy_id", "exchange", "symbol"})
var openOrderBidExposureInUsdMetrics = prometheus.NewGaugeVec( var openOrderBidExposureInUsdMetrics = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "xmaker_open_order_bid_exposure_in_usd", Name: "xmaker_open_order_bid_exposure_in_usd",
@ -77,6 +89,8 @@ func init() {
bidMarginMetrics, bidMarginMetrics,
askMarginMetrics, askMarginMetrics,
aggregatedSignalMetrics, aggregatedSignalMetrics,
cancelOrderDurationMetrics,
makerOrderPlacementDurationMetrics,
configNumOfLayersMetrics, configNumOfLayersMetrics,
configMaxExposureMetrics, configMaxExposureMetrics,
configBidMarginMetrics, configBidMarginMetrics,

View File

@ -17,6 +17,7 @@ import (
"github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/fixedpoint"
indicatorv2 "github.com/c9s/bbgo/pkg/indicator/v2" indicatorv2 "github.com/c9s/bbgo/pkg/indicator/v2"
"github.com/c9s/bbgo/pkg/pricesolver" "github.com/c9s/bbgo/pkg/pricesolver"
"github.com/c9s/bbgo/pkg/profile/timeprofile"
"github.com/c9s/bbgo/pkg/risk/circuitbreaker" "github.com/c9s/bbgo/pkg/risk/circuitbreaker"
"github.com/c9s/bbgo/pkg/strategy/common" "github.com/c9s/bbgo/pkg/strategy/common"
"github.com/c9s/bbgo/pkg/types" "github.com/c9s/bbgo/pkg/types"
@ -914,12 +915,15 @@ func (s *Strategy) updateQuote(ctx context.Context) error {
defer s.tradeCollector.Process() defer s.tradeCollector.Process()
makerOrderPlacementProfile := timeprofile.Start("makerOrderPlacement")
createdOrders, errIdx, err := bbgo.BatchPlaceOrder(ctx, s.makerSession.Exchange, s.makerOrderCreateCallback, formattedOrders...) createdOrders, errIdx, err := bbgo.BatchPlaceOrder(ctx, s.makerSession.Exchange, s.makerOrderCreateCallback, formattedOrders...)
if err != nil { if err != nil {
log.WithError(err).Errorf("unable to place maker orders: %+v", formattedOrders) log.WithError(err).Errorf("unable to place maker orders: %+v", formattedOrders)
return err return err
} }
makerOrderPlacementDurationMetrics.With(s.metricsLabels).Observe(float64(makerOrderPlacementProfile.Stop().Milliseconds()))
openOrderBidExposureInUsdMetrics.With(s.metricsLabels).Set(bidExposureInUsd.Float64()) openOrderBidExposureInUsdMetrics.With(s.metricsLabels).Set(bidExposureInUsd.Float64())
openOrderAskExposureInUsdMetrics.With(s.metricsLabels).Set(askExposureInUsd.Float64()) openOrderAskExposureInUsdMetrics.With(s.metricsLabels).Set(askExposureInUsd.Float64())