Changeset 493:b79718df78d5

Show
Ignore:
Timestamp:
10/14/08 12:54:35 (3 months ago)
Author:
Brian Warner <warner@allmydata.com>
branch:
default
Message:

incident-gatherer: load all 'classify_*.py' files as classifier plugins

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • ChangeLog

    r492 r493  
     12008-10-14  Brian Warner  <warner@allmydata.com> 
     2 
     3        * foolscap/logging/gatherer.py 
     4        (IncidentGathererService.add_classify_files): make the incident 
     5        gatherer look in its base directory for "classify_*.py" files, use 
     6        them as plugins with classification functions. 
     7        (INCIDENT_GATHERER_TACFILE): update example text to match 
     8        * foolscap/test/test_logging.py (IncidentGatherer): test it 
     9        (Gatherer.test_wrongdir): exercise another error case 
     10        * doc/logging.xhtml (gatherer): document it 
     11 
    1122008-10-13  Brian Warner  <warner@allmydata.com> 
    213 
  • doc/logging.xhtml

    r471 r493  
    891891<p>The Incident Gatherer uses a collection of user-supplied classification 
    892892functions to analyze each Incident and place it into one or more categories. 
    893 To add a classification function, you will need to modify the 
    894 <code>gatherer.tac</code> file, and make a call to 
    895 <code>ig.add_classifier()</code> with your function. These functions accept a 
    896 triggering event and a pathname (from which preceding log events can be 
    897 extracted, if desired), and should return a list of categories. Each incident 
    898 can wind up in multiple categories. If no function finds a category for the 
    899 incident, it will be added to the "unknown" category. All incidents are added 
    900 to the "all" category.</p> 
     893To add a classification function, create a file with a name like 
     894"<code>classify_*.py</code>" (such as <code>classify_foolscap.py</code> or 
     895<code>classify_db.py</code>), and define a function in it named 
     896"<code>classify_incident()</code>". Place this file in the gatherer's 
     897directory. All such files will be loaded and evaluated when the gatherer 
     898starts.</p> 
     899 
     900<p>The <code>classify_incident()</code> function will accept a triggering 
     901event and a pathname (from which preceding log events can be extracted, if 
     902desired), and should return a list of categories. Each incident can wind up 
     903in multiple categories. If no function finds a category for the incident, it 
     904will be added to the "unknown" category. All incidents are added to the "all" 
     905category.</p> 
    901906 
    902907<p>The <code>classified/</code> directory will contain a file for each 
  • foolscap/logging/gatherer.py

    r480 r493  
    426426 
    427427    def add_classifier(self, f): 
     428        # there are old .tac files that call this explicitly 
    428429        self.classifiers.append(f) 
    429430 
     
    436437        if not os.path.isdir(outputdir): 
    437438            os.makedirs(outputdir) 
     439        self.add_classify_files() 
    438440        self.classify_stored_incidents(indir) 
    439441        GatheringBase.startService(self) 
     442 
     443    def add_classify_files(self): 
     444        for fn in os.listdir(self.basedir): 
     445            if not (fn.startswith("classify_") and fn.endswith(".py")): 
     446                continue 
     447            f = open(os.path.join(self.basedir, fn), "r") 
     448            localdict = {} 
     449            exec f in localdict 
     450            self.add_classifier(localdict["classify_incident"]) 
    440451 
    441452    def classify_stored_incidents(self, indir): 
     
    535546gs = gatherer.IncidentGathererService() 
    536547 
    537 # To add a classifier function, call gs.add_classifier(f) like this: 
     548# To add a classifier function, store it in a neighboring file named 
     549# classify_*.py, in a function named classify_incident(). All such files will 
     550# be loaded at startup: 
    538551# 
    539 #import re 
    540 #TUBCON_RE = re.compile(r'^Tub.connectorFinished: WEIRD, <foolscap.negotiate.TubConnector instance at \w+> is not in \[') 
    541 #def is_foolscap(nodeid_s, incident): 
    542 #    (header, events) = incident 
    543 #    trigger = header['trigger'] 
    544 #    m = trigger.get('message', '') 
    545 #    if TUBCON_RE.search(m): 
    546 #        return 'foolscap-tubconnector' 
    547 #gs.add_classifier(is_foolscap) 
     552# %% cat classify_foolscap.py 
     553# import re 
     554# TUBCON_RE = re.compile(r'^Tub.connectorFinished: WEIRD, <foolscap.negotiate.TubConnector instance at \w+> is not in \[') 
     555# def classify_incident(nodeid_s, incident): 
     556#     # match some foolscap messages 
     557#     (header, events) = incident 
     558#     trigger = header['trigger'] 
     559#     m = trigger.get('message', '') 
     560#     if TUBCON_RE.search(m): 
     561#         return 'foolscap-tubconnector' 
     562# %% 
    548563 
    549564application = service.Application('incident_gatherer') 
  • foolscap/test/test_logging.py

    r480 r493  
    10231023            self.remove_classified_incidents(ig) 
    10241024            ig2 = self.create_incident_gatherer(basedir, [classify_boom]) 
    1025             ig2.add_classifier(classify_foom) 
     1025            ##ig2.add_classifier(classify_foom) 
     1026            # we add classify_foom by writing it into a file, to exercise the 
     1027            # look-for-classifier-files code 
     1028            foomfile = os.path.join(ig2.basedir, "classify_foom.py") 
     1029            f = open(foomfile, "w") 
     1030            f.write(''' 
     1031def classify_incident(nodeid_s, (header,events)): 
     1032    if "foom" in header["trigger"].get("message",""): 
     1033        return "foom" 
     1034''') 
     1035            f.close() 
    10261036            ig2.setServiceParent(self.parent) 
     1037            # now that it's been read, delete it to avoid affecting later 
     1038            # runs 
     1039            os.unlink(foomfile) 
    10271040            self.ig2 = ig2 
    10281041 
     
    11981211        self.failUnless(data['d']["failure"].check(SampleError)) 
    11991212        self.failUnless("whoops2" in str(data['d']["failure"])) 
     1213 
     1214    def test_wrongdir(self): 
     1215        basedir = "logging/Gatherer/wrongdir" 
     1216        os.makedirs(basedir) 
     1217 
     1218        # create a LogGatherer with an unspecified basedir: it should look 
     1219        # for a .tac file in the current directory, not see it, and complain 
     1220        e = self.failUnlessRaises(RuntimeError, 
     1221                                  MyGatherer, None, True, None) 
     1222        self.failUnless("running in the wrong directory" in str(e)) 
    12001223 
    12011224    def test_log_gatherer(self):