Repository: itamarst/eliot

Issue:
Let `Action.continue_task` to take `action_type` and `fields`.
I've been experimenting with capturing logs from a eliot-using service in integration tests, and want to have a more descriptive action than `eliot:remote_task` as the root action of the service.

Comments:

Patch:
diff --git a/docs/source/news.rst b/docs/source/news.rst
index eb9fb0e..b5bb22a 100644
--- a/docs/source/news.rst
+++ b/docs/source/news.rst
@@ -1,6 +1,13 @@
 What's New
 ==========
 
+Unreleased
+^^^^^^^^^^
+
+Features:
+
+* ``Action.continue_task`` now takes ``action_task`` and extra fields to use for the action, so the default ``eliot:remote_task`` can be changed.
+
 1.13.0
 ^^^^^^
 
diff --git a/eliot/_action.py b/eliot/_action.py
index 5b5b519..56d9b4f 100644
--- a/eliot/_action.py
+++ b/eliot/_action.py
@@ -236,7 +236,15 @@ class Action(object):
         ).encode("ascii")
 
     @classmethod
-    def continue_task(cls, logger=None, task_id=_TASK_ID_NOT_SUPPLIED):
+    def continue_task(
+        cls,
+        logger=None,
+        task_id=_TASK_ID_NOT_SUPPLIED,
+        *,
+        action_type="eliot:remote_task",
+        _serializers=None,
+        **fields,
+    ):
         """
         Start a new action which is part of a serialized task.
 
@@ -247,6 +255,15 @@ class Action(object):
             L{Action.serialize_task_id}, either ASCII-encoded bytes or unicode
             string. Required.
 
+        @param action_type: The type of this action,
+            e.g. C{"yourapp:subsystem:dosomething"}.
+
+        @param _serializers: Either a L{eliot._validation._ActionSerializers}
+            instance or C{None}. In the latter case no validation or serialization
+            will be done for messages generated by the L{Action}.
+
+        @param fields: Additional fields to add to the start message.
+
         @return: The new L{Action} instance.
         """
         if task_id is _TASK_ID_NOT_SUPPLIED:
@@ -255,9 +272,9 @@ class Action(object):
             task_id = task_id.decode("ascii")
         uuid, task_level = task_id.split("@")
         action = cls(
-            logger, uuid, TaskLevel.fromString(task_level), "eliot:remote_task"
+            logger, uuid, TaskLevel.fromString(task_level), action_type, _serializers
         )
-        action._start({})
+        action._start(fields)
         return action
 
     # Backwards-compat variants:


Test patch:
diff --git a/eliot/tests/test_action.py b/eliot/tests/test_action.py
index 1d6db7c..9e1d4ea 100644
--- a/eliot/tests/test_action.py
+++ b/eliot/tests/test_action.py
@@ -781,6 +781,27 @@ class SerializationTests(TestCase):
             },
         )
 
+    def test_continueTaskCustomType(self):
+        """
+        L{Action.continue_task} uses the provided action type and extra fields.
+        """
+        originalAction = Action(None, "uniq456", TaskLevel(level=[3, 4]), "mytype")
+        taskId = originalAction.serializeTaskId()
+        logger = MemoryLogger()
+
+        Action.continue_task(logger, taskId, action_type="custom:action", field="value")
+        assertContainsFields(
+            self,
+            logger.messages[0],
+            {
+                "task_uuid": "uniq456",
+                "task_level": [3, 4, 1, 1],
+                "action_type": "custom:action",
+                "action_status": "started",
+                "field": "value",
+            },
+        )
+
     def test_continueTaskNoLogger(self):
         """
         L{Action.continue_task} can be called without a logger.