mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(websocket): more work websocket ds, # 4355
This commit is contained in:
@@ -245,7 +245,7 @@ func Register(r *macaron.Macaron) {
|
|||||||
r.Any("/ws", liveConn.Serve)
|
r.Any("/ws", liveConn.Serve)
|
||||||
|
|
||||||
// streams
|
// streams
|
||||||
r.Post("/streams/push", reqSignedIn, bind(dtos.StreamMessage{}), liveConn.PushToStream)
|
r.Post("/api/streams/push", reqSignedIn, bind(dtos.StreamMessage{}), liveConn.PushToStream)
|
||||||
|
|
||||||
InitAppPluginRoutes(r)
|
InitAppPluginRoutes(r)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ import "encoding/json"
|
|||||||
|
|
||||||
type StreamMessage struct {
|
type StreamMessage struct {
|
||||||
Stream string `json:"stream"`
|
Stream string `json:"stream"`
|
||||||
Metric string `json:"name"`
|
Metric string `json:"metric"`
|
||||||
Datapoints [][]json.Number `json:"username"`
|
Datapoints [][]json.Number `json:"Datapoints"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,21 +31,15 @@ var upgrader = websocket.Upgrader{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
type subscription struct {
|
|
||||||
name string
|
|
||||||
}
|
|
||||||
|
|
||||||
type connection struct {
|
type connection struct {
|
||||||
ws *websocket.Conn
|
ws *websocket.Conn
|
||||||
streams []*subscription
|
send chan []byte
|
||||||
send chan []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newConnection(ws *websocket.Conn) *connection {
|
func newConnection(ws *websocket.Conn) *connection {
|
||||||
return &connection{
|
return &connection{
|
||||||
send: make(chan []byte, 256),
|
send: make(chan []byte, 256),
|
||||||
streams: make([]*subscription, 0),
|
ws: ws,
|
||||||
ws: ws,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,10 +73,14 @@ func (c *connection) handleMessage(message []byte) {
|
|||||||
msgType := json.Get("action").MustString()
|
msgType := json.Get("action").MustString()
|
||||||
streamName := json.Get("stream").MustString()
|
streamName := json.Get("stream").MustString()
|
||||||
|
|
||||||
|
if len(streamName) == 0 {
|
||||||
|
log.Error(3, "Not allowed to subscribe to empty stream name")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
switch msgType {
|
switch msgType {
|
||||||
case "subscribe":
|
case "subscribe":
|
||||||
c.streams = append(c.streams, &subscription{name: streamName})
|
h.subChannel <- &streamSubscription{name: streamName, conn: c}
|
||||||
log.Info("Live: subscribing to stream %v", streamName)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,30 +2,36 @@ package live
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/grafana/grafana/pkg/api/dtos"
|
"github.com/grafana/grafana/pkg/api/dtos"
|
||||||
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
"github.com/grafana/grafana/pkg/log"
|
"github.com/grafana/grafana/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type hub struct {
|
type hub struct {
|
||||||
// Registered connections.
|
|
||||||
connections map[*connection]bool
|
connections map[*connection]bool
|
||||||
|
streams map[string]map[*connection]bool
|
||||||
|
|
||||||
// Inbound messages from the connections.
|
register chan *connection
|
||||||
broadcast chan []byte
|
unregister chan *connection
|
||||||
|
streamChannel chan *dtos.StreamMessage
|
||||||
|
subChannel chan *streamSubscription
|
||||||
|
}
|
||||||
|
|
||||||
// Register requests from the connections.
|
type streamSubscription struct {
|
||||||
register chan *connection
|
conn *connection
|
||||||
|
name string
|
||||||
// Unregister requests from connections.
|
|
||||||
unregister chan *connection
|
|
||||||
|
|
||||||
streamPipe chan *dtos.StreamMessage
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var h = hub{
|
var h = hub{
|
||||||
broadcast: make(chan []byte),
|
connections: make(map[*connection]bool),
|
||||||
register: make(chan *connection),
|
streams: make(map[string]map[*connection]bool),
|
||||||
unregister: make(chan *connection),
|
register: make(chan *connection),
|
||||||
connections: make(map[*connection]bool),
|
unregister: make(chan *connection),
|
||||||
|
streamChannel: make(chan *dtos.StreamMessage),
|
||||||
|
subChannel: make(chan *streamSubscription),
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *hub) removeConnection() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *hub) run() {
|
func (h *hub) run() {
|
||||||
@@ -39,20 +45,34 @@ func (h *hub) run() {
|
|||||||
delete(h.connections, c)
|
delete(h.connections, c)
|
||||||
close(c.send)
|
close(c.send)
|
||||||
}
|
}
|
||||||
case m := <-h.broadcast:
|
// hand stream subscriptions
|
||||||
log.Info("Live: broadcasting")
|
case sub := <-h.subChannel:
|
||||||
for c := range h.connections {
|
log.Info("Live: Connection subscribing to: %v", sub.name)
|
||||||
|
subscribers, exists := h.streams[sub.name]
|
||||||
|
if !exists {
|
||||||
|
subscribers = make(map[*connection]bool)
|
||||||
|
h.streams[sub.name] = subscribers
|
||||||
|
}
|
||||||
|
subscribers[sub.conn] = true
|
||||||
|
|
||||||
|
// handle stream messages
|
||||||
|
case message := <-h.streamChannel:
|
||||||
|
subscribers, exists := h.streams[message.Stream]
|
||||||
|
if !exists {
|
||||||
|
log.Info("Live: Message to stream without subscribers: %v", message.Stream)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
messageBytes, _ := simplejson.NewFromAny(message).Encode()
|
||||||
|
for sub := range subscribers {
|
||||||
select {
|
select {
|
||||||
case c.send <- m:
|
case sub.send <- messageBytes:
|
||||||
default:
|
default:
|
||||||
close(c.send)
|
close(sub.send)
|
||||||
delete(h.connections, c)
|
delete(h.connections, sub)
|
||||||
|
delete(subscribers, sub)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendMessage(message string) {
|
|
||||||
h.broadcast <- []byte(message)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -31,5 +31,6 @@ func (lc *LiveConn) Serve(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LiveConn) PushToStream(c *middleware.Context, message dtos.StreamMessage) {
|
func (lc *LiveConn) PushToStream(c *middleware.Context, message dtos.StreamMessage) {
|
||||||
|
h.streamChannel <- &message
|
||||||
|
c.JsonOK("Message recevived")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user