Better stats in realtime-advanced
This commit is contained in:
		@ -5,11 +5,8 @@ import (
 | 
			
		||||
	"runtime"
 | 
			
		||||
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
	"github.com/manucorporat/stats"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var messages = stats.New()
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	ConfigRuntime()
 | 
			
		||||
	StartWorkers()
 | 
			
		||||
 | 
			
		||||
@ -62,7 +62,7 @@
 | 
			
		||||
                <p>The chat and the charts data is provided in realtime using the SSE implemention of <a href="https://github.com/gin-gonic/gin/blob/15b0c49da556d58a3d934b86e3aa552ff224026d/examples/realtime-chat/main.go#L23-L32">Gin Framework</a>.</p>
 | 
			
		||||
                <div class="row">
 | 
			
		||||
                    <div class="col-md-8">
 | 
			
		||||
                        <div id="chat-scroll" style="overflow-y:scroll; overflow-x:scroll; height:270px">
 | 
			
		||||
                        <div id="chat-scroll" style="overflow-y:scroll; overflow-x:scroll; height:290px">
 | 
			
		||||
                            <table id="table-style" class="table" data-show-header="false">
 | 
			
		||||
                                <thead>
 | 
			
		||||
                                    <tr>
 | 
			
		||||
@ -97,8 +97,12 @@
 | 
			
		||||
                        {{end}}
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="col-md-4">
 | 
			
		||||
                        <h3>Inbound/Outbound</h3>
 | 
			
		||||
                        <div id="messagesChart" class="epoch category20c"></div>
 | 
			
		||||
                        <div id="messagesChart" class="epoch category10"></div>
 | 
			
		||||
                        <p>
 | 
			
		||||
                        <span style="font-size:20px; color:#1f77b4">◼︎</span> Users<br>
 | 
			
		||||
                        <span style="font-size:20px; color:#ff7f0e">◼︎</span> Inbound messages / sec<br>
 | 
			
		||||
                        <span style="font-size:20px; color:#2ca02c">◼︎</span> Outbound messages / sec<br>
 | 
			
		||||
                        </p>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
@ -106,22 +110,24 @@
 | 
			
		||||
        <div class="container">
 | 
			
		||||
            <div class="row">
 | 
			
		||||
                <h2>Realtime server Go stats</h2>
 | 
			
		||||
                <div class="col-md-4">
 | 
			
		||||
                    <h3>Number of Goroutines</h3>
 | 
			
		||||
                <div class="col-md-6">
 | 
			
		||||
                    <h3>Memory usage</h3>
 | 
			
		||||
                    <p>
 | 
			
		||||
                    <div id="goroutinesChart" class="epoch category20c"></div>
 | 
			
		||||
                    <div id="heapChart" class="epoch category20c"></div>
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <p>
 | 
			
		||||
                    <span style="font-size:20px; color:#1f77b4">◼︎</span> Heap bytes<br>
 | 
			
		||||
                    <span style="font-size:20px; color:#aec7e8">◼︎</span> Stack bytes<br>
 | 
			
		||||
                    </p>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="col-md-4">
 | 
			
		||||
                    <h3>HEAP/Stack bytes</h3>
 | 
			
		||||
                <div class="col-md-6">
 | 
			
		||||
                    <h3>Allocations per second</h3>
 | 
			
		||||
                    <p>
 | 
			
		||||
                    <div id="heapChart" class="epoch category20b"></div>
 | 
			
		||||
                    <div id="mallocsChart" class="epoch category20b"></div>
 | 
			
		||||
                    </p>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="col-md-4">
 | 
			
		||||
                    <h3>Mallocs/Frees</h3>
 | 
			
		||||
                    <p>
 | 
			
		||||
                    <div id="mallocsChart" class="epoch category10"></div>
 | 
			
		||||
                    <span style="font-size:20px; color:#393b79">◼︎</span> Mallocs / sec<br>
 | 
			
		||||
                    <span style="font-size:20px; color:#5254a3">◼︎</span> Frees / sec<br>
 | 
			
		||||
                    </p>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
@ -18,19 +18,12 @@ function StartEpoch(timestamp) {
 | 
			
		||||
    var windowSize = 60;
 | 
			
		||||
    var height = 200;
 | 
			
		||||
    var defaultData = histogram(windowSize, timestamp);
 | 
			
		||||
    window.goroutinesChart = $('#goroutinesChart').epoch({
 | 
			
		||||
        type: 'time.bar',
 | 
			
		||||
        axes: ['bottom', 'left'],
 | 
			
		||||
        height: height,
 | 
			
		||||
        data: [
 | 
			
		||||
            {values: defaultData}
 | 
			
		||||
        ]
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    window.heapChart = $('#heapChart').epoch({
 | 
			
		||||
        type: 'time.area',
 | 
			
		||||
        axes: ['bottom', 'left'],
 | 
			
		||||
        height: height,
 | 
			
		||||
        historySize: 10,
 | 
			
		||||
        data: [
 | 
			
		||||
            {values: defaultData},
 | 
			
		||||
            {values: defaultData}
 | 
			
		||||
@ -41,6 +34,7 @@ function StartEpoch(timestamp) {
 | 
			
		||||
        type: 'time.area',
 | 
			
		||||
        axes: ['bottom', 'left'],
 | 
			
		||||
        height: height,
 | 
			
		||||
        historySize: 10,
 | 
			
		||||
        data: [
 | 
			
		||||
            {values: defaultData},
 | 
			
		||||
            {values: defaultData}
 | 
			
		||||
@ -48,10 +42,12 @@ function StartEpoch(timestamp) {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    window.messagesChart = $('#messagesChart').epoch({
 | 
			
		||||
        type: 'time.area',
 | 
			
		||||
        type: 'time.line',
 | 
			
		||||
        axes: ['bottom', 'left'],
 | 
			
		||||
        height: 250,
 | 
			
		||||
        height: 240,
 | 
			
		||||
        historySize: 10,
 | 
			
		||||
        data: [
 | 
			
		||||
            {values: defaultData},
 | 
			
		||||
            {values: defaultData},
 | 
			
		||||
            {values: defaultData}
 | 
			
		||||
        ]
 | 
			
		||||
@ -69,11 +65,10 @@ function StartSSE(roomid) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function stats(e) {
 | 
			
		||||
    var data = parseJSONStats(e.data)
 | 
			
		||||
    heapChart.push(data.heap)
 | 
			
		||||
    mallocsChart.push(data.mallocs)
 | 
			
		||||
    goroutinesChart.push(data.goroutines)
 | 
			
		||||
    messagesChart.push(data.messages)
 | 
			
		||||
    var data = parseJSONStats(e.data);
 | 
			
		||||
    heapChart.push(data.heap);
 | 
			
		||||
    mallocsChart.push(data.mallocs);
 | 
			
		||||
    messagesChart.push(data.messages);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function parseJSONStats(e) {
 | 
			
		||||
@ -90,16 +85,14 @@ function parseJSONStats(e) {
 | 
			
		||||
        {time: timestamp, y: data.Frees}
 | 
			
		||||
    ];
 | 
			
		||||
    var messages = [
 | 
			
		||||
        {time: timestamp, y: data.Connected},
 | 
			
		||||
        {time: timestamp, y: data.Inbound},
 | 
			
		||||
        {time: timestamp, y: data.Outbound}
 | 
			
		||||
    ];
 | 
			
		||||
    var goroutines = [
 | 
			
		||||
        {time: timestamp, y: data.NuGoroutines},
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        heap: heap,
 | 
			
		||||
        mallocs: mallocs,
 | 
			
		||||
        goroutines: goroutines,
 | 
			
		||||
        messages: messages
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -59,8 +59,12 @@ func streamRoom(c *gin.Context) {
 | 
			
		||||
	roomid := c.ParamValue("roomid")
 | 
			
		||||
	listener := openListener(roomid)
 | 
			
		||||
	ticker := time.NewTicker(1 * time.Second)
 | 
			
		||||
	defer closeListener(roomid, listener)
 | 
			
		||||
	defer ticker.Stop()
 | 
			
		||||
	users.Add("connected", 1)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		closeListener(roomid, listener)
 | 
			
		||||
		ticker.Stop()
 | 
			
		||||
		users.Add("disconnected", 1)
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	c.Stream(func(w io.Writer) bool {
 | 
			
		||||
		select {
 | 
			
		||||
 | 
			
		||||
@ -4,33 +4,49 @@ import (
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/manucorporat/stats"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var messages = stats.New()
 | 
			
		||||
var users = stats.New()
 | 
			
		||||
var mutexStats sync.RWMutex
 | 
			
		||||
var savedStats map[string]uint64
 | 
			
		||||
 | 
			
		||||
func statsWorker() {
 | 
			
		||||
	c := time.Tick(1 * time.Second)
 | 
			
		||||
	var lastMallocs uint64 = 0
 | 
			
		||||
	var lastFrees uint64 = 0
 | 
			
		||||
	for range c {
 | 
			
		||||
		var stats runtime.MemStats
 | 
			
		||||
		runtime.ReadMemStats(&stats)
 | 
			
		||||
 | 
			
		||||
		mutexStats.Lock()
 | 
			
		||||
		savedStats = map[string]uint64{
 | 
			
		||||
			"timestamp":    uint64(time.Now().Unix()),
 | 
			
		||||
			"HeapInuse":    stats.HeapInuse,
 | 
			
		||||
			"StackInuse":   stats.StackInuse,
 | 
			
		||||
			"NuGoroutines": uint64(runtime.NumGoroutine()),
 | 
			
		||||
			"Mallocs":      stats.Mallocs,
 | 
			
		||||
			"Frees":        stats.Mallocs,
 | 
			
		||||
			"Inbound":      uint64(messages.Get("inbound")),
 | 
			
		||||
			"Outbound":     uint64(messages.Get("outbound")),
 | 
			
		||||
			"timestamp":  uint64(time.Now().Unix()),
 | 
			
		||||
			"HeapInuse":  stats.HeapInuse,
 | 
			
		||||
			"StackInuse": stats.StackInuse,
 | 
			
		||||
			"Mallocs":    (stats.Mallocs - lastMallocs),
 | 
			
		||||
			"Frees":      (stats.Frees - lastFrees),
 | 
			
		||||
			"Inbound":    uint64(messages.Get("inbound")),
 | 
			
		||||
			"Outbound":   uint64(messages.Get("outbound")),
 | 
			
		||||
			"Connected":  connectedUsers(),
 | 
			
		||||
		}
 | 
			
		||||
		lastMallocs = stats.Mallocs
 | 
			
		||||
		lastFrees = stats.Frees
 | 
			
		||||
		messages.Reset()
 | 
			
		||||
		mutexStats.Unlock()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func connectedUsers() uint64 {
 | 
			
		||||
	connected := users.Get("connected") - users.Get("disconnected")
 | 
			
		||||
	if connected < 0 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	return uint64(connected)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Stats() map[string]uint64 {
 | 
			
		||||
	mutexStats.RLock()
 | 
			
		||||
	defer mutexStats.RUnlock()
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user