mv metrics/service to x
This commit is contained in:
@ -26,6 +26,7 @@ type Route interface {
|
|||||||
Nodes() []*Node
|
Nodes() []*Node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// route is a Route without nodes.
|
||||||
type route struct{}
|
type route struct{}
|
||||||
|
|
||||||
func (*route) Dial(ctx context.Context, network, address string, opts ...DialOption) (net.Conn, error) {
|
func (*route) Dial(ctx context.Context, network, address string, opts ...DialOption) (net.Conn, error) {
|
||||||
|
@ -18,10 +18,10 @@ type SockOpts struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RouterOptions struct {
|
type RouterOptions struct {
|
||||||
|
Retries int
|
||||||
|
Timeout time.Duration
|
||||||
IfceName string
|
IfceName string
|
||||||
SockOpts *SockOpts
|
SockOpts *SockOpts
|
||||||
Timeout time.Duration
|
|
||||||
Retries int
|
|
||||||
Chain Chainer
|
Chain Chainer
|
||||||
Resolver resolver.Resolver
|
Resolver resolver.Resolver
|
||||||
HostMapper hosts.HostMapper
|
HostMapper hosts.HostMapper
|
||||||
|
@ -2,45 +2,8 @@ package metrics
|
|||||||
|
|
||||||
type MetricName string
|
type MetricName string
|
||||||
|
|
||||||
const (
|
|
||||||
// Number of services. Labels: host.
|
|
||||||
MetricServicesGauge MetricName = "gost_services"
|
|
||||||
// Total service requests. Labels: host, service.
|
|
||||||
MetricServiceRequestsCounter MetricName = "gost_service_requests_total"
|
|
||||||
// Number of in-flight requests. Labels: host, service.
|
|
||||||
MetricServiceRequestsInFlightGauge MetricName = "gost_service_requests_in_flight"
|
|
||||||
// Request duration historgram. Labels: host, service.
|
|
||||||
MetricServiceRequestsDurationObserver MetricName = "gost_service_request_duration_seconds"
|
|
||||||
// Total service input data transfer size in bytes. Labels: host, service.
|
|
||||||
MetricServiceTransferInputBytesCounter MetricName = "gost_service_transfer_input_bytes_total"
|
|
||||||
// Total service output data transfer size in bytes. Labels: host, service.
|
|
||||||
MetricServiceTransferOutputBytesCounter MetricName = "gost_service_transfer_output_bytes_total"
|
|
||||||
// Chain node connect duration histogram. Labels: host, chain, node.
|
|
||||||
MetricNodeConnectDurationObserver MetricName = "gost_chain_node_connect_duration_seconds"
|
|
||||||
// Total service handler errors. Labels: host, service.
|
|
||||||
MetricServiceHandlerErrorsCounter MetricName = "gost_service_handler_errors_total"
|
|
||||||
// Total chain connect errors. Labels: host, chain, node.
|
|
||||||
MetricChainErrorsCounter MetricName = "gost_chain_errors_total"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Labels map[string]string
|
type Labels map[string]string
|
||||||
|
|
||||||
var (
|
|
||||||
global Metrics = Noop()
|
|
||||||
)
|
|
||||||
|
|
||||||
func Init(m Metrics) {
|
|
||||||
if m != nil {
|
|
||||||
global = m
|
|
||||||
} else {
|
|
||||||
global = Noop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsEnabled() bool {
|
|
||||||
return global != Noop()
|
|
||||||
}
|
|
||||||
|
|
||||||
type Gauge interface {
|
type Gauge interface {
|
||||||
Inc()
|
Inc()
|
||||||
Dec()
|
Dec()
|
||||||
@ -62,15 +25,3 @@ type Metrics interface {
|
|||||||
Gauge(name MetricName, labels Labels) Gauge
|
Gauge(name MetricName, labels Labels) Gauge
|
||||||
Observer(name MetricName, labels Labels) Observer
|
Observer(name MetricName, labels Labels) Observer
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCounter(name MetricName, labels Labels) Counter {
|
|
||||||
return global.Counter(name, labels)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetGauge(name MetricName, labels Labels) Gauge {
|
|
||||||
return global.Gauge(name, labels)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetObserver(name MetricName, labels Labels) Observer {
|
|
||||||
return global.Observer(name, labels)
|
|
||||||
}
|
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
package metrics
|
|
||||||
|
|
||||||
var (
|
|
||||||
nopGauge = &noopGauge{}
|
|
||||||
nopCounter = &noopCounter{}
|
|
||||||
nopObserver = &noopObserver{}
|
|
||||||
|
|
||||||
noop Metrics = &noopMetrics{}
|
|
||||||
)
|
|
||||||
|
|
||||||
type noopMetrics struct{}
|
|
||||||
|
|
||||||
func Noop() Metrics {
|
|
||||||
return noop
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *noopMetrics) Counter(name MetricName, labels Labels) Counter {
|
|
||||||
return nopCounter
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *noopMetrics) Gauge(name MetricName, labels Labels) Gauge {
|
|
||||||
return nopGauge
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *noopMetrics) Observer(name MetricName, labels Labels) Observer {
|
|
||||||
return nopObserver
|
|
||||||
}
|
|
||||||
|
|
||||||
type noopGauge struct{}
|
|
||||||
|
|
||||||
func (*noopGauge) Inc() {}
|
|
||||||
func (*noopGauge) Dec() {}
|
|
||||||
func (*noopGauge) Add(v float64) {}
|
|
||||||
func (*noopGauge) Set(v float64) {}
|
|
||||||
|
|
||||||
type noopCounter struct{}
|
|
||||||
|
|
||||||
func (*noopCounter) Inc() {}
|
|
||||||
func (*noopCounter) Add(v float64) {}
|
|
||||||
|
|
||||||
type noopObserver struct{}
|
|
||||||
|
|
||||||
func (*noopObserver) Observe(v float64) {}
|
|
@ -1,157 +1,11 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"net"
|
"net"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/core/admission"
|
|
||||||
"github.com/go-gost/core/handler"
|
|
||||||
"github.com/go-gost/core/listener"
|
|
||||||
"github.com/go-gost/core/logger"
|
|
||||||
"github.com/go-gost/core/metrics"
|
|
||||||
"github.com/go-gost/core/recorder"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type options struct {
|
|
||||||
admission admission.Admission
|
|
||||||
recorders []recorder.RecorderObject
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
type Option func(opts *options)
|
|
||||||
|
|
||||||
func AdmissionOption(admission admission.Admission) Option {
|
|
||||||
return func(opts *options) {
|
|
||||||
opts.admission = admission
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func RecordersOption(recorders ...recorder.RecorderObject) Option {
|
|
||||||
return func(opts *options) {
|
|
||||||
opts.recorders = recorders
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoggerOption(logger logger.Logger) Option {
|
|
||||||
return func(opts *options) {
|
|
||||||
opts.logger = logger
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Service interface {
|
type Service interface {
|
||||||
Serve() error
|
Serve() error
|
||||||
Addr() net.Addr
|
Addr() net.Addr
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type service struct {
|
|
||||||
name string
|
|
||||||
listener listener.Listener
|
|
||||||
handler handler.Handler
|
|
||||||
options options
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewService(name string, ln listener.Listener, h handler.Handler, opts ...Option) Service {
|
|
||||||
var options options
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
return &service{
|
|
||||||
name: name,
|
|
||||||
listener: ln,
|
|
||||||
handler: h,
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *service) Addr() net.Addr {
|
|
||||||
return s.listener.Addr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *service) Close() error {
|
|
||||||
return s.listener.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *service) Serve() error {
|
|
||||||
if v := metrics.GetGauge(
|
|
||||||
metrics.MetricServicesGauge,
|
|
||||||
metrics.Labels{}); v != nil {
|
|
||||||
v.Inc()
|
|
||||||
defer v.Dec()
|
|
||||||
}
|
|
||||||
|
|
||||||
var tempDelay time.Duration
|
|
||||||
for {
|
|
||||||
conn, e := s.listener.Accept()
|
|
||||||
if e != nil {
|
|
||||||
// TODO: remove Temporary checking
|
|
||||||
if ne, ok := e.(net.Error); ok && ne.Temporary() {
|
|
||||||
if tempDelay == 0 {
|
|
||||||
tempDelay = 1 * time.Second
|
|
||||||
} else {
|
|
||||||
tempDelay *= 2
|
|
||||||
}
|
|
||||||
if max := 5 * time.Second; tempDelay > max {
|
|
||||||
tempDelay = max
|
|
||||||
}
|
|
||||||
s.options.logger.Warnf("accept: %v, retrying in %v", e, tempDelay)
|
|
||||||
time.Sleep(tempDelay)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
s.options.logger.Errorf("accept: %v", e)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
tempDelay = 0
|
|
||||||
|
|
||||||
for _, rec := range s.options.recorders {
|
|
||||||
host := conn.RemoteAddr().String()
|
|
||||||
if h, _, _ := net.SplitHostPort(host); h != "" {
|
|
||||||
host = h
|
|
||||||
}
|
|
||||||
if rec.Record == recorder.RecorderServiceClientAddress {
|
|
||||||
if err := rec.Recorder.Record(context.Background(), []byte(host)); err != nil {
|
|
||||||
s.options.logger.Errorf("record %s: %v", rec.Record, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if s.options.admission != nil &&
|
|
||||||
!s.options.admission.Admit(conn.RemoteAddr().String()) {
|
|
||||||
conn.Close()
|
|
||||||
s.options.logger.Debugf("admission: %s is denied", conn.RemoteAddr())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
if v := metrics.GetCounter(metrics.MetricServiceRequestsCounter,
|
|
||||||
metrics.Labels{"service": s.name}); v != nil {
|
|
||||||
v.Inc()
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := metrics.GetGauge(metrics.MetricServiceRequestsInFlightGauge,
|
|
||||||
metrics.Labels{"service": s.name}); v != nil {
|
|
||||||
v.Inc()
|
|
||||||
defer v.Dec()
|
|
||||||
}
|
|
||||||
|
|
||||||
start := time.Now()
|
|
||||||
if v := metrics.GetObserver(metrics.MetricServiceRequestsDurationObserver,
|
|
||||||
metrics.Labels{"service": s.name}); v != nil {
|
|
||||||
defer func() {
|
|
||||||
v.Observe(float64(time.Since(start).Seconds()))
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.handler.Handle(
|
|
||||||
context.Background(),
|
|
||||||
conn,
|
|
||||||
); err != nil {
|
|
||||||
s.options.logger.Error(err)
|
|
||||||
if v := metrics.GetCounter(metrics.MetricServiceHandlerErrorsCounter,
|
|
||||||
metrics.Labels{"service": s.name}); v != nil {
|
|
||||||
v.Inc()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user