diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2017-06-09 01:03:54 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2017-06-09 01:03:54 +0900 |
| commit | 4e5545af384f610a56b3d19ea73c3b801b0be6c6 (patch) | |
| tree | 4cd0b12e891bd1d8991ac4ad14cbbb7af83a0aee /src | |
| parent | v2038 (diff) | |
| download | sharkey-4e5545af384f610a56b3d19ea73c3b801b0be6c6.tar.gz sharkey-4e5545af384f610a56b3d19ea73c3b801b0be6c6.tar.bz2 sharkey-4e5545af384f610a56b3d19ea73c3b801b0be6c6.zip | |
nanka iroiro
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/stream/server.ts | 20 | ||||
| -rw-r--r-- | src/api/streaming.ts | 6 | ||||
| -rw-r--r-- | src/index.ts | 6 | ||||
| -rw-r--r-- | src/utils/stats.ts | 25 | ||||
| -rw-r--r-- | src/web/app/common/scripts/home-stream.js | 18 | ||||
| -rw-r--r-- | src/web/app/common/scripts/messaging-stream.js | 52 | ||||
| -rw-r--r-- | src/web/app/common/scripts/server-stream.js | 14 | ||||
| -rw-r--r-- | src/web/app/common/scripts/stream.js | 15 | ||||
| -rw-r--r-- | src/web/app/common/tags/messaging/room.tag | 16 | ||||
| -rw-r--r-- | src/web/app/desktop/tags/home-widgets/activity.tag | 15 | ||||
| -rw-r--r-- | src/web/app/desktop/tags/home-widgets/server.tag | 177 | ||||
| -rw-r--r-- | src/web/app/desktop/tags/home.tag | 1 | ||||
| -rw-r--r-- | src/web/app/desktop/tags/index.js | 1 | ||||
| -rw-r--r-- | src/web/app/init.js | 4 |
14 files changed, 313 insertions, 57 deletions
diff --git a/src/api/stream/server.ts b/src/api/stream/server.ts new file mode 100644 index 0000000000..6de5337499 --- /dev/null +++ b/src/api/stream/server.ts @@ -0,0 +1,20 @@ +import * as websocket from 'websocket'; +import Xev from 'xev'; + +const ev = new Xev(); + +export default function homeStream(request: websocket.request, connection: websocket.connection): void { + const onStats = stats => { + connection.send(JSON.stringify({ + type: 'stats', + body: stats + })); + }; + + ev.addListener('stats', onStats); + + connection.on('close', () => { + console.log('yooo'); + ev.removeListener('stats', onStats); + }); +} diff --git a/src/api/streaming.ts b/src/api/streaming.ts index e1d79481d3..c71132100c 100644 --- a/src/api/streaming.ts +++ b/src/api/streaming.ts @@ -8,6 +8,7 @@ import isNativeToken from './common/is-native-token'; import homeStream from './stream/home'; import messagingStream from './stream/messaging'; +import serverStream from './stream/server'; module.exports = (server: http.Server) => { /** @@ -20,6 +21,11 @@ module.exports = (server: http.Server) => { ws.on('request', async (request) => { const connection = request.accept(); + if (request.resourceURL.pathname === '/server') { + serverStream(request, connection); + return; + } + const user = await authenticate(connection, request.resourceURL.query.i); if (user == null) { diff --git a/src/index.ts b/src/index.ts index 0b568b5d44..da83dde108 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,17 +12,20 @@ import * as chalk from 'chalk'; // import portUsed = require('tcp-port-used'); import isRoot = require('is-root'); import { master } from 'accesses'; +import Xev from 'xev'; import Logger from './utils/logger'; import ProgressBar from './utils/cli/progressbar'; import EnvironmentInfo from './utils/environmentInfo'; import MachineInfo from './utils/machineInfo'; import DependencyInfo from './utils/dependencyInfo'; +import stats from './utils/stats'; import { Config, path as configPath } from './config'; import loadConfig from './config'; const clusterLog = debug('misskey:cluster'); +const ev = new Xev(); process.title = 'Misskey'; @@ -35,6 +38,9 @@ main(); function main() { if (cluster.isMaster) { masterMain(); + + ev.mount(); + stats(); } else { workerMain(); } diff --git a/src/utils/stats.ts b/src/utils/stats.ts new file mode 100644 index 0000000000..1615268310 --- /dev/null +++ b/src/utils/stats.ts @@ -0,0 +1,25 @@ +import * as os from 'os'; +const osUtils = require('os-utils'); +import * as diskusage from 'diskusage'; +import Xev from 'xev'; + +const ev = new Xev(); + +/** + * Report stats regularly + */ +export default function() { + setInterval(() => { + osUtils.cpuUsage(cpuUsage => { + const disk = diskusage.checkSync(os.platform() == 'win32' ? 'c:' : '/'); + ev.emit('stats', { + cpu_usage: cpuUsage, + mem: { + total: os.totalmem(), + free: os.freemem() + }, + disk + }); + }); + }, 1000); +} diff --git a/src/web/app/common/scripts/home-stream.js b/src/web/app/common/scripts/home-stream.js new file mode 100644 index 0000000000..24f13cd291 --- /dev/null +++ b/src/web/app/common/scripts/home-stream.js @@ -0,0 +1,18 @@ +'use strict'; + +import Stream from './stream'; + +/** + * Home stream connection + */ +class Connection extends Stream { + constructor(me) { + super('', { + i: me.token + }); + + this.on('i_updated', me.update); + } +} + +export default Connection; diff --git a/src/web/app/common/scripts/messaging-stream.js b/src/web/app/common/scripts/messaging-stream.js index 50d41c2be9..261525d5f6 100644 --- a/src/web/app/common/scripts/messaging-stream.js +++ b/src/web/app/common/scripts/messaging-stream.js @@ -1,42 +1,22 @@ -const ReconnectingWebSocket = require('reconnecting-websocket'); -import * as riot from 'riot'; -import CONFIG from './config'; +'use strict'; -class Connection { - constructor(me, otherparty) { - // BIND ----------------------------------- - this.onOpen = this.onOpen.bind(this); - this.onMessage = this.onMessage.bind(this); - this.close = this.close.bind(this); - // ---------------------------------------- - - this.event = riot.observable(); - this.me = me; - - const host = CONFIG.apiUrl.replace('http', 'ws'); - this.socket = new ReconnectingWebSocket(`${host}/messaging?i=${me.token}&otherparty=${otherparty}`); - this.socket.addEventListener('open', this.onOpen); - this.socket.addEventListener('message', this.onMessage); - } +import Stream from './stream'; - onOpen() { - this.socket.send(JSON.stringify({ - i: this.me.token - })); - } - - onMessage(message) { - try { - const msg = JSON.parse(message.data); - if (msg.type) this.event.trigger(msg.type, msg.body); - } catch(e) { - // noop - } - } +/** + * Messaging stream connection + */ +class Connection extends Stream { + constructor(me, otherparty) { + super('messaging', { + i: me.token, + otherparty + }); - close() { - this.socket.removeEventListener('open', this.onOpen); - this.socket.removeEventListener('message', this.onMessage); + this.on('_connected_', () => { + this.send({ + i: me.token + }); + }); } } diff --git a/src/web/app/common/scripts/server-stream.js b/src/web/app/common/scripts/server-stream.js new file mode 100644 index 0000000000..a1c466b35d --- /dev/null +++ b/src/web/app/common/scripts/server-stream.js @@ -0,0 +1,14 @@ +'use strict'; + +import Stream from './stream'; + +/** + * Server stream connection + */ +class Connection extends Stream { + constructor() { + super('server'); + } +} + +export default Connection; diff --git a/src/web/app/common/scripts/stream.js b/src/web/app/common/scripts/stream.js index ac3dd67153..981118b5de 100644 --- a/src/web/app/common/scripts/stream.js +++ b/src/web/app/common/scripts/stream.js @@ -5,10 +5,10 @@ import * as riot from 'riot'; import CONFIG from './config'; /** - * Home stream connection + * Misskey stream connection */ class Connection { - constructor(me) { + constructor(endpoint, params) { // BIND ----------------------------------- this.onOpen = this.onOpen.bind(this); this.onClose = this.onClose.bind(this); @@ -20,16 +20,19 @@ class Connection { riot.observable(this); this.state = 'initializing'; - this.me = me; this.buffer = []; const host = CONFIG.apiUrl.replace('http', 'ws'); - this.socket = new ReconnectingWebSocket(`${host}?i=${me.token}`); + const query = params + ? Object.keys(params) + .map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k])) + .join('&') + : null; + + this.socket = new ReconnectingWebSocket(`${host}/${endpoint}${query ? '?' + query : ''}`); this.socket.addEventListener('open', this.onOpen); this.socket.addEventListener('close', this.onClose); this.socket.addEventListener('message', this.onMessage); - - this.on('i_updated', me.update); } /** diff --git a/src/web/app/common/tags/messaging/room.tag b/src/web/app/common/tags/messaging/room.tag index bd49a4d782..93f07f2cee 100644 --- a/src/web/app/common/tags/messaging/room.tag +++ b/src/web/app/common/tags/messaging/room.tag @@ -137,8 +137,8 @@ this.connection = new MessagingStreamConnection(this.I, this.user.id); this.on('mount', () => { - this.connection.event.on('message', this.onMessage); - this.connection.event.on('read', this.onRead); + this.connection.on('message', this.onMessage); + this.connection.on('read', this.onRead); document.addEventListener('visibilitychange', this.onVisibilitychange); @@ -153,8 +153,8 @@ }); this.on('unmount', () => { - this.connection.event.off('message', this.onMessage); - this.connection.event.off('read', this.onRead); + this.connection.off('message', this.onMessage); + this.connection.off('read', this.onRead); this.connection.close(); document.removeEventListener('visibilitychange', this.onVisibilitychange); @@ -174,10 +174,10 @@ this.messages.push(message); if (message.user_id != this.I.id && !document.hidden) { - this.connection.socket.send(JSON.stringify({ + this.connection.send({ type: 'read', id: message.id - })); + }); } this.update(); @@ -239,10 +239,10 @@ if (document.hidden) return; this.messages.forEach(message => { if (message.user_id !== this.I.id && !message.is_read) { - this.connection.socket.send(JSON.stringify({ + this.connection.send({ type: 'read', id: message.id - })); + }); } }); }; diff --git a/src/web/app/desktop/tags/home-widgets/activity.tag b/src/web/app/desktop/tags/home-widgets/activity.tag index 621702fa17..3a8afdfa33 100644 --- a/src/web/app/desktop/tags/home-widgets/activity.tag +++ b/src/web/app/desktop/tags/home-widgets/activity.tag @@ -100,6 +100,8 @@ </svg> <style> :scope + display block + > svg display block padding 10px @@ -131,7 +133,7 @@ </mk-activity-home-widget-calender> <mk-activity-home-widget-chart> - <svg riot-viewBox="0 0 { viewBoxX } 60" preserveAspectRatio="none" onmousedown={ onMousedown }> + <svg riot-viewBox="0 0 { viewBoxX } { viewBoxY }" preserveAspectRatio="none" onmousedown={ onMousedown }> <polyline riot-points={ pointsPost } fill="none" @@ -155,6 +157,8 @@ </svg> <style> :scope + display block + > svg display block padding 10px @@ -163,6 +167,7 @@ </style> <script> this.viewBoxX = 140; + this.viewBoxY = 60; this.zoom = 1; this.pos = 0; @@ -176,10 +181,10 @@ this.render = () => { this.update({ - pointsPost: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.posts / peak)) * 60}`).join(' '), - pointsReply: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.replies / peak)) * 60}`).join(' '), - pointsRepost: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.reposts / peak)) * 60}`).join(' '), - pointsTotal: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.total / peak)) * 60}`).join(' ') + pointsPost: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.posts / peak)) * this.viewBoxY}`).join(' '), + pointsReply: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.replies / peak)) * this.viewBoxY}`).join(' '), + pointsRepost: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.reposts / peak)) * this.viewBoxY}`).join(' '), + pointsTotal: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.total / peak)) * this.viewBoxY}`).join(' ') }); }; diff --git a/src/web/app/desktop/tags/home-widgets/server.tag b/src/web/app/desktop/tags/home-widgets/server.tag new file mode 100644 index 0000000000..7a51299585 --- /dev/null +++ b/src/web/app/desktop/tags/home-widgets/server.tag @@ -0,0 +1,177 @@ +<mk-server-home-widget> + <p class="title"><i class="fa fa-server"></i>%i18n:desktop.tags.mk-server-home-widget.title%</p> + <button onclick={ toggle } title="%i18n:desktop.tags.mk-server-home-widget.toggle%"><i class="fa fa-sort"></i></button> + <p class="initializing" if={ initializing }><i class="fa fa-spinner fa-pulse fa-fw"></i>%i18n:common.loading%<mk-ellipsis/></p> + <mk-server-home-widget-stats if={ !initializing && view == 0 }/> + <mk-server-home-widget-info if={ !initializing && view == 1 } meta={ meta }/> + <style> + :scope + display block + background #fff + + > .title + z-index 1 + margin 0 + padding 0 16px + line-height 42px + font-size 0.9em + font-weight bold + color #888 + box-shadow 0 1px rgba(0, 0, 0, 0.07) + + > i + margin-right 4px + + > button + position absolute + z-index 2 + top 0 + right 0 + padding 0 + width 42px + font-size 0.9em + line-height 42px + color #ccc + + &:hover + color #aaa + + &:active + color #999 + + > .initializing + margin 0 + padding 16px + text-align center + color #aaa + + > i + margin-right 4px + + </style> + <script> + this.mixin('api'); + + this.initializing = true; + this.view = 0; + + this.on('mount', () => { + this.api('meta').then(meta => { + this.update({ + initializing: false, + meta + }); + }); + }); + + this.toggle = () => { + this.view++; + if (this.view == 2) this.view = 0; + }; + </script> +</mk-server-home-widget> + +<mk-server-home-widget-stats> + <svg riot-viewBox="0 0 { viewBoxX } { viewBoxY }" preserveAspectRatio="none"> + <text dx="1" dy="5">CPU</text> + <polygon + riot-points={ cpuPolygonPoints } + riot-fill={ cpuColor } + fill-opacity="0.5"/> + <polyline + riot-points={ cpuPolylinePoints } + fill="none" + stroke-width="1" + riot-stroke={ cpuColor }/> + </svg> + <svg riot-viewBox="0 0 { viewBoxX } { viewBoxY }" preserveAspectRatio="none"> + <text dx="1" dy="5">MEM</text> + <polygon + riot-points={ memPolygonPoints } + riot-fill={ memColor } + fill-opacity="0.5"/> + <polyline + riot-points={ memPolylinePoints } + fill="none" + stroke-width="1" + riot-stroke={ memColor }/> + </svg> + <style> + :scope + display block + + > svg + display block + padding 10px + width 50% + float left + + &:first-child + padding-right 5px + + &:last-child + padding-left 5px + + > text + font-size 5px + fill #7b7b7b + + &:after + content "" + display block + clear both + </style> + <script> + import Connection from '../../../common/scripts/server-stream'; + + this.viewBoxX = 50; + this.viewBoxY = 30; + this.stats = []; + this.connection = new Connection(); + + this.on('mount', () => { + this.connection.on('stats', this.onStats); + }); + + this.on('unmount', () => { + this.connection.off('stats', this.onStats); + this.connection.close(); + }); + + this.onStats = stats => { + this.stats.push(stats); + if (this.stats.length > 50) this.stats.shift(); + + const cpuPolylinePoints = this.stats.map((s, i) => `${this.viewBoxX - ((this.stats.length - 1) - i)},${(1 - s.cpu_usage) * this.viewBoxY}`).join(' '); + const memPolylinePoints = this.stats.map((s, i) => `${this.viewBoxX - ((this.stats.length - 1) - i)},${(s.mem.free / s.mem.total) * this.viewBoxY}`).join(' '); + + const cpuPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${ this.viewBoxY } ${ cpuPolylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`; + const memPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${ this.viewBoxY } ${ memPolylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`; + + const cpuColor = `hsl(${180 - (stats.cpu_usage * 180)}, 80%, 70%)`; + const memColor = `hsl(${180 - (stats.mem.free / stats.mem.total * 180)}, 80%, 70%)`; + + this.update({ + cpuPolylinePoints, + memPolylinePoints, + cpuPolygonPoints, + memPolygonPoints, + cpuColor, + memColor + }); + }; + </script> +</mk-server-home-widget-stats> + +<mk-server-home-widget-info> + <p>Maintainer: { meta.maintainer }</p> + <style> + :scope + display block + padding 10px + </style> + <script> + this.meta = this.opts.meta; + </script> +</mk-server-home-widget-info> + diff --git a/src/web/app/desktop/tags/home.tag b/src/web/app/desktop/tags/home.tag index 0e4a2ced10..41053ccbbe 100644 --- a/src/web/app/desktop/tags/home.tag +++ b/src/web/app/desktop/tags/home.tag @@ -70,6 +70,7 @@ 'rss-reader', 'trends', 'photo-stream', + 'server', 'version' ], right: [ diff --git a/src/web/app/desktop/tags/index.js b/src/web/app/desktop/tags/index.js index 1e0ebd44cf..177ba41293 100644 --- a/src/web/app/desktop/tags/index.js +++ b/src/web/app/desktop/tags/index.js @@ -45,6 +45,7 @@ require('./home-widgets/version.tag'); require('./home-widgets/recommended-polls.tag'); require('./home-widgets/trends.tag'); require('./home-widgets/activity.tag'); +require('./home-widgets/server.tag'); require('./timeline.tag'); require('./messaging/window.tag'); require('./messaging/room-window.tag'); diff --git a/src/web/app/init.js b/src/web/app/init.js index 17f9a2d09e..b442d36a15 100644 --- a/src/web/app/init.js +++ b/src/web/app/init.js @@ -8,7 +8,7 @@ import * as riot from 'riot'; import api from './common/scripts/api'; import signout from './common/scripts/signout'; import checkForUpdate from './common/scripts/check-for-update'; -import Connection from './common/scripts/stream'; +import Connection from './common/scripts/home-stream'; import mixin from './common/mixins'; import generateDefaultUserdata from './common/scripts/generate-default-userdata'; import CONFIG from './common/scripts/config'; @@ -95,7 +95,7 @@ export default callback => { }); } - // Init stream connection + // Init home stream connection const stream = me ? new Connection(me) : null; // ミックスイン初期化 |