func (c *Client) Stats(addr string, options ...StatsOption) (stats.Stats, error) {
	var extra protocol.StatsExtra
	for _, opt := range options {
		opt(&extra)
	}
	s := stats.Stats{}
	req := protocol.NewSystemMessage(protocol.OpStats)
	req.SetExtra(extra)
	resp, err := c.client.RequestTo(addr, req)
	if err != nil {
		return s, err
	}
	err = checkStatusCode(resp)
	if err != nil {
		return s, err
	}
	err = msgpack.Unmarshal(resp.Value(), &s)
	if err != nil {
		return s, err
	}
	return s, nil
}
Stats exposes some useful metrics to monitor an Olric node.
package client  
import (
	"fmt"
	"log"
	"os"
	"sync"
	"github.com/buraksezer/olric"
	"github.com/buraksezer/olric/config"
	"github.com/buraksezer/olric/internal/bufpool"
	"github.com/buraksezer/olric/internal/kvstore"
	"github.com/buraksezer/olric/internal/protocol"
	"github.com/buraksezer/olric/internal/transport"
	"github.com/buraksezer/olric/pkg/storage"
	"github.com/buraksezer/olric/serializer"
	"github.com/buraksezer/olric/stats"
	"github.com/pkg/errors"
	"github.com/vmihailenco/msgpack"
)
var (
	logger     = log.New(os.Stderr, "olric: ", log.Lshortfile)
	bufferPool = bufpool.New()
)
type Client struct {
	config       *Config
	client       *transport.Client
	roundRobin   *roundRobin
	serializer   serializer.Serializer
	streams      *streams
	entryFormats map[string]storage.Entry
	wg           sync.WaitGroup
}
type Config struct {
	Servers               []string
	Serializer            serializer.Serializer
	Client                *config.Client
	MaxListenersPerStream int  
	EntryFormats map[string]storage.Entry
}
func New(c *Config) (*Client, error) {
	if c == nil {
		return nil, fmt.Errorf("config cannot be nil")
	}
	if len(c.Servers) == 0 {
		return nil, fmt.Errorf("servers cannot be empty")
	}
	if c.Serializer == nil {
		c.Serializer = serializer.NewGobSerializer()
	}
	if c.MaxListenersPerStream <= 0 {
		c.MaxListenersPerStream = maxListenersPerStream
	}
	err := c.Client.Sanitize()
	if err != nil {
		return nil, err
	}
	client := transport.NewClient(c.Client)
	createStreamFunction = client.CreateStream
	return &Client{
		roundRobin:   newRoundRobin(c.Servers),
		config:       c,
		client:       client,
		serializer:   c.Serializer,
		entryFormats: c.EntryFormats,
		streams:      &streams{m: make(map[uint64]*stream)},
	}, nil
}
func (c *Client) getEntryFormat(name string) storage.Entry {
	e, ok := c.entryFormats[name]
	if !ok {
		e = &kvstore.Entry{}
	}
	return e
}
func (c *Client) AddServer(addr string) {
	c.roundRobin.add(addr)
}
func (c *Client) DeleteServer(addr string) error {
	return c.roundRobin.delete(addr)
}
func (c *Client) Ping(addr string) error {
	req := protocol.NewSystemMessage(protocol.OpPing)
	_, err := c.client.RequestTo(addr, req)
	return err
}
func (c *Client) request(req protocol.EncodeDecoder) (protocol.EncodeDecoder, error) {
	addr := c.roundRobin.get()
	return c.client.RequestTo(addr, req)
}