summaryrefslogblamecommitdiffstats
path: root/static/new_status-dnbd3.html
blob: 85a34ec5eea020aa314e32e43e621d3d54ae8b0f (plain) (tree)
1
2
3
4
5
6



                      

                         










                                   
  
                     
                  

                            





                           



                        













                                


               


          

       
 
                

                                                                                                                       
               

                                                                                                



                                                                                                                                
                                                                          

                                                                              
                                                                                                                         
                                                                                                   
                 


                
          
                                                           


                                  

                                   




                   








                                                                                                                                                                                                                                              
    



























                                                                                                                                 
          

                              
     



                                                 
                                          

                                       












                                                                                                                              
                                     
                                                     
                                                            










                                                                               

       





                                                                                       






                                                          
                                                                                                                   




                                                                                                











                                                                      
     



                                                                 
                                                                                
                     









                                                      

                                      





                                                  





         
<!DOCTYPE html>
<meta charset="utf-8">
<html>
<head>
  <style type="text/css">
  
  html, body {
    height: 100%;
    margin: 0;
  }

  #app {
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
  
  .server-container {
    display: flex;
    justify-content: center;
    overflow-y: auto;
  }
  
  .server {
    border-spacing: 5px;
    background-color: #eee;
    border: 1px solid #666;
    flex: 1;
    white-space: nowrap;
    max-width: 360px;
    margin: 5px;
  }
  
  .first-row {
    font-weight: bold;
  }
  
  .server-ip {
    text-align: center;
  }
  
  .client-label, .client-speed {
    border: 1px solid black;
    text-align: center;
  }

  .expand {
    width: 99%;
  }
  
  </style>
</head>
<body>

  <div id="app">
    <div class="server-container">
      <table v-for="(server, index) in servers" class="server" :style="{ border: '2px solid ' + GRAPH_COLORS[index] }">
        <tbody>
          <tr class="first-row"><td colspan="2" class="server-ip">{{ server.address }}</td></tr>
          <tr><td>Uptime:</td><td class="expand">{{ formatSeconds(server.uptime) }}</td></tr>
          <tr><td>Upload speed:</td><td>{{ formatSpeed(peak ? server.peakUploadSpeed : server.avgUploadSpeed) }}</td></tr>
          <tr><td>Download speed:</td><td>{{ formatSpeed(peak ? server.peakDownloadSpeed : server.avgDownloadSpeed) }}</td></tr>
          <tr><td>Total sent:</td><td>{{ formatSpeed(server.bytesSent) }}</td></tr>
          <tr><td>Total received:</td><td>{{ formatSpeed(server.bytesReceived) }}</td></tr>
          <tr><td>Client count:</td><td>{{ server.clientCount }}</td></tr>
          <tr v-for="client in server.clients">
            <td class="client-label">{{ client.address.split( ":" )[0] }}</td>
            <td class="client-speed" :style="calcBackgroundStyle(peak ? client.peakUploadSpeed : client.avgUploadSpeed)">
              <span>{{ formatSpeed(peak ? client.peakUploadSpeed : client.avgUploadSpeed) }}</span>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    <canvas ref="chart" :width="this.canvasWidth"></canvas>
  </div>
  
<script src="vue.min.js"></script>
<script src="smoothie.js"></script>

<script>

var app = new Vue({
  el: '#app',
  data: {
    rawData: {},
    servers: [],
    logs: {},
    timespan: 120,
    peak: false,
    canvasWidth: 0,
    smoothie: null,
    graphLines: {},
    GRAPH_COLORS: ["#3366cc", "#dc3912", "#ff9900", "#109618", "#990099", "#0099c6", "#dd4477", "#66aa00", "#b82e2e", "#316395", "#994499", "#22aa99", "#aaaa11", "#6633cc", "#e67300", "#8b0707", "#651067", "#329262", "#5574a6", "#3b3eac"]
  },
  watch: {
    rawData () {
      if (this.rawData.servers) {
        const servers = this.rawData.servers.slice(0)
        servers.sort(this.compareObjectIps)
        const currentTime = new Date().getTime()
        servers.forEach((server, index) => {
          this.calcSpeed(server)

          // Update the graph
          if (!this.graphLines[server.address]) {
            Vue.set(this.graphLines, server.address, new TimeSeries({ logarithmicScale: true }))
            this.smoothie.addTimeSeries(this.graphLines[server.address], { lineWidth: 2, strokeStyle: this.GRAPH_COLORS[index] })
          }
          this.graphLines[server.address].append(currentTime, server.uploadSpeed)

          // Update clients
          server.clients.forEach(client => {
            client.timestamp = server.timestamp
            this.calcSpeed(client)
          })
          if (this.peak) {
            server.clients = server.clients.filter(client => client.peakUploadSpeed > 0)
            server.clients.sort((a, b) => b.peakUploadSpeed - a.peakUploadSpeed)
          } else {
            server.clients = server.clients.filter(client => client.avgUploadSpeed > 0)
            server.clients.sort((a, b) => b.avgUploadSpeed - a.avgUploadSpeed)
          }
        })
        this.servers = servers
      }
    }
  },
  methods: {
    async updateData () {
      const response = await fetch('/data2.json')
      this.rawData = await response.json()
      setTimeout(this.updateData, 2000)
    },
    calcSpeed (obj) {
      // Create a log for this ip if it doesn't exist already
      if(!this.logs[obj.address]) Vue.set(this.logs, obj.address, [])
      // Remove outdated values
      this.logs[obj.address] = this.logs[obj.address].filter(x => x.timestamp > this.rawData.timestamp - this.timespan * 1000)
      // Get the all the old values accumulated over the timespan
      const log = this.logs[obj.address]
      // Add new values to the log
      if (log.length === 0 || obj.timestamp > log[log.length - 1].timestamp) log.push(obj)

      if (log.length > 1) {
        // Calculate current speeds
        var a = log[log.length - 2]
        const b = log[log.length - 1]
        var time = (b.timestamp - a.timestamp) / 1000
        obj.uploadSpeed = (b.bytesSent - a.bytesSent) / time
        obj.downloadSpeed = (b.bytesReceived - a.bytesReceived) / time

        // Calculate peak speeds
        obj.peakUploadSpeed = Math.max(...log.map(x => x.uploadSpeed || 0))
        obj.peakDownloadSpeed = Math.max(...log.map(x => x.downloadSpeed || 0))

        // Calculate average speeds
        a = log[0]
        time = (b.timestamp - a.timestamp) / 1000
        obj.avgUploadSpeed = (b.bytesSent - a.bytesSent) / time
        obj.avgDownloadSpeed = (b.bytesReceived - a.bytesReceived) / time
      }
    },
    formatSpeed (bytes) {
      if (bytes < 1024) return bytes.toFixed(2) + ' B/s'
      else if (bytes < 1048576) return (bytes / 1024).toFixed(2) + ' KiB/s'
      else if (bytes < 1073741824) return (bytes / 1048576).toFixed(2) + ' MiB/s'
      else if (bytes < 1099511627776) return (bytes / 1073741824).toFixed(2) + ' GiB/s'
      else return (bytes / 1099511627776).toFixed(2) + ' TiB/s'
    },
    formatSeconds (seconds) {
      return ( Math.floor(seconds / ( 3600 * 24 ) ) + 'd '
             + Math.floor(seconds / 3600 ) % 24 + 'h '
             + Math.floor(seconds / 60 ) % 60 + 'min' )
    },
    calcBackgroundStyle (speed) {
      const percent = Math.round(Math.max(0, Math.min(100, this.logScale(speed) / this.logScale(262144000) * 100)))
      var color = '#056d00'
      if (speed < 1048576) color = '#8adb8b'
      else if (speed < 10485760) color = '#5cdb55'
      else if (speed < 104857600) color = '#26a81f'
      return { background: `linear-gradient(90deg, ${color} ${percent}%, #e0e0e0 ${percent}%)` }
    },
    compareObjectIps (obj1, obj2) {
      const parts1 = obj1.address.split('.').map(str => parseInt(str))
      const parts2 = obj2.address.split('.').map(str => parseInt(str))
      var result = parts1[0] - parts2[0]
      if (result === 0) result = parts1[1] - parts2[1]
      if (result === 0) result = parts1[2] - parts2[2]
      if (result === 0) result = parts1[3] - parts2[3]
      return result
    },
    logScale (value) {
      return Math.log(value/100000 + 1)
    }
  },
  created () {
    const urlParams = new URLSearchParams(window.location.search)
    this.timespan = parseInt(urlParams.get('timespan')) || 120
    this.peak = urlParams.get('peak') === 'true' || urlParams.get('peak') === ''
    this.updateData()
  },
  mounted () {
    this.canvasWidth = window.innerWidth
    window.addEventListener('resize', () => {
      this.canvasWidth = window.innerWidth
    })
    this.smoothie = new SmoothieChart({
      'millisPerPixel': 300,
      'grid': { 'millisPerLine': 30000 },
      timestampFormatter: SmoothieChart.timeFormatter,
      yMaxFormatter: this.formatSpeed,
      yMinFormatter: this.formatSpeed,
      valueTransformFunction: this.logScale,
      minValue: 0,
      maxValue: 262144000,
      labels: { fontSize: 13 }
    })
    this.smoothie.streamTo(this.$refs.chart, 2000)
  }
})

</script>
</body>
</html>