diff --git a/src/_zkapauthorizer/eliot.py b/src/_zkapauthorizer/eliot.py index e9f4d49304300ee1be5f169f5e53ba97623b996e..26f766f552eaf5124b493f998961d96e099bc58f 100644 --- a/src/_zkapauthorizer/eliot.py +++ b/src/_zkapauthorizer/eliot.py @@ -16,7 +16,8 @@ Eliot field, message, and action definitions for ZKAPAuthorizer. """ -from eliot import ActionType, Field, MessageType +import attr +from eliot import ActionType, Field, MessageType, register_exception_extractor PRIVACYPASS_MESSAGE = Field( "message", @@ -102,3 +103,13 @@ MUTABLE_PASSES_REQUIRED = MessageType( [CURRENT_SIZES, TW_VECTORS_SUMMARY, NEW_SIZES, NEW_PASSES], "Some number of passes has been computed as the cost of updating a mutable.", ) + + +def register_attr_exception(cls): + """ + Decorator that registers the decorated attr exception class with eliot. + + The fields of the exception will be included when the exception is logged. + """ + register_exception_extractor(cls, attr.asdict) + return cls diff --git a/src/_zkapauthorizer/tests/test_eliot.py b/src/_zkapauthorizer/tests/test_eliot.py new file mode 100644 index 0000000000000000000000000000000000000000..f191b040af251e2165051009ac806f9dc783fccb --- /dev/null +++ b/src/_zkapauthorizer/tests/test_eliot.py @@ -0,0 +1,49 @@ +# Copyright PrivateStorage.io, LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Tests for eliot helpers. +""" +from __future__ import absolute_import, division, print_function, unicode_literals + +import attr +from eliot import start_action +from eliot.testing import assertHasAction +from testtools import TestCase + +from ..eliot import register_attr_exception +from .eliot import capture_logging + + +class RegisterExceptionTests(TestCase): + """ + Tests for :py:`register_attr_exception`. + """ + + @capture_logging(None) + def test_register(self, logger): + @register_attr_exception + @attr.s(auto_exc=True) + class E(Exception): + field = attr.ib() + + try: + with start_action(action_type="test:action"): + raise E(field="value") + except E: + pass + + assertHasAction( + self, logger, "test:action", False, endFields={"field": "value"} + )