stuff
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"container/ring"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.tornberg.me/go-otel/internal/websocket"
|
||||
|
||||
"go.opentelemetry.io/collector/consumer"
|
||||
"go.opentelemetry.io/collector/pdata/plog"
|
||||
"go.opentelemetry.io/collector/pdata/pmetric"
|
||||
"go.opentelemetry.io/collector/pdata/ptrace"
|
||||
)
|
||||
|
||||
type Collector struct {
|
||||
broadcaster websocket.Broadcaster
|
||||
historySize int
|
||||
history *ring.Ring
|
||||
historyMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func New(broadcaster websocket.Broadcaster, historySize int) *Collector {
|
||||
return &Collector{
|
||||
broadcaster: broadcaster,
|
||||
historySize: historySize,
|
||||
history: ring.New(historySize),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Collector) SetBroadcaster(broadcaster websocket.Broadcaster) {
|
||||
c.broadcaster = broadcaster
|
||||
}
|
||||
|
||||
func (c *Collector) addToHistory(dataType websocket.DataType, data interface{}) {
|
||||
c.historyMutex.Lock()
|
||||
defer c.historyMutex.Unlock()
|
||||
|
||||
c.history.Value = websocket.HistoryEntry{
|
||||
Type: string(dataType),
|
||||
Timestamp: time.Now().UnixNano(),
|
||||
Data: data,
|
||||
}
|
||||
c.history = c.history.Next()
|
||||
}
|
||||
|
||||
func (c *Collector) GetHistory() []websocket.HistoryEntry {
|
||||
c.historyMutex.RLock()
|
||||
defer c.historyMutex.RUnlock()
|
||||
|
||||
var history []websocket.HistoryEntry
|
||||
c.history.Do(func(v interface{}) {
|
||||
if entry, ok := v.(websocket.HistoryEntry); ok && entry.Type != "" {
|
||||
history = append(history, entry)
|
||||
}
|
||||
})
|
||||
return history
|
||||
}
|
||||
|
||||
func (c *Collector) ConsumeTraces(ctx context.Context, td ptrace.Traces) error {
|
||||
marshaler := &ptrace.JSONMarshaler{}
|
||||
buf, err := marshaler.MarshalTraces(td)
|
||||
if err != nil {
|
||||
log.Printf("failed to marshal traces: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Parse to interface{} for history storage
|
||||
var data interface{}
|
||||
if err := json.Unmarshal(buf, &data); err != nil {
|
||||
log.Printf("failed to unmarshal traces for history: %v", err)
|
||||
} else {
|
||||
c.addToHistory(websocket.DataTypeTraces, data)
|
||||
}
|
||||
|
||||
entry := websocket.Entry{
|
||||
Type: string(websocket.DataTypeTraces),
|
||||
Data: data,
|
||||
}
|
||||
|
||||
c.broadcaster.Broadcast(&entry)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) ConsumeMetrics(ctx context.Context, md pmetric.Metrics) error {
|
||||
marshaler := &pmetric.JSONMarshaler{}
|
||||
buf, err := marshaler.MarshalMetrics(md)
|
||||
if err != nil {
|
||||
log.Printf("failed to marshal metrics: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Parse to interface{} for history storage
|
||||
var data interface{}
|
||||
if err := json.Unmarshal(buf, &data); err != nil {
|
||||
log.Printf("failed to unmarshal metrics for history: %v", err)
|
||||
} else {
|
||||
c.addToHistory(websocket.DataTypeMetrics, data)
|
||||
}
|
||||
|
||||
entry := websocket.Entry{
|
||||
Type: string(websocket.DataTypeMetrics),
|
||||
Data: data,
|
||||
}
|
||||
|
||||
c.broadcaster.Broadcast(&entry)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) ConsumeLogs(ctx context.Context, ld plog.Logs) error {
|
||||
marshaler := &plog.JSONMarshaler{}
|
||||
buf, err := marshaler.MarshalLogs(ld)
|
||||
if err != nil {
|
||||
log.Printf("failed to marshal logs: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Parse to interface{} for history storage
|
||||
var data interface{}
|
||||
if err := json.Unmarshal(buf, &data); err != nil {
|
||||
log.Printf("failed to unmarshal logs for history: %v", err)
|
||||
} else {
|
||||
c.addToHistory(websocket.DataTypeLogs, data)
|
||||
}
|
||||
|
||||
entry := websocket.Entry{
|
||||
Type: string(websocket.DataTypeLogs),
|
||||
Data: data,
|
||||
}
|
||||
|
||||
c.broadcaster.Broadcast(&entry)
|
||||
|
||||
//c.broadcaster.Broadcast(buf)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Implement consumer interfaces
|
||||
func (c *Collector) Capabilities() consumer.Capabilities {
|
||||
return consumer.Capabilities{MutatesData: false}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type DataType string
|
||||
|
||||
const (
|
||||
DataTypeTraces DataType = "traces"
|
||||
DataTypeMetrics DataType = "metrics"
|
||||
DataTypeLogs DataType = "logs"
|
||||
)
|
||||
|
||||
type HistoryProvider interface {
|
||||
GetHistory() []HistoryEntry
|
||||
}
|
||||
|
||||
type HistoryEntry struct {
|
||||
Type string `json:"type"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
type Entry struct {
|
||||
Type string `json:"type"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
type Broadcaster interface {
|
||||
Broadcast(data *Entry)
|
||||
}
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
clients map[*websocket.Conn]bool
|
||||
mutex sync.Mutex
|
||||
historyProvider HistoryProvider
|
||||
}
|
||||
|
||||
func New(historyProvider HistoryProvider) *Server {
|
||||
return &Server{
|
||||
|
||||
clients: make(map[*websocket.Conn]bool),
|
||||
historyProvider: historyProvider,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) HandleConnections(w http.ResponseWriter, r *http.Request) {
|
||||
ws, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
log.Printf("failed to upgrade connection: %v", err)
|
||||
return
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
s.mutex.Lock()
|
||||
s.clients[ws] = true
|
||||
s.mutex.Unlock()
|
||||
|
||||
log.Printf("client connected")
|
||||
|
||||
// // Send history to new client
|
||||
// if s.historyProvider != nil {
|
||||
// history := s.historyProvider.GetHistory()
|
||||
// for _, entry := range history {
|
||||
// if data, err := json.Marshal(entry); err == nil {
|
||||
// if err := ws.WriteMessage(websocket.TextMessage, data); err != nil {
|
||||
// log.Printf("failed to send history to client: %v", err)
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
for {
|
||||
// Read message from browser
|
||||
_, _, err := ws.ReadMessage()
|
||||
if err != nil {
|
||||
log.Printf("read error: %v", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
s.mutex.Lock()
|
||||
delete(s.clients, ws)
|
||||
s.mutex.Unlock()
|
||||
log.Printf("client disconnected")
|
||||
}
|
||||
|
||||
func (s *Server) Broadcast(entry *Entry) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
msg, err := json.Marshal(entry)
|
||||
if err != nil {
|
||||
log.Printf("failed to marshal log entry: %v", err)
|
||||
} else {
|
||||
for client := range s.clients {
|
||||
if err := client.WriteMessage(websocket.TextMessage, msg); err != nil {
|
||||
log.Printf("write error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) SendHistory(ws *websocket.Conn) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
history := s.historyProvider.GetHistory() // Assuming GetHistory() returns the history data
|
||||
for _, entry := range history {
|
||||
data, err := json.Marshal(entry)
|
||||
if err != nil {
|
||||
log.Printf("failed to marshal history entry: %v", err)
|
||||
continue
|
||||
}
|
||||
if err := ws.WriteMessage(websocket.TextMessage, data); err != nil {
|
||||
log.Printf("write error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) HandleMessage(ws *websocket.Conn, msg []byte) {
|
||||
var message map[string]interface{}
|
||||
if err := json.Unmarshal(msg, &message); err != nil {
|
||||
log.Printf("error unmarshaling message: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Handle the message (this is just an example, adjust according to your needs)
|
||||
switch message["type"] {
|
||||
case "ping":
|
||||
log.Printf("received ping")
|
||||
s.SendPong(ws)
|
||||
default:
|
||||
log.Printf("unknown message type : %v", message)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) SendPong(ws *websocket.Conn) {
|
||||
if err := ws.WriteMessage(websocket.PongMessage, nil); err != nil {
|
||||
log.Printf("error sending pong", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user