| OLD | NEW |
| 1 # This file is part of Buildbot. Buildbot is free software: you can | 1 # This file is part of Buildbot. Buildbot is free software: you can |
| 2 # redistribute it and/or modify it under the terms of the GNU General Public | 2 # redistribute it and/or modify it under the terms of the GNU General Public |
| 3 # License as published by the Free Software Foundation, version 2. | 3 # License as published by the Free Software Foundation, version 2. |
| 4 # | 4 # |
| 5 # This program is distributed in the hope that it will be useful, but WITHOUT | 5 # This program is distributed in the hope that it will be useful, but WITHOUT |
| 6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 7 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | 7 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 8 # details. | 8 # details. |
| 9 # | 9 # |
| 10 # You should have received a copy of the GNU General Public License along with | 10 # You should have received a copy of the GNU General Public License along with |
| 11 # this program; if not, write to the Free Software Foundation, Inc., 51 | 11 # this program; if not, write to the Free Software Foundation, Inc., 51 |
| 12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 13 # | 13 # |
| 14 # Copyright Buildbot Team Members | 14 # Copyright Buildbot Team Members |
| 15 | 15 |
| 16 | 16 |
| 17 import os, weakref | 17 import os, time, weakref |
| 18 | 18 |
| 19 from zope.interface import implements | 19 from zope.interface import implements |
| 20 from twisted.python import log | 20 from twisted.python import log |
| 21 from twisted.application import strports, service | 21 from twisted.application import strports, service |
| 22 from twisted.web import server, distrib, static | 22 from twisted.web import server, distrib, static |
| 23 from twisted.spread import pb | 23 from twisted.spread import pb |
| 24 from twisted.web.util import Redirect | 24 from twisted.web.util import Redirect |
| 25 | 25 |
| 26 from buildbot.interfaces import IStatusReceiver | 26 from buildbot.interfaces import IStatusReceiver |
| 27 | 27 |
| 28 from buildbot.status.web.base import StaticFile, createJinjaEnv | 28 from buildbot.status.web.base import StaticFile, createJinjaEnv |
| 29 from buildbot.status.web.feeds import Rss20StatusResource, \ | 29 from buildbot.status.web.feeds import Rss20StatusResource, \ |
| 30 Atom10StatusResource | 30 Atom10StatusResource |
| 31 from buildbot.status.web.waterfall import WaterfallStatusResource | 31 from buildbot.status.web.waterfall import WaterfallStatusResource |
| 32 from buildbot.status.web.console import ConsoleStatusResource | 32 from buildbot.status.web.console import ConsoleStatusResource |
| 33 from buildbot.status.web.olpb import OneLinePerBuild | 33 from buildbot.status.web.olpb import OneLinePerBuild |
| 34 from buildbot.status.web.grid import GridStatusResource, TransposedGridStatusRes
ource | 34 from buildbot.status.web.grid import GridStatusResource, TransposedGridStatusRes
ource |
| 35 from buildbot.status.web.changes import ChangesResource | 35 from buildbot.status.web.changes import ChangesResource |
| 36 from buildbot.status.web.builder import BuildersResource | 36 from buildbot.status.web.builder import BuildersResource |
| 37 from buildbot.status.web.buildstatus import BuildStatusStatusResource | 37 from buildbot.status.web.buildstatus import BuildStatusStatusResource |
| 38 from buildbot.status.web.slaves import BuildSlavesResource | 38 from buildbot.status.web.slaves import BuildSlavesResource |
| 39 from buildbot.status.web.status_json import JsonStatusResource | 39 from buildbot.status.web.status_json import JsonStatusResource |
| 40 from buildbot.status.web.about import AboutBuildbot | 40 from buildbot.status.web.about import AboutBuildbot |
| 41 from buildbot.status.web.authz import Authz | 41 from buildbot.status.web.authz import Authz |
| 42 from buildbot.status.web.auth import AuthFailResource | 42 from buildbot.status.web.auth import AuthFailResource |
| 43 from buildbot.status.web.root import RootPage | 43 from buildbot.status.web.root import RootPage |
| 44 from buildbot.status.web.change_hook import ChangeHookResource | 44 from buildbot.status.web.change_hook import ChangeHookResource |
| 45 | 45 |
| 46 from infra_libs.ts_mon.common import http_metrics |
| 47 |
| 46 # this class contains the WebStatus class. Basic utilities are in base.py, | 48 # this class contains the WebStatus class. Basic utilities are in base.py, |
| 47 # and specific pages are each in their own module. | 49 # and specific pages are each in their own module. |
| 48 | 50 |
| 49 class WebStatus(service.MultiService): | 51 class WebStatus(service.MultiService): |
| 50 implements(IStatusReceiver) | 52 implements(IStatusReceiver) |
| 51 # TODO: IStatusReceiver is really about things which subscribe to hear | 53 # TODO: IStatusReceiver is really about things which subscribe to hear |
| 52 # about buildbot events. We need a different interface (perhaps a parent | 54 # about buildbot events. We need a different interface (perhaps a parent |
| 53 # of IStatusReceiver) for status targets that don't subscribe, like the | 55 # of IStatusReceiver) for status targets that don't subscribe, like the |
| 54 # WebStatus class. buildbot.master.BuildMaster.loadConfig:737 asserts | 56 # WebStatus class. buildbot.master.BuildMaster.loadConfig:737 asserts |
| 55 # that everything in c['status'] provides IStatusReceiver, but really it | 57 # that everything in c['status'] provides IStatusReceiver, but really it |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 def either(a,b): # a if a else b for py2.4 | 381 def either(a,b): # a if a else b for py2.4 |
| 380 if a: | 382 if a: |
| 381 return a | 383 return a |
| 382 else: | 384 else: |
| 383 return b | 385 return b |
| 384 | 386 |
| 385 rotateLength = either(self.logRotateLength, self.master.log_rotation.rot
ateLength) | 387 rotateLength = either(self.logRotateLength, self.master.log_rotation.rot
ateLength) |
| 386 maxRotatedFiles = either(self.maxRotatedFiles, self.master.log_rotation.
maxRotatedFiles) | 388 maxRotatedFiles = either(self.maxRotatedFiles, self.master.log_rotation.
maxRotatedFiles) |
| 387 | 389 |
| 388 if not self.site: | 390 if not self.site: |
| 389 | 391 |
| 392 class MonitoredRequest(server.Request): |
| 393 def __init__(self, *args, **kwargs): |
| 394 server.Request.__init__(self, *args, **kwargs) |
| 395 self.startTime = time.time() |
| 396 |
| 397 def render(self, resrc): |
| 398 self.resourceClassName = resrc.__class__.__name__ |
| 399 server.Request.render(self, resrc) |
| 400 |
| 390 class RotateLogSite(server.Site): | 401 class RotateLogSite(server.Site): |
| 402 requestFactory = MonitoredRequest |
| 403 |
| 404 def log(self, request): |
| 405 server.Site.log(self, request) |
| 406 |
| 407 durationMsec = 1000 * (time.time() - request.startTime) |
| 408 |
| 409 requestLength = request.getHeader('content-length') |
| 410 if requestLength is not None: |
| 411 requestLength = int(requestLength) |
| 412 |
| 413 http_metrics.update_http_server_metrics( |
| 414 request.resourceClassName, |
| 415 request.code, |
| 416 durationMsec, |
| 417 requestLength, |
| 418 request.sentLength, |
| 419 request.getHeader('user-agent') or '') |
| 420 |
| 391 def _openLogFile(self, path): | 421 def _openLogFile(self, path): |
| 392 try: | 422 try: |
| 393 from twisted.python.logfile import LogFile | 423 from twisted.python.logfile import LogFile |
| 394 log.msg("Setting up http.log rotating %s files of %s byt
es each" % | 424 log.msg("Setting up http.log rotating %s files of %s byt
es each" % |
| 395 (maxRotatedFiles, rotateLength)) | 425 (maxRotatedFiles, rotateLength)) |
| 396 if hasattr(LogFile, "fromFullPath"): # not present in Tw
isted-2.5.0 | 426 if hasattr(LogFile, "fromFullPath"): # not present in Tw
isted-2.5.0 |
| 397 return LogFile.fromFullPath(path, rotateLength=rotat
eLength, maxRotatedFiles=maxRotatedFiles) | 427 return LogFile.fromFullPath(path, rotateLength=rotat
eLength, maxRotatedFiles=maxRotatedFiles) |
| 398 else: | 428 else: |
| 399 log.msg("WebStatus: rotated http logs are not suppor
ted on this version of Twisted") | 429 log.msg("WebStatus: rotated http logs are not suppor
ted on this version of Twisted") |
| 400 except ImportError, e: | 430 except ImportError, e: |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 # What happened to getControl?! | 517 # What happened to getControl?! |
| 488 # | 518 # |
| 489 # instead of passing control objects all over the place in the web | 519 # instead of passing control objects all over the place in the web |
| 490 # code, at the few places where a control instance is required we | 520 # code, at the few places where a control instance is required we |
| 491 # find the requisite object manually, starting at the buildmaster. | 521 # find the requisite object manually, starting at the buildmaster. |
| 492 # This is in preparation for removal of the IControl hierarchy | 522 # This is in preparation for removal of the IControl hierarchy |
| 493 # entirely. | 523 # entirely. |
| 494 | 524 |
| 495 # resources can get access to the IStatus by calling | 525 # resources can get access to the IStatus by calling |
| 496 # request.site.buildbot_service.getStatus() | 526 # request.site.buildbot_service.getStatus() |
| OLD | NEW |