forked from mirror/gin
Updates realtime-advanced demo
This commit is contained in:
parent
9386d78673
commit
1f11541011
|
@ -4,17 +4,16 @@ import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/manucorporat/stats"
|
||||||
)
|
)
|
||||||
|
|
||||||
import "github.com/manucorporat/stats"
|
|
||||||
|
|
||||||
var ips = stats.New()
|
var ips = stats.New()
|
||||||
|
|
||||||
func ratelimit(c *gin.Context) {
|
func ratelimit(c *gin.Context) {
|
||||||
ip := c.ClientIP()
|
ip := c.ClientIP()
|
||||||
value := uint64(ips.Add(ip, 1))
|
value := uint64(ips.Add(ip, 1))
|
||||||
if value >= 400 {
|
if value >= 1000 {
|
||||||
if value%400 == 0 {
|
if value%1000 == 0 {
|
||||||
log.Printf("BlockedIP:%s Requests:%d\n", ip, value)
|
log.Printf("BlockedIP:%s Requests:%d\n", ip, value)
|
||||||
}
|
}
|
||||||
c.AbortWithStatus(401)
|
c.AbortWithStatus(401)
|
||||||
|
|
|
@ -1,13 +1,24 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/manucorporat/stats"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var messages = stats.New()
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
nuCPU := runtime.NumCPU()
|
||||||
|
runtime.GOMAXPROCS(nuCPU)
|
||||||
|
fmt.Printf("Running with %d CPUs\n", nuCPU)
|
||||||
|
|
||||||
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
|
||||||
router := gin.New()
|
router := gin.New()
|
||||||
router.Use(ratelimit, gin.Recovery(), gin.Logger())
|
router.Use(ratelimit, gin.Recovery(), gin.Logger())
|
||||||
|
|
||||||
|
@ -19,7 +30,7 @@ func main() {
|
||||||
//router.DELETE("/room/:roomid", roomDELETE)
|
//router.DELETE("/room/:roomid", roomDELETE)
|
||||||
router.GET("/stream/:roomid", streamRoom)
|
router.GET("/stream/:roomid", streamRoom)
|
||||||
|
|
||||||
router.Run(":8080")
|
router.Run("127.0.0.1:8080")
|
||||||
}
|
}
|
||||||
|
|
||||||
func index(c *gin.Context) {
|
func index(c *gin.Context) {
|
||||||
|
@ -29,6 +40,9 @@ func index(c *gin.Context) {
|
||||||
func roomGET(c *gin.Context) {
|
func roomGET(c *gin.Context) {
|
||||||
roomid := c.ParamValue("roomid")
|
roomid := c.ParamValue("roomid")
|
||||||
userid := c.FormValue("nick")
|
userid := c.FormValue("nick")
|
||||||
|
if len(userid) > 13 {
|
||||||
|
userid = userid[0:12] + "..."
|
||||||
|
}
|
||||||
c.HTML(200, "room_login.templ.html", gin.H{
|
c.HTML(200, "room_login.templ.html", gin.H{
|
||||||
"roomid": roomid,
|
"roomid": roomid,
|
||||||
"nick": userid,
|
"nick": userid,
|
||||||
|
@ -42,7 +56,7 @@ func roomPOST(c *gin.Context) {
|
||||||
nick := c.FormValue("nick")
|
nick := c.FormValue("nick")
|
||||||
message := c.PostFormValue("message")
|
message := c.PostFormValue("message")
|
||||||
|
|
||||||
if len(message) > 200 || len(nick) > 20 {
|
if len(message) > 200 || len(nick) > 13 {
|
||||||
c.JSON(400, gin.H{
|
c.JSON(400, gin.H{
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"error": "the message or nickname is too long",
|
"error": "the message or nickname is too long",
|
||||||
|
@ -54,6 +68,7 @@ func roomPOST(c *gin.Context) {
|
||||||
"nick": nick,
|
"nick": nick,
|
||||||
"message": message,
|
"message": message,
|
||||||
}
|
}
|
||||||
|
messages.Add("inbound", 1)
|
||||||
room(roomid).Submit(post)
|
room(roomid).Submit(post)
|
||||||
c.JSON(200, post)
|
c.JSON(200, post)
|
||||||
}
|
}
|
||||||
|
@ -73,6 +88,7 @@ func streamRoom(c *gin.Context) {
|
||||||
c.Stream(func(w io.Writer) bool {
|
c.Stream(func(w io.Writer) bool {
|
||||||
select {
|
select {
|
||||||
case msg := <-listener:
|
case msg := <-listener:
|
||||||
|
messages.Add("outbound", 1)
|
||||||
c.SSEvent("message", msg)
|
c.SSEvent("message", msg)
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
c.SSEvent("stats", Stats())
|
c.SSEvent("stats", Stats())
|
||||||
|
|
|
@ -19,13 +19,41 @@
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
|
||||||
<!-- Latest compiled and minified JavaScript -->
|
<!-- Latest compiled and minified JavaScript -->
|
||||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
||||||
|
<!-- Primjs -->
|
||||||
|
<link href="/static/prismjs.min.css" rel="stylesheet" />
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
StartRealtime({{.roomid}}, {{.timestamp}});
|
StartRealtime({{.roomid}}, {{.timestamp}});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<style>
|
||||||
|
body { padding-top: 50px; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<nav class="navbar navbar-fixed-top navbar-inverse">
|
||||||
|
<div class="container">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||||
|
<span class="sr-only">Toggle navigation</span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</button>
|
||||||
|
<a class="navbar-brand" href="#">Server-Sent Events</a>
|
||||||
|
</div>
|
||||||
|
<div id="navbar" class="collapse navbar-collapse">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li class="active"><a href="#">Demo</a></li>
|
||||||
|
<li><a href="http://www.w3.org/TR/2009/WD-eventsource-20091029/">W3 Standard</a></li>
|
||||||
|
<li><a href="http://caniuse.com/#feat=eventsource">Browser Support</a></li>
|
||||||
|
<li><a href="http://gin-gonic.github.io/gin/">Gin Framework</a></li>
|
||||||
|
<li><a href="https://github.com/gin-gonic/gin/tree/develop/examples/realtime-advanced">Github</a></li>
|
||||||
|
</ul>
|
||||||
|
</div><!-- /.nav-collapse -->
|
||||||
|
</div><!-- /.container -->
|
||||||
|
</nav><!-- /.navbar -->
|
||||||
<!-- Main jumbotron for a primary marketing message or call to action -->
|
<!-- Main jumbotron for a primary marketing message or call to action -->
|
||||||
<div class="jumbotron">
|
<div class="jumbotron">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
@ -33,10 +61,8 @@
|
||||||
<p><a href="http://www.html5rocks.com/en/tutorials/eventsource/basics/">Server-sent events (SSE)</a> is a technology where a browser receives automatic updates from a server via HTTP connection.</p>
|
<p><a href="http://www.html5rocks.com/en/tutorials/eventsource/basics/">Server-sent events (SSE)</a> is a technology where a browser receives automatic updates from a server via HTTP connection.</p>
|
||||||
<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>
|
<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="row">
|
||||||
{{if not .nick}}
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
{{end}}
|
<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:200px">
|
|
||||||
<table id="table-style" class="table">
|
<table id="table-style" class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -49,17 +75,22 @@
|
||||||
</div>
|
</div>
|
||||||
{{if .nick}}
|
{{if .nick}}
|
||||||
<form class="form-inline" id="chat-form" action="/room/{{.roomid}}?nick={{.nick}}" method="post">
|
<form class="form-inline" id="chat-form" action="/room/{{.roomid}}?nick={{.nick}}" method="post">
|
||||||
<div class="form-group col-md-6">
|
<div class="form-group">
|
||||||
<input name="message" id="chat-message" placeholder="a message" type="text" class="form-control" style="width:100%" />
|
<label class="sr-only" for="chat-message">Message</label>
|
||||||
</div>
|
<div class="input-group">
|
||||||
<div class="form-group col-md-2">
|
<div class="input-group-addon">{{.nick}}</div>
|
||||||
<input type="submit" class="btn btn-primary" value="Send" />
|
<input name="message" id="chat-message" placeholder="a message" type="text" class="form-control" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<input type="submit" class="btn btn-primary" value="Send" />
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if not .nick}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
|
{{if .nick}}
|
||||||
|
<h3>Inbound/Outbound</h3>
|
||||||
|
<div id="messagesChart" class="epoch category20c"></div>
|
||||||
|
{{else}}
|
||||||
<form action="" method="get">
|
<form action="" method="get">
|
||||||
<legend>Join the SSE real-time chat</legend>
|
<legend>Join the SSE real-time chat</legend>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -70,13 +101,14 @@
|
||||||
<input type="submit" class="btn btn-success btn-login-submit" value="Join" />
|
<input type="submit" class="btn btn-success btn-login-submit" value="Join" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<h2>Realtime server Go stats</h2>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<h3>Number of Goroutines</h3>
|
<h3>Number of Goroutines</h3>
|
||||||
<p>
|
<p>
|
||||||
|
@ -96,9 +128,41 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h2>Source code</h2>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<script src="/static/prismjs.min.js"></script>
|
||||||
|
<h3>Server-side (Go)</h3>
|
||||||
|
<pre><code class="language-go">func streamRoom(c *gin.Context) {
|
||||||
|
roomid := c.ParamValue("roomid")
|
||||||
|
listener := openListener(roomid)
|
||||||
|
statsTicker := time.NewTicker(1 * time.Second)
|
||||||
|
defer closeListener(roomid, listener)
|
||||||
|
defer statsTicker.Stop()
|
||||||
|
|
||||||
|
c.Stream(func(w io.Writer) bool {
|
||||||
|
select {
|
||||||
|
case msg := <-listener:
|
||||||
|
c.SSEvent("message", msg)
|
||||||
|
case <-statsTicker.C:
|
||||||
|
c.SSEvent("stats", Stats())
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}</code></pre>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h3>Client-side (JS)</h3>
|
||||||
|
<pre><code class="language-javascript">function StartSSE(roomid) {
|
||||||
|
var source = new EventSource('/stream/'+roomid);
|
||||||
|
source.addEventListener('message', newChatMessage, false);
|
||||||
|
source.addEventListener('stats', stats, false);
|
||||||
|
}</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<footer>
|
<footer>
|
||||||
<p>© Company 2014</p>
|
<p>Created with <span class="glyphicon glyphicon-heart"></span> by <a href="https://github.com/manucorporat">Manu Martinez-Almeida</a></p>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+go */
|
||||||
|
/**
|
||||||
|
* prism.js default theme for JavaScript, CSS and HTML
|
||||||
|
* Based on dabblet (http://dabblet.com)
|
||||||
|
* @author Lea Verou
|
||||||
|
*/
|
||||||
|
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
color: black;
|
||||||
|
text-shadow: 0 1px white;
|
||||||
|
font-family: Consolas, Monaco, 'Andale Mono', monospace;
|
||||||
|
direction: ltr;
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre;
|
||||||
|
word-spacing: normal;
|
||||||
|
word-break: normal;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||||
|
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
|
||||||
|
code[class*="language-"]::selection, code[class*="language-"] ::selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
pre[class*="language-"] {
|
||||||
|
padding: 1em;
|
||||||
|
margin: .5em 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre) > code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
background: #f5f2f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline code */
|
||||||
|
:not(pre) > code[class*="language-"] {
|
||||||
|
padding: .1em;
|
||||||
|
border-radius: .3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.comment,
|
||||||
|
.token.prolog,
|
||||||
|
.token.doctype,
|
||||||
|
.token.cdata {
|
||||||
|
color: slategray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.punctuation {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.namespace {
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.property,
|
||||||
|
.token.tag,
|
||||||
|
.token.boolean,
|
||||||
|
.token.number,
|
||||||
|
.token.constant,
|
||||||
|
.token.symbol,
|
||||||
|
.token.deleted {
|
||||||
|
color: #905;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.selector,
|
||||||
|
.token.attr-name,
|
||||||
|
.token.string,
|
||||||
|
.token.char,
|
||||||
|
.token.builtin,
|
||||||
|
.token.inserted {
|
||||||
|
color: #690;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.operator,
|
||||||
|
.token.entity,
|
||||||
|
.token.url,
|
||||||
|
.language-css .token.string,
|
||||||
|
.style .token.string {
|
||||||
|
color: #a67f59;
|
||||||
|
background: hsla(0, 0%, 100%, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.atrule,
|
||||||
|
.token.attr-value,
|
||||||
|
.token.keyword {
|
||||||
|
color: #07a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.function {
|
||||||
|
color: #DD4A68;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.regex,
|
||||||
|
.token.important,
|
||||||
|
.token.variable {
|
||||||
|
color: #e90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.important,
|
||||||
|
.token.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.token.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.entity {
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+go */
|
||||||
|
self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content),e.alias):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var a={};for(var r in e)e.hasOwnProperty(r)&&(a[r]=t.util.clone(e[r]));return a;case"Array":return e.map(function(e){return t.util.clone(e)})}return e}},languages:{extend:function(e,n){var a=t.util.clone(t.languages[e]);for(var r in n)a[r]=n[r];return a},insertBefore:function(e,n,a,r){r=r||t.languages;var i=r[e];if(2==arguments.length){a=arguments[1];for(var l in a)a.hasOwnProperty(l)&&(i[l]=a[l]);return i}var s={};for(var o in i)if(i.hasOwnProperty(o)){if(o==n)for(var l in a)a.hasOwnProperty(l)&&(s[l]=a[l]);s[o]=i[o]}return t.languages.DFS(t.languages,function(t,n){n===r[e]&&t!=e&&(this[t]=s)}),r[e]=s},DFS:function(e,n,a){for(var r in e)e.hasOwnProperty(r)&&(n.call(e,r,e[r],a||r),"Object"===t.util.type(e[r])?t.languages.DFS(e[r],n):"Array"===t.util.type(e[r])&&t.languages.DFS(e[r],n,r))}},highlightAll:function(e,n){for(var a,r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'),i=0;a=r[i++];)t.highlightElement(a,e===!0,n)},highlightElement:function(a,r,i){for(var l,s,o=a;o&&!e.test(o.className);)o=o.parentNode;if(o&&(l=(o.className.match(e)||[,""])[1],s=t.languages[l]),s){a.className=a.className.replace(e,"").replace(/\s+/g," ")+" language-"+l,o=a.parentNode,/pre/i.test(o.nodeName)&&(o.className=o.className.replace(e,"").replace(/\s+/g," ")+" language-"+l);var u=a.textContent;if(u){u=u.replace(/^(?:\r?\n|\r)/,"");var g={element:a,language:l,grammar:s,code:u};if(t.hooks.run("before-highlight",g),r&&self.Worker){var c=new Worker(t.filename);c.onmessage=function(e){g.highlightedCode=n.stringify(JSON.parse(e.data),l),t.hooks.run("before-insert",g),g.element.innerHTML=g.highlightedCode,i&&i.call(g.element),t.hooks.run("after-highlight",g)},c.postMessage(JSON.stringify({language:g.language,code:g.code}))}else g.highlightedCode=t.highlight(g.code,g.grammar,g.language),t.hooks.run("before-insert",g),g.element.innerHTML=g.highlightedCode,i&&i.call(a),t.hooks.run("after-highlight",g)}}},highlight:function(e,a,r){var i=t.tokenize(e,a);return n.stringify(t.util.encode(i),r)},tokenize:function(e,n){var a=t.Token,r=[e],i=n.rest;if(i){for(var l in i)n[l]=i[l];delete n.rest}e:for(var l in n)if(n.hasOwnProperty(l)&&n[l]){var s=n[l];s="Array"===t.util.type(s)?s:[s];for(var o=0;o<s.length;++o){var u=s[o],g=u.inside,c=!!u.lookbehind,f=0,h=u.alias;u=u.pattern||u;for(var p=0;p<r.length;p++){var d=r[p];if(r.length>e.length)break e;if(!(d instanceof a)){u.lastIndex=0;var m=u.exec(d);if(m){c&&(f=m[1].length);var y=m.index-1+f,m=m[0].slice(f),v=m.length,k=y+v,b=d.slice(0,y+1),w=d.slice(k+1),N=[p,1];b&&N.push(b);var O=new a(l,g?t.tokenize(m,g):m,h);N.push(O),w&&N.push(w),Array.prototype.splice.apply(r,N)}}}}}return r},hooks:{all:{},add:function(e,n){var a=t.hooks.all;a[e]=a[e]||[],a[e].push(n)},run:function(e,n){var a=t.hooks.all[e];if(a&&a.length)for(var r,i=0;r=a[i++];)r(n)}}},n=t.Token=function(e,t,n){this.type=e,this.content=t,this.alias=n};if(n.stringify=function(e,a,r){if("string"==typeof e)return e;if("Array"===t.util.type(e))return e.map(function(t){return n.stringify(t,a,e)}).join("");var i={type:e.type,content:n.stringify(e.content,a,r),tag:"span",classes:["token",e.type],attributes:{},language:a,parent:r};if("comment"==i.type&&(i.attributes.spellcheck="true"),e.alias){var l="Array"===t.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,l)}t.hooks.run("wrap",i);var s="";for(var o in i.attributes)s+=o+'="'+(i.attributes[o]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+s+">"+i.content+"</"+i.tag+">"},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),a=n.language,r=n.code;self.postMessage(JSON.stringify(t.util.encode(t.tokenize(r,t.languages[a])))),self.close()},!1),self.Prism):self.Prism;var a=document.getElementsByTagName("script");return a=a[a.length-1],a&&(t.filename=a.src,document.addEventListener&&!a.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);;
|
||||||
|
Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:/("|')(\\\n|\\?.)*?\1/,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":{pattern:/[a-z0-9_]+\(/i,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|~|\^|%/,ignore:/&(lt|gt|amp);/i,punctuation:/[{}[\];(),.:]/};;
|
||||||
|
Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|get|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|-?Infinity)\b/,"function":/(?!\d)[a-z0-9_$]+(?=\()/i}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/<script[\w\W]*?>[\w\W]*?<\/script>/i,inside:{tag:{pattern:/<script[\w\W]*?>|<\/script>/i,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript},alias:"language-javascript"}});;
|
||||||
|
Prism.languages.go=Prism.languages.extend("clike",{keyword:/\b(break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,builtin:/\b(bool|byte|complex(64|128)|error|float(32|64)|rune|string|u?int(8|16|32|64|)|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(ln)?|real|recover)\b/,"boolean":/\b(_|iota|nil|true|false)\b/,operator:/([(){}\[\]]|[*\/%^!]=?|\+[=+]?|-[>=-]?|\|[=|]?|>[=>]?|<(<|[=-])?|==?|&(&|=|^=?)?|\.(\.\.)?|[,;]|:=?)/,number:/\b(-?(0x[a-f\d]+|(\d+\.?\d*|\.\d+)(e[-+]?\d+)?)i?)\b/i,string:/("|'|`)(\\?.|\r|\n)*?\1/}),delete Prism.languages.go["class-name"];;
|
|
@ -46,6 +46,18 @@ function StartEpoch(timestamp) {
|
||||||
{values: defaultData}
|
{values: defaultData}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if($('#messagesChart').length ) {
|
||||||
|
window.messagesChart = $('#messagesChart').epoch({
|
||||||
|
type: 'time.area',
|
||||||
|
axes: ['bottom', 'left'],
|
||||||
|
height: 250,
|
||||||
|
data: [
|
||||||
|
{values: defaultData},
|
||||||
|
{values: defaultData}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function StartSSE(roomid) {
|
function StartSSE(roomid) {
|
||||||
|
@ -63,6 +75,9 @@ function stats(e) {
|
||||||
heapChart.push(data.heap)
|
heapChart.push(data.heap)
|
||||||
mallocsChart.push(data.mallocs)
|
mallocsChart.push(data.mallocs)
|
||||||
goroutinesChart.push(data.goroutines)
|
goroutinesChart.push(data.goroutines)
|
||||||
|
if(messagesChart) {
|
||||||
|
messagesChart.push(data.messages)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseJSONStats(e) {
|
function parseJSONStats(e) {
|
||||||
|
@ -78,13 +93,18 @@ function parseJSONStats(e) {
|
||||||
{time: timestamp, y: data.Mallocs},
|
{time: timestamp, y: data.Mallocs},
|
||||||
{time: timestamp, y: data.Frees}
|
{time: timestamp, y: data.Frees}
|
||||||
];
|
];
|
||||||
|
var messages = [
|
||||||
|
{time: timestamp, y: data.Inbound},
|
||||||
|
{time: timestamp, y: data.Outbound}
|
||||||
|
];
|
||||||
var goroutines = [
|
var goroutines = [
|
||||||
{time: timestamp, y: data.NuGoroutines},
|
{time: timestamp, y: data.NuGoroutines},
|
||||||
]
|
]
|
||||||
return {
|
return {
|
||||||
heap: heap,
|
heap: heap,
|
||||||
mallocs: mallocs,
|
mallocs: mallocs,
|
||||||
goroutines: goroutines
|
goroutines: goroutines,
|
||||||
|
messages: messages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,9 @@ func Stats() map[string]uint64 {
|
||||||
"HeapInuse": stats.HeapInuse,
|
"HeapInuse": stats.HeapInuse,
|
||||||
"StackInuse": stats.StackInuse,
|
"StackInuse": stats.StackInuse,
|
||||||
"NuGoroutines": uint64(runtime.NumGoroutine()),
|
"NuGoroutines": uint64(runtime.NumGoroutine()),
|
||||||
//"Latency": latency,
|
"Mallocs": stats.Mallocs,
|
||||||
"Mallocs": stats.Mallocs,
|
"Frees": stats.Mallocs,
|
||||||
"Frees": stats.Mallocs,
|
"Inbound": uint64(messages.Get("inbound")),
|
||||||
// "HeapIdle": stats.HeapIdle,
|
"Outbound": uint64(messages.Get("outbound")),
|
||||||
// "HeapInuse": stats.HeapInuse,
|
|
||||||
// "HeapReleased": stats.HeapReleased,
|
|
||||||
// "HeapObjects": stats.HeapObjects,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue