Repository: honeycombio/beeline-nodejs
Pull request #217 (2020-07-08 04:27:04)

Refactor header parsers
Title sums it up! This PR does ~~three~~ two main things: 
- pulls trace header parsers into separate files
- ~~generalizes the marshal and unmarshal functions. Currently just calling the honeycomb parsers (along the lines of keeping functionality the same here)~~ specifies marshal and unmarshal functions separately for aws and honeycomb. The previous functions are still available and wrap the honeycomb functions for backwards compatibility.
- ~~adds an OTel parser for availability in a subsequent PR, definitely willing to bump this change over but I didn't want to change actual functionality in this particular merge~~ pulled this out to a separate PR


Mostly echoing the changes in this [merged PR to the golang beeline](https://github.com/honeycombio/beeline-go/pull/111/files). I even aimed to carry over the function names for consistency and easier documentation.

(don't mind the long list of commits here, I played around a lot on this first one)

Open to any thoughts/suggestions/feedback! One thing I'm majorly uncertain about is where would make the most sense to declare the trace header keys for their respective trace providers. They were previously all in the propagation.js doc that I've broken up into smaller files now. They could all go in index, they're currently declared in the relevant parser file and still exported from propagation/index.js. These currently act as exact string matches for determining which parser to use, so may be a moot point in the near future.


katiebayes: Looking much cleaner! Let me know what you think, re-requesting...

Patch:
diff --git a/lib/api/index.js b/lib/api/index.js
index f1264ce..c38cbe3 100644
--- a/lib/api/index.js
+++ b/lib/api/index.js
@@ -9,6 +9,8 @@ const path = require("path"),
   LibhoneyImpl = require("./libhoney"),
   MockImpl = require("./mock");
 
+const { honeycomb, aws } = propagation;
+
 let apiImpl;
 
 function mapFieldsToApp(map) {
@@ -49,12 +51,24 @@ module.exports = {
     return tracker.getTracked();
   },
 
-  TRACE_HTTP_HEADER: propagation.TRACE_HTTP_HEADER,
-  AMAZON_TRACE_HTTP_HEADER: propagation.AMAZON_TRACE_HTTP_HEADER,
   REQUEST_ID_HTTP_HEADER: propagation.REQUEST_ID_HTTP_HEADER,
-  marshalTraceContext: propagation.marshalTraceContext,
+  marshalTraceContext: honeycomb.marshalTraceContext,
+
+  // deprecated. Use provider-specific functions and constants
+  TRACE_HTTP_HEADER: honeycomb.TRACE_HTTP_HEADER,
+  AMAZON_TRACE_HTTP_HEADER: aws.TRACE_HTTP_HEADER,
   unmarshalTraceContext: propagation.unmarshalTraceContext,
 
+  honeycomb: {
+    TRACE_HTTP_HEADER: honeycomb.TRACE_HTTP_HEADER,
+    unmarshalTraceContext: honeycomb.unmarshalTraceContext,
+  },
+
+  aws: {
+    TRACE_HTTP_HEADER: aws.TRACE_HTTP_HEADER,
+    unmarshalTraceContext: aws.unmarshalTraceContext,
+  },
+
   startTrace(metadataContext, withTraceId, withParentSpanId, withDataset) {
     return apiImpl.startTrace(metadataContext, withTraceId, withParentSpanId, withDataset);
   },
diff --git a/lib/instrumentation/trace-util.js b/lib/instrumentation/trace-util.js
index 37c9368..e4f4f4b 100644
--- a/lib/instrumentation/trace-util.js
+++ b/lib/instrumentation/trace-util.js
@@ -21,6 +21,16 @@ const getValueFromHeaders = (requestHeaders, headers) => {
   return undefined;
 };
 
+// adds trace source field to the context and returns the updated context
+function _includeSource(context, key) {
+  if (!context) {
+    return {};
+  }
+  return Object.assign({}, context, {
+    source: `${key} http header`,
+  });
+}
+
 exports.getTraceContext = (traceIdSource, req) => {
   if (typeof traceIdSource === "undefined" || typeof traceIdSource === "string") {
     let headers =
@@ -33,52 +43,29 @@ exports.getTraceContext = (traceIdSource, req) => {
       return {};
     }
     let { value, header } = valueAndHeader;
+    let parsed = {};
 
     switch (header) {
-      case api.TRACE_HTTP_HEADER: {
-        let parsed = api.unmarshalTraceContext(value);
-        if (!parsed) {
-          return {};
-        }
-        return Object.assign({}, parsed, {
-          source: `${header} http header`,
-        });
+      //honeycomb trace header
+      case api.honeycomb.TRACE_HTTP_HEADER: {
+        header = api.honeycomb.TRACE_HTTP_HEADER;
+        parsed = api.honeycomb.unmarshalTraceContext(value);
+        return _includeSource(parsed, header);
       }
 
-      case api.AMAZON_TRACE_HTTP_HEADER: {
-        let traceId, parentSpanId;
-
-        const split = value.split(";");
-        for (const s of split) {
-          const [name, value] = s.split("=");
-          if (name === "Root") {
-            traceId = value;
-          } else if (name === "Parent") {
-            parentSpanId = value;
-          }
-        }
-
-        if (!traceId) {
-          // if we didn't even get a 'Root=' clause, bail.
-          return {};
-        }
-
-        if (!parentSpanId) {
-          parentSpanId = traceId;
-        }
-
-        return {
-          traceId,
-          parentSpanId,
-          source: `${header} http header`,
-        };
+      case api.aws.TRACE_HTTP_HEADER: {
+        header = api.aws.TRACE_HTTP_HEADER;
+        parsed = api.aws.unmarshalTraceContext(value);
+        return _includeSource(parsed, header);
       }
 
       default: {
-        return {
-          traceId: value,
-          source: `${header} http header`,
-        };
+        return _includeSource(
+          {
+            traceId: value,
+          },
+          header
+        );
       }
     }
   } else {
diff --git a/lib/propagation/aws.js b/lib/propagation/aws.js
new file mode 100644
index 0000000..6722b0c
--- /dev/null
+++ b/lib/propagation/aws.js
@@ -0,0 +1,34 @@
+/* global exports */
+const TRACE_HTTP_HEADER = "X-Amzn-Trace-Id";
+exports.TRACE_HTTP_HEADER = TRACE_HTTP_HEADER;
+
+// unmarshalTraceContext takes a string trace header and returns a context
+exports.unmarshalTraceContext = unmarshalTraceContext;
+
+function unmarshalTraceContext(header) {
+  let traceId, parentSpanId;
+
+  const split = header.split(";");
+  for (const s of split) {
+    const [name, value] = s.split("=");
+    if (name === "Root") {
+      traceId = value;
+    } else if (name === "Parent") {
+      parentSpanId = value;
+    }
+  }
+
+  if (!traceId) {
+    // if we didn't even get a 'Root=' clause, bail.
+    return;
+  }
+
+  if (!parentSpanId) {
+    parentSpanId = traceId;
+  }
+
+  return {
+    traceId,
+    parentSpanId,
+  };
+}
diff --git a/lib/propagation.js b/lib/propagation/honeycomb.js
similarity index 79%
rename from lib/propagation.js
rename to lib/propagation/honeycomb.js
index e07548a..0dd7c86 100644
--- a/lib/propagation.js
+++ b/lib/propagation/honeycomb.js
@@ -1,12 +1,11 @@
 /* global require, exports, Buffer, __dirname */
 const path = require("path"),
-  pkg = require(path.join(__dirname, "..", "package.json")),
+  pkg = require(path.join(__dirname, "..", "..", "package.json")),
   debug = require("debug")(`${pkg.name}:propagation`),
-  schema = require("./schema");
+  schema = require("../schema");
 
-exports.TRACE_HTTP_HEADER = "X-Honeycomb-Trace";
-exports.AMAZON_TRACE_HTTP_HEADER = "X-Amzn-Trace-Id";
-exports.REQUEST_ID_HTTP_HEADER = "X-Request-ID";
+const TRACE_HTTP_HEADER = "X-Honeycomb-Trace";
+exports.TRACE_HTTP_HEADER = TRACE_HTTP_HEADER;
 
 const VERSION = "1";
 exports.VERSION = VERSION;
@@ -27,8 +26,11 @@ exports.VERSION = VERSION;
 //
 // ex: X-Honeycomb-Trace: 1;trace_id=weofijwoeifj,parent_id=owefjoweifj,context=SGVsbG8gV29ybGQ=
 
-exports.marshalTraceContext = marshalTraceContextv1;
-function marshalTraceContextv1(context) {
+// marshalTraceContext takes a trace context object
+// and returns a serialized honeycomb trace header
+exports.marshalTraceContext = marshalTraceContext;
+
+function marshalTraceContext(context) {
   let traceId = context.id;
   let spanId = context.stack[context.stack.length - 1].payload[schema.TRACE_SPAN_ID];
   let contextToSend = context.traceContext || {};
@@ -44,8 +46,12 @@ function marshalTraceContextv1(context) {
   ).toString("base64")}`;
 }
 
+// unmarshalTraceContext takes a string trace header and returns a context
 exports.unmarshalTraceContext = unmarshalTraceContext;
+
 function unmarshalTraceContext(contextStr) {
+  // this trim and split just splits out the version from the remaining trace header
+  // payload is trace header minus version
   let [version, payload] = contextStr.trim().split(";");
   switch (version) {
     case "1":
@@ -101,5 +107,10 @@ function unmarshalTraceContextv1(payload) {
     }
   }
 
-  return { traceId, parentSpanId, customContext, dataset };
+  return {
+    traceId,
+    parentSpanId,
+    customContext,
+    dataset,
+  };
 }
diff --git a/lib/propagation/index.js b/lib/propagation/index.js
new file mode 100644
index 0000000..dfc467f
--- /dev/null
+++ b/lib/propagation/index.js
@@ -0,0 +1,25 @@
+/* global require, exports */
+const honeycomb = require("./honeycomb");
+exports.aws = require("./aws");
+
+exports.REQUEST_ID_HTTP_HEADER = "X-Request-ID";
+
+// unmarshalTraceContext wraps honeycomb.unmarshalTraceContext for backwards compatibility.
+
+// Deprecated: Use honeycomb.unmarshalTraceContext
+exports.unmarshalTraceContext = unmarshalTraceContext;
+
+function unmarshalTraceContext(traceHeader) {
+  return honeycomb.unmarshalTraceContext(traceHeader);
+}
+
+// marshalTraceContext wraps honeycomb.marshalTraceContext for backwards compatibility.
+
+// Deprecated: Use honeycomb.marshalTraceContext
+exports.marshalTraceContext = marshalTraceContext;
+
+function marshalTraceContext(context) {
+  return honeycomb.marshalTraceContext(context);
+}
+
+exports.honeycomb = honeycomb;
diff --git a/package-lock.json b/package-lock.json
index d139c0e..b41a1d5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -196,9 +196,9 @@
       },
       "dependencies": {
         "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "version": "1.2.5",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+          "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
           "dev": true
         }
       }
@@ -1641,9 +1641,9 @@
           "dev": true
         },
         "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+          "version": "6.0.3",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+          "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
           "dev": true
         }
       }
@@ -3299,26 +3299,6 @@
       "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
       "dev": true
     },
-    "handlebars": {
-      "version": "4.4.5",
-      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.5.tgz",
-      "integrity": "sha512-0Ce31oWVB7YidkaTq33ZxEbN+UDxMMgThvCe8ptgQViymL5DPis9uLdTA13MiRPhgvqyxIegugrP97iK3JeBHg==",
-      "dev": true,
-      "requires": {
-        "neo-async": "^2.6.0",
-        "optimist": "^0.6.1",
-        "source-map": "^0.6.1",
-        "uglify-js": "^3.1.4"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        }
-      }
-    },
     "har-schema": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@@ -3447,6 +3427,12 @@
         "whatwg-encoding": "^1.0.1"
       }
     },
+    "html-escaper": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+      "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+      "dev": true
+    },
     "http-errors": {
       "version": "1.6.3",
       "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
@@ -4217,12 +4203,12 @@
       }
     },
     "istanbul-reports": {
-      "version": "2.2.6",
-      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz",
-      "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==",
+      "version": "2.2.7",
+      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz",
+      "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==",
       "dev": true,
       "requires": {
-        "handlebars": "^4.1.2"
+        "html-escaper": "^2.0.0"
       }
     },
     "jest": {
@@ -4839,9 +4825,9 @@
       },
       "dependencies": {
         "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "version": "1.2.5",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+          "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
           "dev": true
         }
       }
@@ -5351,9 +5337,9 @@
       },
       "dependencies": {
         "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+          "version": "6.0.3",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+          "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
           "dev": true
         }
       }
@@ -5409,12 +5395,6 @@
         "brace-expansion": "^1.1.7"
       }
     },
-    "minimist": {
-      "version": "0.0.8",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
-      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
-      "dev": true
-    },
     "mixin-deep": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
@@ -5437,12 +5417,20 @@
       }
     },
     "mkdirp": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
-      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+      "version": "0.5.5",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+      "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
       "dev": true,
       "requires": {
-        "minimist": "0.0.8"
+        "minimist": "^1.2.5"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.5",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+          "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+          "dev": true
+        }
       }
     },
     "ms": {
@@ -5496,9 +5484,9 @@
           "dev": true
         },
         "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+          "version": "6.0.3",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+          "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
           "dev": true
         }
       }
@@ -5515,12 +5503,6 @@
       "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
       "dev": true
     },
-    "neo-async": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
-      "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
-      "dev": true
-    },
     "netmask": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz",
@@ -5741,16 +5723,6 @@
         "mimic-fn": "^1.0.0"
       }
     },
-    "optimist": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
-      "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
-      "dev": true,
-      "requires": {
-        "minimist": "~0.0.1",
-        "wordwrap": "~0.0.2"
-      }
-    },
     "optionator": {
       "version": "0.8.2",
       "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
@@ -6714,9 +6686,9 @@
       },
       "dependencies": {
         "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "version": "1.2.5",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+          "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
           "dev": true
         }
       }
@@ -7712,33 +7684,6 @@
         }
       }
     },
-    "uglify-js": {
-      "version": "3.6.4",
-      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.4.tgz",
-      "integrity": "sha512-9Yc2i881pF4BPGhjteCXQNaXx1DCwm3dtOyBaG2hitHjLWOczw/ki8vD1bqyT3u6K0Ms/FpCShkmfg+FtlOfYA==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "commander": "~2.20.3",
-        "source-map": "~0.6.1"
-      },
-      "dependencies": {
-        "commander": {
-          "version": "2.20.3",
-          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-          "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
-          "dev": true,
-          "optional": true
-        },
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true,
-          "optional": true
-        }
-      }
-    },
     "union-value": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
@@ -7842,9 +7787,9 @@
       },
       "dependencies": {
         "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+          "version": "6.0.3",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+          "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
           "dev": true
         }
       }
@@ -7968,12 +7913,6 @@
       "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
       "dev": true
     },
-    "wordwrap": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
-      "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
-      "dev": true
-    },
     "wrap-ansi": {
       "version": "5.1.0",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
@@ -8123,9 +8062,9 @@
       }
     },
     "yargs-parser": {
-      "version": "13.1.1",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
-      "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
+      "version": "13.1.2",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
+      "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
       "dev": true,
       "requires": {
         "camelcase": "^5.0.0",


Test patch:
diff --git a/lib/propagation.test.js b/lib/propagation/propagation.test.js
similarity index 93%
rename from lib/propagation.test.js
rename to lib/propagation/propagation.test.js
index 9357a6c..101c66e 100644
--- a/lib/propagation.test.js
+++ b/lib/propagation/propagation.test.js
@@ -1,9 +1,10 @@
 /* global require describe test expect */
-const propagation = require("./propagation"),
-  schema = require("./schema"),
-  Span = require("./api/span"),
+const propagation = require("."),
+  schema = require("../schema"),
+  Span = require("../api/span"),
   cases = require("jest-in-case");
 
+const { honeycomb } = propagation;
 // this context structure is the same as what the libhoney event api implementation generate.
 let testContext = {
   id: "abcdef123456",
@@ -19,7 +20,7 @@ let testContext = {
 describe("marshaling", () => {
   test("version string prefix", () => {
     expect(
-      propagation.marshalTraceContext(testContext).startsWith(`${propagation.VERSION};`)
+      propagation.marshalTraceContext(testContext).startsWith(`${honeycomb.VERSION};`)
     ).toBeTruthy();
   });
 });