Repository: honeycombio/beeline-nodejs (js)

Issue:
sample rate not being passed with events
At the moment, we aren't sending a sampleRate in any events, even if the deterministic sampler is in use.

Should check how the go beeline is handling this and duplicate behavior.

Pull request description:
include deterministic sampler sampleRate with events
If we have a deterministic sampler configured, include its sample rate with events that we send.  also switch to using `sendPresampled` for events, instead of `send`.

fixes #95 

Patch:
diff --git a/lib/api/libhoney.js b/lib/api/libhoney.js
index fd246d8..667a446 100644
--- a/lib/api/libhoney.js
+++ b/lib/api/libhoney.js
@@ -205,7 +205,10 @@ module.exports = class LibhoneyEventAPI {
         [schema.BEELINE_VERSION]: pkg.version,
         [schema.NODE_VERSION]: process.version,
       });
-      ev.send();
+      if (this.ds) {
+        ev.sampleRate = this.ds.sampleRate;
+      }
+      ev.sendPresampled();
     });
   }
 
diff --git a/lib/deterministic_sampler.js b/lib/deterministic_sampler.js
index af12f64..fdf0106 100644
--- a/lib/deterministic_sampler.js
+++ b/lib/deterministic_sampler.js
@@ -5,6 +5,7 @@ const MAX_UINT32 = Math.pow(2, 32) - 1;
 
 module.exports = class DeterministicSampler {
   constructor(sampleRate) {
+    this.sampleRate = sampleRate;
     this.upperBound = (MAX_UINT32 / sampleRate) >>> 0;
   }
 


Test patch:
diff --git a/lib/api/index.test.js b/lib/api/index.test.js
index d580d21..9ef6562 100644
--- a/lib/api/index.test.js
+++ b/lib/api/index.test.js
@@ -52,6 +52,7 @@ test("startTrace starts tracking and creates an initial event, finishTrace sends
   let sent = honey.transmission.events[0];
   let postData = JSON.parse(sent.postData);
   expect(sent.timestamp).toEqual(new Date(startTime));
+  expect(sent.sampleRate).toBe(1);
   expect(postData[schema.EVENT_TYPE]).toBe("source");
   expect(postData[schema.TRACE_SPAN_NAME]).toBe("name");
   expect(postData[schema.TRACE_ID]).toBe(traceId);
@@ -60,6 +61,64 @@ test("startTrace starts tracking and creates an initial event, finishTrace sends
   expect(postData[schema.DURATION_MS]).not.toBeUndefined();
 });
 
+test("sample rates are propagated", () => {
+  event._resetForTesting();
+  event.configure({
+    impl: "libhoney-event",
+    transmission: "mock",
+    writeKey: "abc123",
+    sampleRate: 10,
+  });
+
+  const honey = event._apiForTesting().honey;
+  expect(tracker.getTracked()).toBeUndefined(); // context should be empty initially
+
+  let sampled = false;
+  while (!sampled) {
+    let requestPayload = event.startTrace({
+      [schema.EVENT_TYPE]: "source",
+      [schema.TRACE_SPAN_NAME]: "name",
+    });
+    if (requestPayload === null) {
+      continue;
+    }
+    sampled = true;
+
+    // starting a request creates a context
+    let context = tracker.getTracked();
+    expect(context).not.toBeUndefined();
+
+    // the stack consists solely of the request's event
+    expect(context.stack).toEqual([requestPayload]);
+    // and it should have these properties
+    expect(requestPayload[schema.EVENT_TYPE]).toBe("source");
+    let traceId = requestPayload[schema.TRACE_ID];
+    expect(traceId).not.toBeUndefined();
+    let startTime = requestPayload.startTime;
+    expect(startTime).not.toBeUndefined();
+
+    // libhoney shouldn't have been told to send anything yet
+    expect(honey.transmission.events).toEqual([]);
+
+    // finish the request
+    event.finishTrace(requestPayload);
+    expect(tracker.getTracked()).toBeUndefined(); // context should be cleared
+
+    // libhoney should have been told to send one event
+    expect(honey.transmission.events.length).toBe(1);
+    let sent = honey.transmission.events[0];
+    let postData = JSON.parse(sent.postData);
+    expect(sent.timestamp).toEqual(new Date(startTime));
+    expect(sent.sampleRate).toBe(10);
+    expect(postData[schema.EVENT_TYPE]).toBe("source");
+    expect(postData[schema.TRACE_SPAN_NAME]).toBe("name");
+    expect(postData[schema.TRACE_ID]).toBe(traceId);
+    expect(postData[schema.TRACE_PARENT_ID]).toBeUndefined();
+    expect(postData[schema.TRACE_SPAN_ID]).not.toBeUndefined();
+    expect(postData[schema.DURATION_MS]).not.toBeUndefined();
+  }
+});
+
 test("ending events out of order isn't allowed", () => {
   let requestPayload = event.startTrace({
     [schema.EVENT_TYPE]: "source",