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