| | 2 | |
|---|
| | 3 | * Release 0.3.1 (03 Sep 2008) |
|---|
| | 4 | |
|---|
| | 5 | ** Compatibility: same as 0.2.6 |
|---|
| | 6 | |
|---|
| | 7 | ** callRemote API changes: DeadReferenceError |
|---|
| | 8 | |
|---|
| | 9 | All partitioning exceptions are now mapped to DeadReferenceError. Previously |
|---|
| | 10 | there were three separate exceptions that might indicate a network partition: |
|---|
| | 11 | DeadReferenceError, ConnectionLost, and ConnectionDone. (a network partition |
|---|
| | 12 | is when one party cannot reach the other party, due to a variety of reasons: |
|---|
| | 13 | temporary network failure, the remote program being shut down, the remote |
|---|
| | 14 | host being taken offline, etc). |
|---|
| | 15 | |
|---|
| | 16 | This means that, if you want to send a message and don't care whether that |
|---|
| | 17 | message makes it to the recipient or not (but you *do* still care if the |
|---|
| | 18 | recipient raises an exception during processing of that message), you can set |
|---|
| | 19 | up the Deferred chain like this: |
|---|
| | 20 | |
|---|
| | 21 | d = rref.callRemote("message", args) |
|---|
| | 22 | d.addCallback(self.handle_response) |
|---|
| | 23 | d.addErrback(lambda f: f.trap(foolscap.DeadReferenceError)) |
|---|
| | 24 | d.addErrback(log.err) |
|---|
| | 25 | |
|---|
| | 26 | The first d.addErrback will use f.trap to catch DeadReferenceError, but will |
|---|
| | 27 | pass other exceptions through to the log.err() errback. This will cause |
|---|
| | 28 | DeadReferenceError to be ignored, but other errors to be logged. |
|---|
| | 29 | |
|---|
| | 30 | DeadReferenceError will be signalled in any of the following situations: |
|---|
| | 31 | |
|---|
| | 32 | 1: the TCP connection was lost before callRemote was invoked |
|---|
| | 33 | 2: the connection was lost after the request was sent, but before |
|---|
| | 34 | the response was received |
|---|
| | 35 | 3: when the active connection is dropped because a duplicate connection was |
|---|
| | 36 | established. This can occur when two programs are simultaneously |
|---|
| | 37 | connecting to each other. |
|---|
| | 38 | |
|---|
| | 39 | ** logging improvements |
|---|
| | 40 | |
|---|
| | 41 | *** bridge foolscap logs into twistd.log |
|---|
| | 42 | |
|---|
| | 43 | By calling foolscap.logging.log.bridgeLogsToTwisted(), or by setting the |
|---|
| | 44 | $FLOGTOTWISTED environment variable (to anything), a subset of Foolscap log |
|---|
| | 45 | events will be copied into the Twisted logging system. The default filter |
|---|
| | 46 | will not copy events below the log.OPERATIONAL level, nor will it copy |
|---|
| | 47 | internal foolscap events (i.e. those with a facility name that starts with |
|---|
| | 48 | "foolscap"). This mechanism is careful to avoid loops, so it is safe to use |
|---|
| | 49 | both bridgeLogsToTwisted() and bridgeTwistedLogs() at the same time. The |
|---|
| | 50 | events that are copied into the Twisted logging system will typically show up |
|---|
| | 51 | in the twistd.log file (for applications that are run under twistd). |
|---|
| | 52 | |
|---|
| | 53 | An alternate filter function can be passed to bridgeLogsToTwisted(). |
|---|
| | 54 | |
|---|
| | 55 | This feature provides a human-readable on-disk record of significant events, |
|---|
| | 56 | using a traditional one-line-per-event all-text sequential logging structure. |
|---|
| | 57 | It does not record parent/child relationships, structured event data, or |
|---|
| | 58 | causality information. |
|---|
| | 59 | |
|---|
| | 60 | *** Incident Gatherer improvements |
|---|
| | 61 | |
|---|
| | 62 | If an Incident occurs while a previous Incident is still being recorded (i.e. |
|---|
| | 63 | during the "trailing log period"), the two will be folded together. |
|---|
| | 64 | Specifically, the second event will not trigger a new Incident, but will be |
|---|
| | 65 | recorded in the first Incident as a normal log event. This serves to address |
|---|
| | 66 | some performance problems we've seen when incident triggers occur in |
|---|
| | 67 | clusters, which used to cause dozens of simultaneous Incident Recorders to |
|---|
| | 68 | swing into action. |
|---|
| | 69 | |
|---|
| | 70 | The Incident Gatherer has been changed to only fetch one Incident at a time |
|---|
| | 71 | (per publishing application), to avoid overloading the app with a large |
|---|
| | 72 | outbound TCP queue. |
|---|
| | 73 | |
|---|
| | 74 | The Incident Gatherer has also been changed to scan the classified/* output |
|---|
| | 75 | files and reclassify any stored incidents it has that are not mentioned in |
|---|
| | 76 | one of these files. This means that you can update the classification |
|---|
| | 77 | functions (to add a function for some previously unknown type of incident), |
|---|
| | 78 | delete the classified/unknown file, then restart the incident gatherer, and |
|---|
| | 79 | it will only reclassify the previously-unknown incidents. This makes it much |
|---|
| | 80 | easier to iteratively develop classification functions. |
|---|
| | 81 | |
|---|
| | 82 | *** Application Version data |
|---|
| | 83 | |
|---|
| | 84 | The table of application versions, previously displayed only by the 'flogtool |
|---|
| | 85 | tail' command, is now recorded in the header of both Incidents and the |
|---|
| | 86 | 'flogtool tail --save-to' output file. |
|---|
| | 87 | |
|---|
| | 88 | The API to add application versions has changed: now programs should call |
|---|
| | 89 | foolscap.logging.app_versions.add_version(name, verstr). |
|---|
| | 90 | |
|---|