Initial commit
This commit is contained in:
commit
b28b03b78e
9 changed files with 251 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
config/*.coffee
|
||||||
|
node_modules/*
|
55
README.md
Normal file
55
README.md
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#DBMonitor
|
||||||
|
|
||||||
|
Use your web browser to monitor table inserts
|
||||||
|
|
||||||
|
##Description
|
||||||
|
|
||||||
|
Monitor inserts to a specific table of a datbase based on a MySQL timestamp
|
||||||
|
column.
|
||||||
|
|
||||||
|
##Dependencies
|
||||||
|
|
||||||
|
* nodejs
|
||||||
|
* npm
|
||||||
|
* Static web server
|
||||||
|
|
||||||
|
##Install
|
||||||
|
|
||||||
|
```
|
||||||
|
$ git clone git://github.com/atomaka/dbmonitor.git
|
||||||
|
$ cd dbmonitor
|
||||||
|
$ npm install
|
||||||
|
$ cp config/application.coffee.sample application.coffee
|
||||||
|
$ cp config/database.coffee.sample database.coffee
|
||||||
|
```
|
||||||
|
|
||||||
|
* Edit settings in application.coffee and database.coffee as necessary
|
||||||
|
* Setup your web server to serve the public directory
|
||||||
|
|
||||||
|
##Usage
|
||||||
|
|
||||||
|
Go to URL setup in your static web server!
|
||||||
|
|
||||||
|
##License
|
||||||
|
|
||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2012 Andrew Tomaka
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
10
config/application.coffee.sample
Normal file
10
config/application.coffee.sample
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
application_config = {
|
||||||
|
port: 5120
|
||||||
|
updateTime: 10
|
||||||
|
table: 'print_jobs'
|
||||||
|
columns: ['print_host','user_print', '(pages_end - pages_start) AS pages', 'queue_name']
|
||||||
|
timestamp_column: 'rec_time'
|
||||||
|
where: "queue_name IN('wellsaop1','wellsaop2')"
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = application_config
|
9
config/database.coffee.sample
Normal file
9
config/database.coffee.sample
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
database_config = {
|
||||||
|
host: 'localhost'
|
||||||
|
port: 3306
|
||||||
|
database: 'database'
|
||||||
|
username: 'username'
|
||||||
|
password: 'password'
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = database_config
|
32
dbmonitor.coffee
Normal file
32
dbmonitor.coffee
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
database = require './config/database.coffee'
|
||||||
|
application = require './config/application.coffee'
|
||||||
|
|
||||||
|
moment = require 'moment'
|
||||||
|
io = require('socket.io').listen(application.port)
|
||||||
|
|
||||||
|
sockets = []
|
||||||
|
io.set('log level', 1);
|
||||||
|
|
||||||
|
db = require('mysql-native').createTCPClient(database.host, database.port)
|
||||||
|
db.auth database.database, database.username, database.password
|
||||||
|
db.auto_prepare = true
|
||||||
|
|
||||||
|
checkDate = moment().add('minutes', -5)
|
||||||
|
|
||||||
|
getDatabaseUpdates = () ->
|
||||||
|
query = "SELECT " + application.timestamp_column + "," + application.columns.join(',') + " FROM " + application.table + " WHERE " + application.where + " AND " + application.timestamp_column + " > '" + checkDate.format('YYYY-MM-DD HH:mm:ss') + "'"
|
||||||
|
db.query(query).addListener 'row', (job) ->
|
||||||
|
jobDate = moment(job.rec_time, 'YYYY-MM-DD HH:mm:ss')
|
||||||
|
checkDate = jobDate if jobDate > checkDate
|
||||||
|
updateClient job
|
||||||
|
|
||||||
|
updateClient = (job) ->
|
||||||
|
for client in sockets
|
||||||
|
client.emit 'update', job
|
||||||
|
|
||||||
|
io.sockets.on 'connection', (socket) ->
|
||||||
|
sockets.push socket
|
||||||
|
|
||||||
|
setInterval () ->
|
||||||
|
getDatabaseUpdates()
|
||||||
|
, 1000 * application.updateTime
|
11
package.json
Normal file
11
package.json
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"name": "dbmonitor",
|
||||||
|
"description": "Use your web browser to monitor table inserts",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"mysql-native": "0.4.x",
|
||||||
|
"socket.io": "0.9.x",
|
||||||
|
"moment": "1.7.x"
|
||||||
|
}
|
||||||
|
}
|
50
public/css/style.css
Normal file
50
public/css/style.css
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
.down {
|
||||||
|
width: 794px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
background-color: #f2cac2;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
width: 800px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse:collapse;
|
||||||
|
border-bottom: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
table, th, td {
|
||||||
|
border-left: 1px solid black;
|
||||||
|
border-right: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
border-top: 1px solid black;
|
||||||
|
border-bottom: 1px solid black;
|
||||||
|
text-align: left;
|
||||||
|
background-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(odd) {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
67
public/index.html
Normal file
67
public/index.html
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<!doctype html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<title>DBMonitor</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="css/style.css">
|
||||||
|
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.10/socket.io.min.js"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/coffee-script/1.3.3/coffee-script.min.js"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/mustache.js/0.5.0-dev/mustache.min.js"></script>
|
||||||
|
<script src="https://raw.github.com/jonnyreeves/jquery-Mustache/master/src/jquery-Mustache.js"></script>
|
||||||
|
|
||||||
|
<script type="text/coffeescript">
|
||||||
|
server = window.location.protocol + '//' + window.location.hostname
|
||||||
|
$.Mustache.load('./templates/views.html')
|
||||||
|
|
||||||
|
socket = io.connect server + ':5120', {
|
||||||
|
'reconnect': true,
|
||||||
|
'reconnection_delay': 500,
|
||||||
|
'max reconnection attempts': 25
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.on 'connect', () ->
|
||||||
|
$('#disconnected').hide()
|
||||||
|
if $('#container tbody').children().length == 0
|
||||||
|
$('#empty').show()
|
||||||
|
|
||||||
|
socket.on 'disconnect', () ->
|
||||||
|
$('#disconnected').show()
|
||||||
|
$('#empty').hide()
|
||||||
|
|
||||||
|
socket.on 'error', (reason) ->
|
||||||
|
console.log 'Socket.io error', reason
|
||||||
|
|
||||||
|
socket.on 'update', (data) ->
|
||||||
|
if $('#container thead').children().length == 0
|
||||||
|
$('#container thead').html($.Mustache.render('header', getKeys(data)))
|
||||||
|
$('#empty').hide()
|
||||||
|
|
||||||
|
$('#container tbody').html($.Mustache.render('row', getValues(data)) + $('#container tbody').html())
|
||||||
|
|
||||||
|
while $('#container tbody').children().length > 20
|
||||||
|
$('#container tbody tr:last').remove()
|
||||||
|
|
||||||
|
getKeys = (data) ->
|
||||||
|
keys = []
|
||||||
|
keys.push key for key, value of data
|
||||||
|
{ 'labels': keys }
|
||||||
|
|
||||||
|
getValues = (data) ->
|
||||||
|
values = []
|
||||||
|
values.push value for key, value of data
|
||||||
|
{ 'values': values }
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="disconnected" class="down text-center">Not connected to the server. Retrying...</div>
|
||||||
|
<div id="empty" class="down text-center">Waiting to receive data from the server.</div>
|
||||||
|
<table id="container">
|
||||||
|
<thead></thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
15
public/templates/views.html
Normal file
15
public/templates/views.html
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<script id="header" type="text/html">
|
||||||
|
<tr>
|
||||||
|
{{#labels}}
|
||||||
|
<th>{{.}}</th>
|
||||||
|
{{/labels}}
|
||||||
|
</tr>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="row" type="text/html">
|
||||||
|
<tr>
|
||||||
|
{{#values}}
|
||||||
|
<td>{{.}}</td>
|
||||||
|
{{/values}}
|
||||||
|
</tr>
|
||||||
|
</script>
|
Loading…
Reference in a new issue