mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-13 12:46:36 +08:00
init
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/go-gost/core/metrics"
|
||||
)
|
||||
|
||||
const (
|
||||
// Number of services. Labels: host.
|
||||
MetricServicesGauge metrics.MetricName = "gost_services"
|
||||
// Total service requests. Labels: host, service.
|
||||
MetricServiceRequestsCounter metrics.MetricName = "gost_service_requests_total"
|
||||
// Number of in-flight requests. Labels: host, service.
|
||||
MetricServiceRequestsInFlightGauge metrics.MetricName = "gost_service_requests_in_flight"
|
||||
// Request duration historgram. Labels: host, service.
|
||||
MetricServiceRequestsDurationObserver metrics.MetricName = "gost_service_request_duration_seconds"
|
||||
// Total service input data transfer size in bytes. Labels: host, service.
|
||||
MetricServiceTransferInputBytesCounter metrics.MetricName = "gost_service_transfer_input_bytes_total"
|
||||
// Total service output data transfer size in bytes. Labels: host, service.
|
||||
MetricServiceTransferOutputBytesCounter metrics.MetricName = "gost_service_transfer_output_bytes_total"
|
||||
// Chain node connect duration histogram. Labels: host, chain, node.
|
||||
MetricNodeConnectDurationObserver metrics.MetricName = "gost_chain_node_connect_duration_seconds"
|
||||
// Total service handler errors. Labels: host, service.
|
||||
MetricServiceHandlerErrorsCounter metrics.MetricName = "gost_service_handler_errors_total"
|
||||
// Total chain connect errors. Labels: host, chain, node.
|
||||
MetricChainErrorsCounter metrics.MetricName = "gost_chain_errors_total"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultMetrics metrics.Metrics = NewMetrics()
|
||||
enabled atomic.Bool
|
||||
)
|
||||
|
||||
func Enable(b bool) {
|
||||
enabled.Store(b)
|
||||
}
|
||||
|
||||
func IsEnabled() bool {
|
||||
return enabled.Load()
|
||||
}
|
||||
|
||||
func GetCounter(name metrics.MetricName, labels metrics.Labels) metrics.Counter {
|
||||
if IsEnabled() {
|
||||
return defaultMetrics.Counter(name, labels)
|
||||
}
|
||||
return noop.Counter(name, labels)
|
||||
}
|
||||
|
||||
func GetGauge(name metrics.MetricName, labels metrics.Labels) metrics.Gauge {
|
||||
if IsEnabled() {
|
||||
return defaultMetrics.Gauge(name, labels)
|
||||
}
|
||||
return noop.Gauge(name, labels)
|
||||
}
|
||||
|
||||
func GetObserver(name metrics.MetricName, labels metrics.Labels) metrics.Observer {
|
||||
if IsEnabled() {
|
||||
return defaultMetrics.Observer(name, labels)
|
||||
}
|
||||
return noop.Observer(name, labels)
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package metrics
|
||||
|
||||
import "github.com/go-gost/core/metrics"
|
||||
|
||||
var (
|
||||
nopGauge = &noopGauge{}
|
||||
nopCounter = &noopCounter{}
|
||||
nopObserver = &noopObserver{}
|
||||
|
||||
noop metrics.Metrics = &noopMetrics{}
|
||||
)
|
||||
|
||||
type noopMetrics struct{}
|
||||
|
||||
func Noop() metrics.Metrics {
|
||||
return noop
|
||||
}
|
||||
|
||||
func (m *noopMetrics) Counter(name metrics.MetricName, labels metrics.Labels) metrics.Counter {
|
||||
return nopCounter
|
||||
}
|
||||
|
||||
func (m *noopMetrics) Gauge(name metrics.MetricName, labels metrics.Labels) metrics.Gauge {
|
||||
return nopGauge
|
||||
}
|
||||
|
||||
func (m *noopMetrics) Observer(name metrics.MetricName, labels metrics.Labels) metrics.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) {}
|
||||
@@ -0,0 +1,135 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/go-gost/core/metrics"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
type promMetrics struct {
|
||||
host string
|
||||
gauges map[metrics.MetricName]*prometheus.GaugeVec
|
||||
counters map[metrics.MetricName]*prometheus.CounterVec
|
||||
histograms map[metrics.MetricName]*prometheus.HistogramVec
|
||||
}
|
||||
|
||||
func NewMetrics() metrics.Metrics {
|
||||
host, _ := os.Hostname()
|
||||
m := &promMetrics{
|
||||
host: host,
|
||||
gauges: map[metrics.MetricName]*prometheus.GaugeVec{
|
||||
MetricServicesGauge: prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: string(MetricServicesGauge),
|
||||
Help: "Current number of services",
|
||||
},
|
||||
[]string{"host"}),
|
||||
MetricServiceRequestsInFlightGauge: prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: string(MetricServiceRequestsInFlightGauge),
|
||||
Help: "Current in-flight requests",
|
||||
},
|
||||
[]string{"host", "service", "client"}),
|
||||
},
|
||||
counters: map[metrics.MetricName]*prometheus.CounterVec{
|
||||
MetricServiceRequestsCounter: prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: string(MetricServiceRequestsCounter),
|
||||
Help: "Total number of requests",
|
||||
},
|
||||
[]string{"host", "service", "client"}),
|
||||
MetricServiceTransferInputBytesCounter: prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: string(MetricServiceTransferInputBytesCounter),
|
||||
Help: "Total service input data transfer size in bytes",
|
||||
},
|
||||
[]string{"host", "service", "client"}),
|
||||
MetricServiceTransferOutputBytesCounter: prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: string(MetricServiceTransferOutputBytesCounter),
|
||||
Help: "Total service output data transfer size in bytes",
|
||||
},
|
||||
[]string{"host", "service", "client"}),
|
||||
MetricServiceHandlerErrorsCounter: prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: string(MetricServiceHandlerErrorsCounter),
|
||||
Help: "Total service handler errors",
|
||||
},
|
||||
[]string{"host", "service", "client"}),
|
||||
MetricChainErrorsCounter: prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: string(MetricChainErrorsCounter),
|
||||
Help: "Total chain errors",
|
||||
},
|
||||
[]string{"host", "chain", "node"}),
|
||||
},
|
||||
histograms: map[metrics.MetricName]*prometheus.HistogramVec{
|
||||
MetricServiceRequestsDurationObserver: prometheus.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: string(MetricServiceRequestsDurationObserver),
|
||||
Help: "Distribution of request latencies",
|
||||
Buckets: []float64{
|
||||
.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 15, 30, 60,
|
||||
},
|
||||
},
|
||||
[]string{"host", "service"}),
|
||||
MetricNodeConnectDurationObserver: prometheus.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: string(MetricNodeConnectDurationObserver),
|
||||
Help: "Distribution of chain node connect latencies",
|
||||
Buckets: []float64{
|
||||
.01, .05, .1, .25, .5, 1, 1.5, 2, 5, 10, 15, 30, 60,
|
||||
},
|
||||
},
|
||||
[]string{"host", "chain", "node"}),
|
||||
},
|
||||
}
|
||||
for k := range m.gauges {
|
||||
prometheus.MustRegister(m.gauges[k])
|
||||
}
|
||||
for k := range m.counters {
|
||||
prometheus.MustRegister(m.counters[k])
|
||||
}
|
||||
for k := range m.histograms {
|
||||
prometheus.MustRegister(m.histograms[k])
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *promMetrics) Gauge(name metrics.MetricName, labels metrics.Labels) metrics.Gauge {
|
||||
v, ok := m.gauges[name]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if labels == nil {
|
||||
labels = metrics.Labels{}
|
||||
}
|
||||
labels["host"] = m.host
|
||||
return v.With(prometheus.Labels(labels))
|
||||
}
|
||||
|
||||
func (m *promMetrics) Counter(name metrics.MetricName, labels metrics.Labels) metrics.Counter {
|
||||
v, ok := m.counters[name]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if labels == nil {
|
||||
labels = metrics.Labels{}
|
||||
}
|
||||
labels["host"] = m.host
|
||||
return v.With(prometheus.Labels(labels))
|
||||
}
|
||||
|
||||
func (m *promMetrics) Observer(name metrics.MetricName, labels metrics.Labels) metrics.Observer {
|
||||
v, ok := m.histograms[name]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if labels == nil {
|
||||
labels = metrics.Labels{}
|
||||
}
|
||||
labels["host"] = m.host
|
||||
return v.With(prometheus.Labels(labels))
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-gost/core/auth"
|
||||
"github.com/go-gost/core/service"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultPath = "/metrics"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
path string
|
||||
auther auth.Authenticator
|
||||
}
|
||||
|
||||
type Option func(*options)
|
||||
|
||||
func PathOption(path string) Option {
|
||||
return func(o *options) {
|
||||
o.path = path
|
||||
}
|
||||
}
|
||||
|
||||
func AutherOption(auther auth.Authenticator) Option {
|
||||
return func(o *options) {
|
||||
o.auther = auther
|
||||
}
|
||||
}
|
||||
|
||||
type metricService struct {
|
||||
s *http.Server
|
||||
ln net.Listener
|
||||
cclose chan struct{}
|
||||
}
|
||||
|
||||
func NewService(network, addr string, opts ...Option) (service.Service, error) {
|
||||
if network == "" {
|
||||
network = "tcp"
|
||||
}
|
||||
ln, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var options options
|
||||
for _, opt := range opts {
|
||||
opt(&options)
|
||||
}
|
||||
if options.path == "" {
|
||||
options.path = DefaultPath
|
||||
}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle(options.path, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if options.auther != nil {
|
||||
u, p, _ := r.BasicAuth()
|
||||
if _, ok := options.auther.Authenticate(r.Context(), u, p); !ok {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
}
|
||||
promhttp.Handler().ServeHTTP(w, r)
|
||||
}))
|
||||
return &metricService{
|
||||
s: &http.Server{
|
||||
Handler: mux,
|
||||
},
|
||||
ln: ln,
|
||||
cclose: make(chan struct{}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *metricService) Serve() error {
|
||||
return s.s.Serve(s.ln)
|
||||
}
|
||||
|
||||
func (s *metricService) Addr() net.Addr {
|
||||
return s.ln.Addr()
|
||||
}
|
||||
|
||||
func (s *metricService) Close() error {
|
||||
return s.s.Close()
|
||||
}
|
||||
|
||||
func (s *metricService) IsClosed() bool {
|
||||
select {
|
||||
case <-s.cclose:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
package wrapper
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"github.com/go-gost/core/metadata"
|
||||
"github.com/go-gost/core/metrics"
|
||||
xnet "github.com/go-gost/x/internal/net"
|
||||
"github.com/go-gost/x/internal/net/udp"
|
||||
xmetrics "github.com/go-gost/x/metrics"
|
||||
)
|
||||
|
||||
var (
|
||||
errUnsupport = errors.New("unsupported operation")
|
||||
)
|
||||
|
||||
// serverConn is a server side Conn with metrics supported.
|
||||
type serverConn struct {
|
||||
net.Conn
|
||||
service string
|
||||
clientIP string
|
||||
}
|
||||
|
||||
func WrapConn(service string, c net.Conn) net.Conn {
|
||||
if !xmetrics.IsEnabled() || c == nil {
|
||||
return c
|
||||
}
|
||||
|
||||
host, _, _ := net.SplitHostPort(c.RemoteAddr().String())
|
||||
|
||||
return &serverConn{
|
||||
service: service,
|
||||
Conn: c,
|
||||
clientIP: host,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *serverConn) Read(b []byte) (n int, err error) {
|
||||
n, err = c.Conn.Read(b)
|
||||
if counter := xmetrics.GetCounter(
|
||||
xmetrics.MetricServiceTransferInputBytesCounter,
|
||||
metrics.Labels{
|
||||
"service": c.service,
|
||||
"client": c.clientIP,
|
||||
}); counter != nil {
|
||||
counter.Add(float64(n))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *serverConn) Write(b []byte) (n int, err error) {
|
||||
n, err = c.Conn.Write(b)
|
||||
if counter := xmetrics.GetCounter(
|
||||
xmetrics.MetricServiceTransferOutputBytesCounter,
|
||||
metrics.Labels{
|
||||
"service": c.service,
|
||||
"client": c.clientIP,
|
||||
}); counter != nil {
|
||||
counter.Add(float64(n))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *serverConn) SyscallConn() (rc syscall.RawConn, err error) {
|
||||
if sc, ok := c.Conn.(syscall.Conn); ok {
|
||||
rc, err = sc.SyscallConn()
|
||||
return
|
||||
}
|
||||
err = errUnsupport
|
||||
return
|
||||
}
|
||||
|
||||
func (c *serverConn) Metadata() metadata.Metadata {
|
||||
if md, ok := c.Conn.(metadata.Metadatable); ok {
|
||||
return md.Metadata()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type packetConn struct {
|
||||
net.PacketConn
|
||||
service string
|
||||
}
|
||||
|
||||
func WrapPacketConn(service string, pc net.PacketConn) net.PacketConn {
|
||||
if !xmetrics.IsEnabled() {
|
||||
return pc
|
||||
}
|
||||
return &packetConn{
|
||||
PacketConn: pc,
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *packetConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||
n, addr, err = c.PacketConn.ReadFrom(p)
|
||||
|
||||
var clientIP string
|
||||
if addr != nil {
|
||||
clientIP, _, _ = net.SplitHostPort(addr.String())
|
||||
}
|
||||
|
||||
if counter := xmetrics.GetCounter(
|
||||
xmetrics.MetricServiceTransferInputBytesCounter,
|
||||
metrics.Labels{
|
||||
"service": c.service,
|
||||
"client": clientIP,
|
||||
}); counter != nil {
|
||||
counter.Add(float64(n))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *packetConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||
n, err = c.PacketConn.WriteTo(p, addr)
|
||||
|
||||
var clientIP string
|
||||
if addr != nil {
|
||||
clientIP, _, _ = net.SplitHostPort(addr.String())
|
||||
}
|
||||
|
||||
if counter := xmetrics.GetCounter(
|
||||
xmetrics.MetricServiceTransferOutputBytesCounter,
|
||||
metrics.Labels{
|
||||
"service": c.service,
|
||||
"client": clientIP,
|
||||
}); counter != nil {
|
||||
counter.Add(float64(n))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *packetConn) Metadata() metadata.Metadata {
|
||||
if md, ok := c.PacketConn.(metadata.Metadatable); ok {
|
||||
return md.Metadata()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type udpConn struct {
|
||||
net.PacketConn
|
||||
service string
|
||||
}
|
||||
|
||||
func WrapUDPConn(service string, pc net.PacketConn) udp.Conn {
|
||||
return &udpConn{
|
||||
PacketConn: pc,
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *udpConn) RemoteAddr() net.Addr {
|
||||
if nc, ok := c.PacketConn.(xnet.RemoteAddr); ok {
|
||||
return nc.RemoteAddr()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *udpConn) SetReadBuffer(n int) error {
|
||||
if nc, ok := c.PacketConn.(xnet.SetBuffer); ok {
|
||||
return nc.SetReadBuffer(n)
|
||||
}
|
||||
return errUnsupport
|
||||
}
|
||||
|
||||
func (c *udpConn) SetWriteBuffer(n int) error {
|
||||
if nc, ok := c.PacketConn.(xnet.SetBuffer); ok {
|
||||
return nc.SetWriteBuffer(n)
|
||||
}
|
||||
return errUnsupport
|
||||
}
|
||||
|
||||
func (c *udpConn) Read(b []byte) (n int, err error) {
|
||||
if nc, ok := c.PacketConn.(io.Reader); ok {
|
||||
n, err = nc.Read(b)
|
||||
|
||||
var clientIP string
|
||||
if addr := c.RemoteAddr(); addr != nil {
|
||||
clientIP, _, _ = net.SplitHostPort(addr.String())
|
||||
}
|
||||
|
||||
if counter := xmetrics.GetCounter(
|
||||
xmetrics.MetricServiceTransferInputBytesCounter,
|
||||
metrics.Labels{
|
||||
"service": c.service,
|
||||
"client": clientIP,
|
||||
}); counter != nil {
|
||||
counter.Add(float64(n))
|
||||
}
|
||||
return
|
||||
}
|
||||
err = errUnsupport
|
||||
return
|
||||
}
|
||||
|
||||
func (c *udpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||
n, addr, err = c.PacketConn.ReadFrom(p)
|
||||
|
||||
var clientIP string
|
||||
if addr != nil {
|
||||
clientIP, _, _ = net.SplitHostPort(addr.String())
|
||||
}
|
||||
|
||||
if counter := xmetrics.GetCounter(
|
||||
xmetrics.MetricServiceTransferInputBytesCounter,
|
||||
metrics.Labels{
|
||||
"service": c.service,
|
||||
"client": clientIP,
|
||||
}); counter != nil {
|
||||
counter.Add(float64(n))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *udpConn) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) {
|
||||
if nc, ok := c.PacketConn.(udp.ReadUDP); ok {
|
||||
n, addr, err = nc.ReadFromUDP(b)
|
||||
|
||||
var clientIP string
|
||||
if addr != nil {
|
||||
clientIP, _, _ = net.SplitHostPort(addr.String())
|
||||
}
|
||||
|
||||
if counter := xmetrics.GetCounter(
|
||||
xmetrics.MetricServiceTransferInputBytesCounter,
|
||||
metrics.Labels{
|
||||
"service": c.service,
|
||||
"client": clientIP,
|
||||
}); counter != nil {
|
||||
counter.Add(float64(n))
|
||||
}
|
||||
return
|
||||
}
|
||||
err = errUnsupport
|
||||
return
|
||||
}
|
||||
|
||||
func (c *udpConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error) {
|
||||
if nc, ok := c.PacketConn.(udp.ReadUDP); ok {
|
||||
n, oobn, flags, addr, err = nc.ReadMsgUDP(b, oob)
|
||||
|
||||
var clientIP string
|
||||
if addr != nil {
|
||||
clientIP, _, _ = net.SplitHostPort(addr.String())
|
||||
}
|
||||
|
||||
if counter := xmetrics.GetCounter(
|
||||
xmetrics.MetricServiceTransferInputBytesCounter,
|
||||
metrics.Labels{
|
||||
"service": c.service,
|
||||
"client": clientIP,
|
||||
}); counter != nil {
|
||||
counter.Add(float64(n))
|
||||
}
|
||||
return
|
||||
}
|
||||
err = errUnsupport
|
||||
return
|
||||
}
|
||||
|
||||
func (c *udpConn) Write(b []byte) (n int, err error) {
|
||||
if nc, ok := c.PacketConn.(io.Writer); ok {
|
||||
n, err = nc.Write(b)
|
||||
|
||||
var clientIP string
|
||||
if addr := c.RemoteAddr(); addr != nil {
|
||||
clientIP, _, _ = net.SplitHostPort(addr.String())
|
||||
}
|
||||
|
||||
if counter := xmetrics.GetCounter(
|
||||
xmetrics.MetricServiceTransferOutputBytesCounter,
|
||||
metrics.Labels{
|
||||
"service": c.service,
|
||||
"client": clientIP,
|
||||
}); counter != nil {
|
||||
counter.Add(float64(n))
|
||||
}
|
||||
return
|
||||
}
|
||||
err = errUnsupport
|
||||
return
|
||||
}
|
||||
|
||||
func (c *udpConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||
n, err = c.PacketConn.WriteTo(p, addr)
|
||||
|
||||
var clientIP string
|
||||
if addr != nil {
|
||||
clientIP, _, _ = net.SplitHostPort(addr.String())
|
||||
}
|
||||
|
||||
if counter := xmetrics.GetCounter(
|
||||
xmetrics.MetricServiceTransferOutputBytesCounter,
|
||||
metrics.Labels{
|
||||
"service": c.service,
|
||||
"client": clientIP,
|
||||
}); counter != nil {
|
||||
counter.Add(float64(n))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *udpConn) WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) {
|
||||
if nc, ok := c.PacketConn.(udp.WriteUDP); ok {
|
||||
n, err = nc.WriteToUDP(b, addr)
|
||||
|
||||
var clientIP string
|
||||
if addr != nil {
|
||||
clientIP, _, _ = net.SplitHostPort(addr.String())
|
||||
}
|
||||
|
||||
if counter := xmetrics.GetCounter(
|
||||
xmetrics.MetricServiceTransferOutputBytesCounter,
|
||||
metrics.Labels{
|
||||
"service": c.service,
|
||||
"client": clientIP,
|
||||
}); counter != nil {
|
||||
counter.Add(float64(n))
|
||||
}
|
||||
return
|
||||
}
|
||||
err = errUnsupport
|
||||
return
|
||||
}
|
||||
|
||||
func (c *udpConn) WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error) {
|
||||
if nc, ok := c.PacketConn.(udp.WriteUDP); ok {
|
||||
n, oobn, err = nc.WriteMsgUDP(b, oob, addr)
|
||||
|
||||
var clientIP string
|
||||
if addr != nil {
|
||||
clientIP, _, _ = net.SplitHostPort(addr.String())
|
||||
}
|
||||
|
||||
if counter := xmetrics.GetCounter(
|
||||
xmetrics.MetricServiceTransferOutputBytesCounter,
|
||||
metrics.Labels{
|
||||
"service": c.service,
|
||||
"client": clientIP,
|
||||
}); counter != nil {
|
||||
counter.Add(float64(n))
|
||||
}
|
||||
return
|
||||
}
|
||||
err = errUnsupport
|
||||
return
|
||||
}
|
||||
|
||||
func (c *udpConn) SyscallConn() (rc syscall.RawConn, err error) {
|
||||
if nc, ok := c.PacketConn.(syscall.Conn); ok {
|
||||
return nc.SyscallConn()
|
||||
}
|
||||
err = errUnsupport
|
||||
return
|
||||
}
|
||||
|
||||
func (c *udpConn) SetDSCP(n int) error {
|
||||
if nc, ok := c.PacketConn.(xnet.SetDSCP); ok {
|
||||
return nc.SetDSCP(n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *udpConn) Metadata() metadata.Metadata {
|
||||
if md, ok := c.PacketConn.(metadata.Metadatable); ok {
|
||||
return md.Metadata()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package wrapper
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
xmetrics "github.com/go-gost/x/metrics"
|
||||
)
|
||||
|
||||
type listener struct {
|
||||
service string
|
||||
net.Listener
|
||||
}
|
||||
|
||||
func WrapListener(service string, ln net.Listener) net.Listener {
|
||||
if !xmetrics.IsEnabled() {
|
||||
return ln
|
||||
}
|
||||
|
||||
return &listener{
|
||||
service: service,
|
||||
Listener: ln,
|
||||
}
|
||||
}
|
||||
|
||||
func (ln *listener) Accept() (net.Conn, error) {
|
||||
c, err := ln.Listener.Accept()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return WrapConn(ln.service, c), nil
|
||||
}
|
||||
Reference in New Issue
Block a user