Package flumotion :: Package component :: Package misc :: Package httpserver :: Module serverstats
[hide private]

Source Code for Module flumotion.component.misc.httpserver.serverstats

  1  # -*- Mode: Python; test-case-name: -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3   
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007,2008,2009 Fluendo, S.L. 
  6  # Copyright (C) 2010,2011 Flumotion Services, S.A. 
  7  # All rights reserved. 
  8  # 
  9  # This file may be distributed and/or modified under the terms of 
 10  # the GNU Lesser General Public License version 2.1 as published by 
 11  # the Free Software Foundation. 
 12  # This file is distributed without any warranty; without even the implied 
 13  # warranty of merchantability or fitness for a particular purpose. 
 14  # See "LICENSE.LGPL" in the source distribution for more information. 
 15  # 
 16  # Headers in this file shall remain intact. 
 17   
 18  import time 
 19   
 20  from twisted.internet import reactor 
 21   
 22  from flumotion.common import log 
 23   
 24   
 25  # Minimum size to take in account when calculating mean file read 
 26  MIN_REQUEST_SIZE = 64 * 1024 + 1 
 27  # Statistics update period 
 28  STATS_UPDATE_PERIOD = 10 
 29   
 30   
31 -class RequestStatistics(object):
32
33 - def __init__(self, serverStats):
34 self._stats = serverStats 35 self.bytesSent = 0L 36 self._stats._onRequestStart(self)
37
38 - def onDataSent(self, size):
39 self.bytesSent += size 40 self._stats._onRequestDataSent(self, size)
41
42 - def onCompleted(self, size):
43 self._stats._onRequestComplete(self, size)
44 45
46 -class ServerStatistics(object):
47 48 _updater = None 49 _callId = None 50
51 - def __init__(self):
52 now = time.time() 53 self.startTime = now 54 self.currentRequestCount = 0 55 self.totalRequestCount = 0 56 self.requestCountPeak = 0 57 self.requestCountPeakTime = now 58 self.finishedRequestCount = 0 59 self.totalBytesSent = 0L 60 61 # Updated by a call to the update method 62 self.meanRequestCount = 0 63 self.currentRequestRate = 0 64 self.requestRatePeak = 0 65 self.requestRatePeakTime = now 66 self.meanRequestRate = 0.0 67 self.currentBitrate = 0 68 self.meanBitrate = 0 69 self.bitratePeak = 0 70 self.bitratePeakTime = now 71 72 self._fileReadRatios = 0.0 73 self._lastUpdateTime = now 74 self._lastRequestCount = 0 75 self._lastBytesSent = 0L
76
77 - def startUpdates(self, updater):
78 self._updater = updater 79 self._set("bitrate-peak-time", self.bitratePeakTime) 80 self._set("request-rate-peak-time", self.requestRatePeakTime) 81 self._set("request-count-peak-time", self.requestCountPeakTime) 82 if self._callId is None: 83 self._callId = reactor.callLater(STATS_UPDATE_PERIOD, self._update)
84
85 - def stopUpdates(self):
86 self._updater = None 87 if self._callId is not None: 88 self._callId.cancel() 89 self._callId = None
90
91 - def getMeanFileReadRatio(self):
92 if self.finishedRequestCount > 0: 93 return self._fileReadRatios / self.finishedRequestCount 94 return 0.0
95 meanFileReadRatio = property(getMeanFileReadRatio) 96
97 - def _update(self):
98 now = time.time() 99 updateDelta = now - self._lastUpdateTime 100 # Update average concurrent request 101 meanReqCount = self._updateAverage(self._lastUpdateTime, now, 102 self.meanRequestCount, 103 self.currentRequestCount) 104 # Calculate Request rate 105 countDiff = self.totalRequestCount - self._lastRequestCount 106 newReqRate = float(countDiff) / updateDelta 107 # Calculate average request rate 108 meanReqRate = self._updateAverage(self._lastUpdateTime, now, 109 self.currentRequestRate, newReqRate) 110 # Calculate current bitrate 111 bytesDiff = (self.totalBytesSent - self._lastBytesSent) * 8 112 newBitrate = bytesDiff / updateDelta 113 # calculate average bitrate 114 meanBitrate = self._updateAverage(self._lastUpdateTime, now, 115 self.currentBitrate, newBitrate) 116 # Update Values 117 self.meanRequestCount = meanReqCount 118 self.currentRequestRate = newReqRate 119 self.meanRequestRate = meanReqRate 120 self.currentBitrate = newBitrate 121 self.meanBitrate = meanBitrate 122 123 # Update the statistics keys with the new values 124 self._set("mean-request-count", meanReqCount) 125 self._set("current-request-rate", newReqRate) 126 self._set("mean-request-rate", meanReqRate) 127 self._set("current-bitrate", newBitrate) 128 self._set("mean-bitrate", meanBitrate) 129 130 # Update request rate peak 131 if newReqRate > self.requestRatePeak: 132 self.requestRatePeak = newReqRate 133 self.requestRatePeakTime = now 134 # update statistic keys 135 self._set("request-rate-peak", newReqRate) 136 self._set("request-rate-peak-time", now) 137 138 # Update bitrate peak 139 if newBitrate > self.bitratePeak: 140 self.bitratePeak = newBitrate 141 self.bitratePeakTime = now 142 # update statistic keys 143 self._set("bitrate-peak", newBitrate) 144 self._set("bitrate-peak-time", now) 145 146 # Update bytes read statistic key too 147 self._set("total-bytes-sent", self.totalBytesSent) 148 149 self._lastRequestCount = self.totalRequestCount 150 self._lastBytesSent = self.totalBytesSent 151 self._lastUpdateTime = now 152 # Log the stats 153 self._logStatsLine() 154 self._callId = reactor.callLater(STATS_UPDATE_PERIOD, self._update)
155
156 - def _set(self, key, value):
157 if self._updater is not None: 158 self._updater.update(key, value)
159
160 - def _onRequestStart(self, stats):
161 # Update counters 162 self.currentRequestCount += 1 163 self.totalRequestCount += 1 164 self._set("current-request-count", self.currentRequestCount) 165 self._set("total-request-count", self.totalRequestCount) 166 # Update concurrent request peak 167 if self.currentRequestCount > self.requestCountPeak: 168 now = time.time() 169 self.requestCountPeak = self.currentRequestCount 170 self.requestCountPeakTime = now 171 self._set("request-count-peak", self.currentRequestCount) 172 self._set("request-count-peak-time", now)
173
174 - def _onRequestDataSent(self, stats, size):
175 self.totalBytesSent += size
176
177 - def _onRequestComplete(self, stats, size):
178 self.currentRequestCount -= 1 179 self.finishedRequestCount += 1 180 self._set("current-request-count", self.currentRequestCount) 181 if (size > 0) and (stats.bytesSent > MIN_REQUEST_SIZE): 182 self._fileReadRatios += float(stats.bytesSent) / size 183 self._set("mean-file-read-ratio", self.meanFileReadRatio)
184
185 - def _updateAverage(self, lastTime, newTime, lastValue, newValue):
186 lastDelta = lastTime - self.startTime 187 newDelta = newTime - lastTime 188 if lastDelta > 0: 189 delta = lastDelta + newDelta 190 before = (lastValue * lastDelta) / delta 191 after = (newValue * newDelta) / delta 192 return before + after 193 return lastValue
194
195 - def _logStatsLine(self):
196 """ 197 Statistic fields names: 198 TRC: Total Request Count 199 CRC: Current Request Count 200 CRR: Current Request Rate 201 MRR: Mean Request Rate 202 FRR: File Read Ratio 203 MBR: Mean Bitrate 204 CBR: Current Bitrate 205 """ 206 log.debug("stats-http-server", 207 "TRC: %s; CRC: %d; CRR: %.2f; MRR: %.2f; " 208 "FRR: %.4f; MBR: %d; CBR: %d", 209 self.totalRequestCount, self.currentRequestCount, 210 self.currentRequestRate, self.meanRequestRate, 211 self.meanFileReadRatio, self.meanBitrate, 212 self.currentBitrate)
213