Repository: honeycombio/beeline-python

Issue:
Categorize span types on send
<!---
Thank you for contributing an idea to this project!

Please see our [OSS process document](https://github.com/honeycombio/home/blob/main/honeycomb-oss-lifecycle-and-practices.md#) to get an idea of how we operate.
--->

**Is your feature request related to a problem? Please describe.**


**Describe the solution you'd like**


**Describe alternatives you've considered**


**Additional context**


Comments:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a03dbd3..47a1880 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,8 @@
 
 ### Enhancements
 
+**NOTE** If you are using the [FileTransmission](https://github.com/honeycombio/libhoney-py/blob/main/libhoney/transmission.py#L448) method and setting a false API key - and still working in Classic mode - you must update the key to be 32 characters in length to keep the same behavior.
+
 - feat: Add Environment & Services support (#213) | [@JamieDanielson](https://github.com/JamieDanielson)
 
 ## 3.2.0 2022-02-10
diff --git a/README.md b/README.md
index 87a6326..af05e2a 100644
--- a/README.md
+++ b/README.md
@@ -14,17 +14,15 @@ Currently, supports Django (>2), Flask, Bottle, and Tornado.
 
 Compatible with Python 3.
 
-## Get in touch
+## Updating to 3.3.0
 
-Please reach out to [support@honeycomb.io](mailto:support@honeycomb.io) or ping
-us with the chat bubble on [our website](https://www.honeycomb.io) for any
-assistance. We also welcome [bug reports](https://github.com/honeycombio/beeline-python/issues).
+Version 3.3.0 added support for Environment & Services, which changes sending behavior based on API Key.
+
+If you are using the [FileTransmission](https://github.com/honeycombio/libhoney-py/blob/main/libhoney/transmission.py#L448) method and setting a false API key - and still working in Classic mode - you must update the key to be 32 characters in length to keep the same behavior.
 
 ## Contributions
 
-Features, bug fixes and other changes to `beeline-python` are gladly accepted. Please
-open issues or a pull request with your change. Remember to add your name to the
-CONTRIBUTORS file!
+Features, bug fixes and other changes to `beeline-python` are gladly accepted.
 
 If you add a new test module, be sure and update `beeline.test_suite` to pick up the new tests.
 
diff --git a/beeline/trace.py b/beeline/trace.py
index 7606102..2c546e9 100644
--- a/beeline/trace.py
+++ b/beeline/trace.py
@@ -101,9 +101,9 @@ class Tracer(object):
             self._trace = Trace(generate_trace_id(), dataset)
 
         # start the root span
-        return self.start_span(context=context, parent_id=parent_span_id)
+        return self.start_span(context=context, parent_id=parent_span_id, is_root_span=True)
 
-    def start_span(self, context=None, parent_id=None):
+    def start_span(self, context=None, parent_id=None, is_root_span=False):
         if not self._trace:
             log('start_span called but no trace is active')
             return None
@@ -117,11 +117,18 @@ class Tracer(object):
         if context:
             ev.add(data=context)
 
-        ev.add(data={
+        fields = {
             'trace.trace_id': self._trace.id,
             'trace.parent_id': parent_span_id,
             'trace.span_id': span_id,
-        })
+        }
+        if is_root_span:
+            spanType = "root"
+            if parent_span_id:
+                spanType = "subroot"
+            fields['meta.span_type'] = spanType
+        ev.add(data=fields)
+
         is_root = len(self._trace.stack) == 0
         span = Span(trace_id=self._trace.id, parent_id=parent_span_id,
                     id=span_id, event=ev, is_root=is_root)


Test patch:
diff --git a/beeline/test_trace.py b/beeline/test_trace.py
index 84ef4d1..5963e44 100644
--- a/beeline/test_trace.py
+++ b/beeline/test_trace.py
@@ -178,7 +178,7 @@ class TestSynchronousTracer(unittest.TestCase):
             pass
 
         tracer.start_span.assert_called_once_with(
-            context={'name': 'foo'}, parent_id='zyxw')
+            context={'name': 'foo'}, parent_id='zyxw', is_root_span=True)
         tracer.finish_span.assert_called_once_with(mock_span)
 
     def test_trace_context_manager_starts_trace_if_trace_id_supplied(self):
@@ -210,6 +210,7 @@ class TestSynchronousTracer(unittest.TestCase):
                 'trace.trace_id': span.trace_id,
                 'trace.parent_id': span.parent_id,
                 'trace.span_id': span.id,
+                'meta.span_type': "root",
             }),
         ])
         self.assertEqual(tracer._trace.stack[0], span)
@@ -284,6 +285,7 @@ class TestSynchronousTracer(unittest.TestCase):
                 'trace.trace_id': span.trace_id,
                 'trace.parent_id': span.parent_id,
                 'trace.span_id': span.id,
+                'meta.span_type': 'subroot'
             }),
         ])
 
@@ -532,7 +534,7 @@ class TestSynchronousTracer(unittest.TestCase):
             pass
 
         tracer.start_span.assert_called_once_with(
-            context={'name': 'foo'}, parent_id=None)
+            context={'name': 'foo'}, parent_id=None, is_root_span=True)
 
     def test_trace_with_custom_dataset(self):
         dataset = 'flibble'