From e7d61e08ebe25d5ce3193e792717acd4bb0ffb3e Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Tue, 12 May 2015 22:43:16 +0200 Subject: [PATCH] Convert the code to the new client.Client interface. Drop the custom query abstraction in favor of client.Query(). --- main.go | 18 +-------- server/graph.go | 10 ++++- server/query.go | 101 +++++++++++------------------------------------ server/server.go | 36 ++++++----------- 4 files changed, 42 insertions(+), 123 deletions(-) diff --git a/main.go b/main.go index 0b2bfae..5ded814 100644 --- a/main.go +++ b/main.go @@ -34,7 +34,6 @@ import ( "os" "os/user" - "github.com/sysdb/go/client" "github.com/sysdb/webui/server" ) @@ -63,22 +62,7 @@ func main() { flag.Parse() log.Printf("Connecting to SysDB at %s.", *addr) - var conns []*client.Conn - for i := 0; i < 10; i++ { - conn, err := client.Connect(*addr, *username) - if err != nil { - fatalf("Failed to connect to SysDB at %q: %v", *addr, err) - } - conns = append(conns, conn) - } - major, minor, patch, extra, err := conns[0].ServerVersion() - if err != nil { - fatalf("Failed to query server version: %v", err) - } - log.Printf("Connected to SysDB %d.%d.%d%s.", major, minor, patch, extra) - - srv, err := server.New(server.Config{ - Conns: conns, + srv, err := server.New(*addr, *username, server.Config{ TemplatePath: *tmpl, StaticPath: *static, }) diff --git a/server/graph.go b/server/graph.go index 11254d6..ed5c7fd 100644 --- a/server/graph.go +++ b/server/graph.go @@ -39,6 +39,7 @@ import ( "github.com/gonum/plot/plotter" "github.com/gonum/plot/plotutil" "github.com/gonum/plot/vg" + "github.com/sysdb/go/client" "github.com/sysdb/go/sysdb" ) @@ -70,13 +71,18 @@ func (s *Server) graph(w http.ResponseWriter, req request) { return } - res, err := s.query("TIMESERIES %s.%s START %s END %s", req.args[0], req.args[1], start, end) + q, err := client.QueryString("TIMESERIES %s.%s START %s END %s", req.args[0], req.args[1], start, end) + if err != nil { + s.internal(w, fmt.Errorf("Failed to retrieve graph data: %v", err)) + return + } + res, err := s.c.Query(q) if err != nil { s.internal(w, fmt.Errorf("Failed to retrieve graph data: %v", err)) return } - ts, ok := res.(sysdb.Timeseries) + ts, ok := res.(*sysdb.Timeseries) if !ok { s.internal(w, errors.New("TIMESERIES did not return a time-series")) return diff --git a/server/query.go b/server/query.go index cb74f22..6d8fddf 100644 --- a/server/query.go +++ b/server/query.go @@ -30,13 +30,12 @@ package server import ( "errors" "fmt" - "log" "strings" "time" "unicode" + "github.com/sysdb/go/client" "github.com/sysdb/go/proto" - "github.com/sysdb/go/sysdb" ) func listAll(req request, s *Server) (*page, error) { @@ -44,7 +43,11 @@ func listAll(req request, s *Server) (*page, error) { return nil, fmt.Errorf("%s not found", strings.Title(req.cmd)) } - res, err := s.query("LIST %s", identifier(req.cmd)) + q, err := client.QueryString("LIST %s", client.Identifier(req.cmd)) + if err != nil { + return nil, err + } + res, err := s.c.Query(q) if err != nil { return nil, err } @@ -94,7 +97,11 @@ func lookup(req request, s *Server) (*page, error) { } } - res, err := s.query("LOOKUP %s MATCHING"+args, identifier(typ)) + q, err := client.QueryString("LOOKUP %s MATCHING"+args, client.Identifier(typ)) + if err != nil { + return nil, err + } + res, err := s.c.Query(q) if err != nil { return nil, err } @@ -109,28 +116,33 @@ func fetch(req request, s *Server) (*page, error) { return nil, fmt.Errorf("%s not found", strings.Title(req.cmd)) } - var res interface{} + var q string var err error switch req.cmd { case "host": if len(req.args) != 1 { return nil, fmt.Errorf("%s not found", strings.Title(req.cmd)) } - res, err = s.query("FETCH host %s", req.args[0]) + q, err = client.QueryString("FETCH host %s", req.args[0]) case "service", "metric": if len(req.args) != 2 { return nil, fmt.Errorf("%s not found", strings.Title(req.cmd)) } - res, err = s.query("FETCH %s %s.%s", identifier(req.cmd), req.args[0], req.args[1]) - if err == nil && req.cmd == "metric" { - return metric(req, res, s) - } + q, err = client.QueryString("FETCH %s %s.%s", client.Identifier(req.cmd), req.args[0], req.args[1]) default: panic("Unknown request: fetch(" + req.cmd + ")") } if err != nil { return nil, err } + + res, err := s.c.Query(q) + if err != nil { + return nil, err + } + if req.cmd == "metric" { + return metric(req, res, s) + } return tmpl(s.results[req.cmd], res) } @@ -267,73 +279,4 @@ func (s *scanner) inField(r rune) bool { return !unicode.IsSpace(r) } -type identifier string - -func (s *Server) query(cmd string, args ...interface{}) (interface{}, error) { - c := <-s.conns - defer func() { s.conns <- c }() - - for i, arg := range args { - switch v := arg.(type) { - case identifier: - // Nothing to do. - case string: - args[i] = proto.EscapeString(v) - case time.Time: - args[i] = v.Format(datetime) - default: - panic(fmt.Sprintf("query: invalid type %T", arg)) - } - } - - cmd = fmt.Sprintf(cmd, args...) - m := &proto.Message{ - Type: proto.ConnectionQuery, - Raw: []byte(cmd), - } - if err := c.Send(m); err != nil { - return nil, fmt.Errorf("Query %q: %v", cmd, err) - } - - for { - m, err := c.Receive() - if err != nil { - return nil, fmt.Errorf("Failed to receive server response: %v", err) - } - if m.Type == proto.ConnectionLog { - log.Println(string(m.Raw[4:])) - continue - } else if m.Type == proto.ConnectionError { - return nil, errors.New(string(m.Raw)) - } - - t, err := m.DataType() - if err != nil { - return nil, fmt.Errorf("Failed to unmarshal response: %v", err) - } - - var res interface{} - switch t { - case proto.HostList: - var hosts []sysdb.Host - err = proto.Unmarshal(m, &hosts) - res = hosts - case proto.Host: - var host sysdb.Host - err = proto.Unmarshal(m, &host) - res = host - case proto.Timeseries: - var ts sysdb.Timeseries - err = proto.Unmarshal(m, &ts) - res = ts - default: - return nil, fmt.Errorf("Unsupported data type %d", t) - } - if err != nil { - return nil, fmt.Errorf("Failed to unmarshal response: %v", err) - } - return res, nil - } -} - // vim: set tw=78 sw=4 sw=4 noexpandtab : diff --git a/server/server.go b/server/server.go index 093c683..8d0d72d 100644 --- a/server/server.go +++ b/server/server.go @@ -28,10 +28,10 @@ package server import ( "bytes" - "errors" "fmt" "html/template" "io" + "log" "net/http" "net/url" "path/filepath" @@ -42,12 +42,6 @@ import ( // A Config specifies configuration values for a SysDB web server. type Config struct { - // Conns is a slice of connections to a SysDB server instance. The number of - // elements specifies the maximum number of parallel queries to the backend. - // Note that a client connection is not thread-safe but multiple idle - // connections don't impose any load on the server. - Conns []*client.Conn - // TemplatePath specifies the relative or absolute location of template files. TemplatePath string @@ -57,7 +51,7 @@ type Config struct { // A Server implements an http.Handler that serves the SysDB user interface. type Server struct { - conns chan *client.Conn + c *client.Client // Request multiplexer mux map[string]handler @@ -71,25 +65,20 @@ type Server struct { } // New constructs a new SysDB web server using the specified configuration. -func New(cfg Config) (*Server, error) { - if len(cfg.Conns) == 0 { - return nil, errors.New("need at least one client connection") - } +func New(addr, user string, cfg Config) (*Server, error) { + s := &Server{results: make(map[string]*template.Template)} - s := &Server{ - conns: make(chan *client.Conn, len(cfg.Conns)), - results: make(map[string]*template.Template), + var err error + if s.c, err = client.Connect(addr, user); err != nil { + return nil, err } - for _, c := range cfg.Conns { - s.conns <- c + if major, minor, patch, extra, err := s.c.ServerVersion(); err == nil { + log.Printf("Connected to SysDB %d.%d.%d%s.", major, minor, patch, extra) } - var err error - s.main, err = cfg.parse("main.tmpl") - if err != nil { + if s.main, err = cfg.parse("main.tmpl"); err != nil { return nil, err } - types := []string{"host", "hosts", "service", "services", "metric", "metrics"} for _, t := range types { s.results[t], err = cfg.parse(t + ".tmpl") @@ -216,10 +205,7 @@ func (s *Server) static(w http.ResponseWriter, req request) { } func index(_ request, s *Server) (*page, error) { - c := <-s.conns - defer func() { s.conns <- c }() - - major, minor, patch, extra, err := c.ServerVersion() + major, minor, patch, extra, err := s.c.ServerVersion() if err != nil { return nil, err } -- 2.30.2