Merge lp:~lifeless/launchpad/lognamer into lp:launchpad
| Status: | Merged |
|---|---|
| Approved by: | Curtis Hovey on 2010-06-30 |
| Approved revision: | no longer in the source branch. |
| Merged at revision: | 11101 |
| Proposed branch: | lp:~lifeless/launchpad/lognamer |
| Merge into: | lp:launchpad |
| Diff against target: |
1076 lines (+432/-269) 11 files modified
lib/canonical/launchpad/pagetests/standalone/xx-request-expired.txt (+2/-2) lib/canonical/launchpad/pagetests/standalone/xx-soft-timeout.txt (+2/-2) lib/canonical/launchpad/scripts/ftests/test_oops_prune.py (+5/-3) lib/canonical/launchpad/scripts/oops.py (+4/-2) lib/canonical/launchpad/webapp/errorlog.py (+40/-131) lib/canonical/launchpad/webapp/tests/test_errorlog.py (+42/-129) lib/lp/services/job/tests/test_runner.py (+1/-0) lib/lp/services/log/__init__.py (+11/-0) lib/lp/services/log/tests/__init__.py (+4/-0) lib/lp/services/log/tests/test_uniquefileallocator.py (+139/-0) lib/lp/services/log/uniquefileallocator.py (+182/-0) |
| To merge this branch: | bzr merge lp:~lifeless/launchpad/lognamer |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Curtis Hovey (community) | code | 2010-06-27 | Approve on 2010-06-30 |
|
Review via email:
|
|||
Commit Message
Factor out new lp.services.
Description of the Change
Factor out a new canonical.
This new module takes care of allocating and finding log files on disk, without
worrying about serialisation, deciding what should be in them etc.
The result is a more focused ErrorReportingU
be reused for other tasks that also want to be able to write log-like files to
unique names on disk.
I don't know if this is entirely enough to reuse this with no other glue changes, but it looks pretty good to me. And looking at the ERU I can see what it does more easily.
| Robert Collins (lifeless) wrote : | # |
Thanks for the review.
On Wed, Jun 30, 2010 at 7:55 AM, Curtis Hovey
<email address hidden> wrote:
> Review: Needs Information
> Hi Rob.
>
> Thanks for extracting this logic. I have a few comments and I am confused
> by a test change.
Cool :)
>> === added file 'lib/canonical/
>> --- lib/canonical/
>> +++ lib/canonical/
>
> webapp is deprecated. I think this would be better located at
> lib/lp/
Some similar things that might want to use this:
log / dump / debug / trace / audit
This is infrastructure for them, its about uniquely managing a set of
files on disk, in date and lexical ascending order.
So perhaps
logger/
>> +class LogNamer:
>> + """Assign unique file names to logs being written from an app/script.
>> +
>> + LogNamer causes logs written from one process to be uniquely named. It is not
>> + safe for use in multiple processes with the same output root - each process
>> + must have a unique output root.
>> + """
>
> I see trailing whitespace. Wrap the doc at 78 characters.
Sorry, editor isn't set to hunt out trailing whitespace, will fix and rewrap.
>> + def getFilename(self, log_serial, time):
>> + """Get the filename for a given log serial and time."""
>> + log_subtype = self._log_infix()
>> + output_dir = self.output_
>
> Avoid end comments. This looks like a comment rather than an XXX to denote
> tech-debt.
Ok. Gary just reminded me that you have a policy of needing a bug for
XXX, should I file one ?
>> + def newId(self, now=None):
>> + """Returns an (id, filename) pair for use by the caller.
>> +
>> + The ID is composed of a short string to identify the Launchpad instance
>> + followed by an ID that is unique for the day.
>> +
>> + The filename is composed of the zero padded second in the day
>> + followed by the ID. This ensures that reports are in date order when
>> + sorted lexically.
>> + """
>> + if now is not None:
>> + now = now.astimezone(UTC)
>> + else:
>> + now = datetime.
>> + # We look up the error directory before allocating a new ID,
>> + # because if the day has changed, errordir() will reset the ID
>> + # counter to zero.
>> + self.output_
>> + self._
>> + try:
>> + self._last_serial += 1
>> + newid = self._last_serial
>> + finally:
>> + self._
>> + subtype = self._log_infix()
>> + day_number = (now - epoch).days + 1
>> + log_id = '%s-%d%s%d' % (self._log_type, day_number, subtype, newid)
>> + filename = self.getFilenam
>> + return log_id, filename
>
> I am confused. The only changes I see in this method is prefix => infix,
> yet I can see you changed the the last test for this method to verify
> an error wa...
| Robert Collins (lifeless) wrote : | # |
I think I've done what you asked, I chose a name that made sense to me
- please have a look at the incremental diff and let me know what you
think:
=== modified file 'lib/canonical/
--- lib/canonical/
+++ lib/canonical/
@@ -38,7 +38,7 @@
soft_
from canonical.
IErrorReport, IErrorReportEvent, IErrorReportReq
-from canonical.
+from lp.services.
from canonical.
UTC = pytz.utc
@@ -253,8 +253,8 @@
if section_name is None:
- # Start a new LogNamer to activate the new configuration.
- self.log_namer = LogNamer(
+ # Start a new UniqueFileAllocator to activate the new configuration.
+ self.log_namer = UniqueFileAlloc
=== modified file 'lib/canonical/
--- lib/canonical/
01:17:40 +0000
+++ lib/canonical/
00:25:56 +0000
@@ -37,8 +37,8 @@
_is_sensitive)
from canonical.
NoReferrer
-from canonical.
from lazr.restful.
+from lp.services.
from lp.services.osutils import remove_tree
from lp.testing import TestCase
@@ -230,9 +230,9 @@
- def test_creates_
+ def test_sets_
utility = ErrorReportingU
- self.assertIsIn
+ self.assertIsIn
def test_configure(
"""Test ErrorReportingU
=== added directory 'lib/lp/
=== added file 'lib/lp/
--- lib/lp/
+++ lib/lp/
@@ -0,0 +1,11 @@
+# Copyright 2010 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""lp.services.log provides log-like facilities.
+
+Consider putting infrastructure that is used for getting logs or diagnostics
+out of Launchpad and onto some external store in here.
+
+Because this part of lp.services, packages in this namespace can only use
+general LAZR or library functionality.
+"""
=== added directory 'lib/lp/
=== added file 'lib/lp/
--- lib/lp/
| Curtis Hovey (sinzui) wrote : | # |
Thanks for the refactoring and explaining my confusion.

Hi Rob.
Thanks for extracting this logic. I have a few comments and I am confused
by a test change.
> === added file 'lib/canonical/ launchpad/ webapp/ lognamer. py' launchpad/ webapp/ lognamer. py 1970-01-01 00:00:00 +0000 launchpad/ webapp/ lognamer. py 2010-06-27 06:41:28 +0000
> --- lib/canonical/
> +++ lib/canonical/
webapp is deprecated. I think this would be better located at services/ logger/ lognamer. py, maybe logger is too broad.
lib/lp/
...
> +class LogNamer:
> + """Assign unique file names to logs being written from an app/script.
> +
> + LogNamer causes logs written from one process to be uniquely named. It is not
> + safe for use in multiple processes with the same output root - each process
> + must have a unique output root.
> + """
I see trailing whitespace. Wrap the doc at 78 characters.
...
> + def getFilename(self, log_serial, time): dir(time) #XXX locks and scans, bad.
> + """Get the filename for a given log serial and time."""
> + log_subtype = self._log_infix()
> + output_dir = self.output_
Avoid end comments. This looks like a comment rather than an XXX to denote
tech-debt.
...
> + def newId(self, now=None): datetime. now(UTC) dir(now) acquire( ) release( ) e(newid, now)
> + """Returns an (id, filename) pair for use by the caller.
> +
> + The ID is composed of a short string to identify the Launchpad instance
> + followed by an ID that is unique for the day.
> +
> + The filename is composed of the zero padded second in the day
> + followed by the ID. This ensures that reports are in date order when
> + sorted lexically.
> + """
> + if now is not None:
> + now = now.astimezone(UTC)
> + else:
> + now = datetime.
> + # We look up the error directory before allocating a new ID,
> + # because if the day has changed, errordir() will reset the ID
> + # counter to zero.
> + self.output_
> + self._lock.
> + try:
> + self._last_serial += 1
> + newid = self._last_serial
> + finally:
> + self._lock.
> + subtype = self._log_infix()
> + day_number = (now - epoch).days + 1
> + log_id = '%s-%d%s%d' % (self._log_type, day_number, subtype, newid)
> + filename = self.getFilenam
> + return log_id, filename
I am confused. The only changes I see in this method is prefix => infix,
yet I can see you changed the the last test for this method to verify
an error was raised.
Was the test wrong? Am I reading ``now.astimezon e(UTC)` ` wrong?
...
> === added file 'lib/canonical/ launchpad/ webapp/ tests/test_ lognamer. py' launchpad/ webapp/ tests/test_ lognamer. py 1970-01-01 00:00:00 +0000 launchpad/ webapp/ tests/test_ lognamer. py 2010-06-27 06:41:28 +0000 datetime( 2006, 04, 02, 00, 30, 00) es(ValueError, namer.newId, now)
> --- lib/canonical/
> +++ lib/canonical/
> ...
>
> + # Native timestamps are not permitted - UTC only.
> + now = datetime.
> + self.assertRais