Skip to content

Commit

Permalink
additional transmission types (#23)
Browse files Browse the repository at this point in the history
* add mock, writer, and null transmission implementations

* convert existing tests over to using MockTransmission (by specifying "mock" for options.transmission)
  • Loading branch information
toshok committed Feb 21, 2018
1 parent 84ffd0a commit 8f07497
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 72 deletions.
46 changes: 36 additions & 10 deletions src/libhoney.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/**
* @module
*/
import { Transmission, ValidatedEvent } from './transmission';
import { Transmission, MockTransmission, WriterTransmission, NullTransmission, ValidatedEvent } from './transmission';
import Builder from './builder';

import { EventEmitter } from 'events';
Expand All @@ -18,8 +18,14 @@ const defaults = Object.freeze({
// i.e. `sampleRate: 10` means we only send 1/10th the events.
sampleRate: 1,

// transmission constructor, or a string "worker"/"base" to pick one of our builtin versions.
// transmission constructor, or a string to pick one of our builtin versions.
// we fall back to the base impl if worker or a custom implementation throws on init.
// string options available are:
// - "base": the default transmission implementation
// - "worker": a web-worker based transmission (not currently available, see https://github.com/honeycombio/libhoney-js/issues/22)
// - "mock": an implementation that accumulates all events sent
// - "writer": an implementation that logs to the console all events sent
// - "null": an implementation that does nothing
transmission: "base",

// batch triggers
Expand Down Expand Up @@ -98,6 +104,14 @@ export default class Libhoney extends EventEmitter {
this.emit("response", this._responseQueue);
}

/**
* The transmission implementation in use for this libhoney instance. Useful when mocking libhoney (specify
* "mock" for options.transmission, and use this field to get at the list of events sent through libhoney.)
*/
get transmission() {
return this._transmission;
}

/**
* The hostname for the Honeycomb API server to which to send events created through this libhoney
* instance. default: https://api.honeycomb.io/
Expand Down Expand Up @@ -387,16 +401,28 @@ function getAndInitTransmission(transmission, options) {
}

if (typeof transmission === "string") {
if (transmission === "base") {
transmission = Transmission;
} else if (transmission === "worker") {
console.warn("worker implementation not ready yet. using base implementation");
transmission = Transmission;
} else {
throw new Error(`unknown transmission implementation "${transmission}".`);
switch(transmission) {
case "base":
transmission = Transmission;
break;
case "worker":
console.warn("worker implementation not ready yet. using base implementation");
transmission = Transmission;
break;
case "mock":
transmission = MockTransmission;
break;
case "writer":
transmission = WriterTransmission;
break;
case "null":
transmission = NullTransmission;
break;
default:
throw new Error(`unknown transmission implementation "${transmission}".`);
}
} else if (typeof transmission !== "function") {
throw new Error(".transmission must be one of 'base'/'worker' or a constructor.");
throw new Error(".transmission must be one of 'base'/'worker'/'mock'/'writer'/'null' or a constructor.");
}

try {
Expand Down
38 changes: 38 additions & 0 deletions src/transmission.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,44 @@ export class ValidatedEvent {
}
}

export class MockTransmission {
constructor(options) {
this.constructorArg = options;
this.events = [];
}

sendEvent (ev) {
this.events.push(ev);
}

sendPresampledEvent (ev) {
this.events.push(ev);
}

reset() {
this.constructorArg = null;
this.events = [];
}
};

export class WriterTransmission {
sendEvent (ev) {
console.log(JSON.stringify(ev));
}

sendPresampledEvent (ev) {
console.log(JSON.stringify(ev));
}
}

export class NullTransmission {
sendEvent (ev) {
}

sendPresampledEvent (ev) {
}
}

/**
* @private
*/
Expand Down
17 changes: 10 additions & 7 deletions test/builder_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
import assert from 'assert';
import libhoney from '../lib/libhoney';

import { _transmissionSendEventArg, MockTransmission } from './mock_transmission';

describe('libhoney builder', function() {
var hny = new libhoney();

Expand Down Expand Up @@ -38,25 +36,28 @@ describe('libhoney builder', function() {
apiHost: "http://foo/bar",
writeKey: "12345",
dataset: "testing",
transmission: MockTransmission
transmission: "mock"
});
var transmission = honey.transmission;

var postData = { a: { b: 1 }, c: { d: 2 } };

var builder = honey.newBuilder({a: { b : 1 }});

builder.sendNow({ c: { d: 2 } });

assert.equal(_transmissionSendEventArg.postData, JSON.stringify(postData));
assert.equal(transmission.events.length, 1);
assert.equal(transmission.events[0].postData, JSON.stringify(postData));
});

it("includes snapshot of global fields/dyn_fields", function() {
var honey = new libhoney({
apiHost: "http://foo/bar",
writeKey: "12345",
dataset: "testing",
transmission: MockTransmission
transmission: "mock"
});
var transmission = honey.transmission;

var postData = { b : 2, c : 3 };

Expand All @@ -67,7 +68,8 @@ describe('libhoney builder', function() {

builder.sendNow({ c : 3 });

assert.equal(_transmissionSendEventArg.postData, JSON.stringify(postData));
assert.equal(transmission.events.length, 1);
assert.equal(transmission.events[0].postData, JSON.stringify(postData));

// but if we create another builder, it should show up in the post data.
postData = { a : 1, b : 2, c : 3 };
Expand All @@ -76,6 +78,7 @@ describe('libhoney builder', function() {

builder.sendNow({ c : 3 });

assert.equal(_transmissionSendEventArg.postData, JSON.stringify(postData));
assert.equal(transmission.events.length, 2);
assert.equal(transmission.events[1].postData, JSON.stringify(postData));
});
});
64 changes: 28 additions & 36 deletions test/libhoney_test.js
Original file line number Diff line number Diff line change
@@ -1,67 +1,68 @@
/* global describe, it, require, beforeEach */
/* global describe, it, require */
import assert from 'assert';
import libhoney from '../lib/libhoney';

import { _transmissionConstructorArg, _transmissionSendEventArg, MockTransmission, resetArgs } from './mock_transmission';

let superagent = require('superagent');
let mock = require('superagent-mocker')(superagent);

describe('libhoney', function() {
describe("constructor options", function() {
beforeEach(resetArgs);
it("should be communicated to transmission constructor", function() {
var options = { a: 1, b: 2, c: 3, d: 4, transmission: MockTransmission };
var options = { a: 1, b: 2, c: 3, d: 4, transmission: "mock" };

let honey = new libhoney(options);

new libhoney(options);
let transmission = honey.transmission;

assert.equal(options.a, _transmissionConstructorArg.a);
assert.equal(options.b, _transmissionConstructorArg.b);
assert.equal(options.c, _transmissionConstructorArg.c);
assert.equal(options.d, _transmissionConstructorArg.d);
assert.equal(options.a, transmission.constructorArg.a);
assert.equal(options.b, transmission.constructorArg.b);
assert.equal(options.c, transmission.constructorArg.c);
assert.equal(options.d, transmission.constructorArg.d);
});
});

describe("event properties", function() {
beforeEach(resetArgs);
it("should ultimately fallback to hardcoded defaults", function() {
var honey = new libhoney({
// these two properties are required
writeKey: "12345",
dataset: "testing",
transmission: MockTransmission
transmission: "mock"
});
let transmission = honey.transmission;
var postData = { a : 1, b : 2};
honey.sendNow(postData);

assert.equal(_transmissionSendEventArg.apiHost, "https://api.honeycomb.io/");
assert.equal(_transmissionSendEventArg.writeKey, "12345");
assert.equal(transmission.events.length, 1);
assert.equal(transmission.events[0].apiHost, "https://api.honeycomb.io/");
assert.equal(transmission.events[0].writeKey, "12345");

assert.equal(_transmissionSendEventArg.dataset, "testing");
assert.equal(_transmissionSendEventArg.sampleRate, 1);
assert(_transmissionSendEventArg.timestamp instanceof Date);
assert.equal(_transmissionSendEventArg.postData, JSON.stringify(postData));
assert.equal(transmission.events[0].dataset, "testing");
assert.equal(transmission.events[0].sampleRate, 1);
assert(transmission.events[0].timestamp instanceof Date);
assert.equal(transmission.events[0].postData, JSON.stringify(postData));
});

it("should come from libhoney options if not specified in event", function() {
var honey = new libhoney({
apiHost: "http://foo/bar",
writeKey: "12345",
dataset: "testing",
transmission: MockTransmission
transmission: "mock"
});
let transmission = honey.transmission;
var postData = { a : 1, b : 2};
honey.sendNow(postData);

assert.equal(_transmissionSendEventArg.apiHost, "http://foo/bar");
assert.equal(_transmissionSendEventArg.writeKey, "12345");
assert.equal(_transmissionSendEventArg.dataset, "testing");
assert.equal(_transmissionSendEventArg.postData, JSON.stringify(postData));
assert.equal(transmission.events.length, 1);
assert.equal(transmission.events[0].apiHost, "http://foo/bar");
assert.equal(transmission.events[0].writeKey, "12345");
assert.equal(transmission.events[0].dataset, "testing");
assert.equal(transmission.events[0].postData, JSON.stringify(postData));
});
});

describe("response queue", function() {
beforeEach(resetArgs);
it("should enqueue a maximum of maxResponseQueueSize, dropping new responses (not old)", function(done) {
mock.post('http://localhost:9999/1/events/testResponseQueue', function(req) {
return {};
Expand Down Expand Up @@ -101,26 +102,17 @@ describe('libhoney', function() {
});

describe("disabled = true", function() {
beforeEach(resetArgs);
it("should not hit transmission", function() {
var honey = new libhoney({
// these two properties are required
writeKey: "12345",
dataset: "testing",
transmission: MockTransmission,
transmission: "mock",
disabled: true
});
var transmission = honey.transmission;

var postData = { a : 1, b : 2};
honey.sendNow(postData);
assert.equal(_transmissionSendEventArg, null);

var ev = honey.newEvent();
honey.sendEvent(ev);
assert.equal(_transmissionSendEventArg, null);

honey.sendPresampledEvent(ev);
assert.equal(_transmissionSendEventArg, null);
assert.equal(transmission, null);
});
});
});
17 changes: 0 additions & 17 deletions test/mock_transmission.js

This file was deleted.

3 changes: 1 addition & 2 deletions test/transmission_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import { Transmission, ValidatedEvent } from '../lib/transmission';
let superagent = require('superagent');
let mock = require('superagent-mocker')(superagent);

describe('transmission', function() {

describe('base transmission', function() {
it('should handle batchSizeTrigger of 0', function(done) {
mock.post('http://localhost:9999/1/events/test-transmission', function(req) {
let reqEvents = JSON.parse(req.body);
Expand Down

0 comments on commit 8f07497

Please sign in to comment.