Socket
Socket
Sign inDemoInstall

libhoney

Package Overview
Dependencies
Maintainers
2
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

libhoney - npm Package Compare versions

Comparing version 1.1.3 to 1.2.1

examples/browser/package.json

1037

dist/libhoney.cjs.js

@@ -8,2 +8,3 @@ 'use strict';

var superagent = _interopDefault(require('superagent'));
var proxy = _interopDefault(require('superagent-proxy'));
var events = require('events');

@@ -176,359 +177,5 @@

const USER_AGENT = "libhoney-js/1.2.0";
class ResourceClient {
constructor(
apiHost,
resourceEndpoint,
resourceType,
apiKey,
disabled,
datasetScoped,
userAgentAddition = ""
) {
this.apiHost = apiHost;
this.resourceEndpoint = resourceEndpoint;
this.resourceType = resourceType;
this.apiKey = apiKey;
this.disabled = disabled;
this.datasetScoped = datasetScoped;
let userAgent = USER_AGENT;
let trimmedAddition = userAgentAddition.trim();
if (trimmedAddition) {
userAgent = `${USER_AGENT} ${trimmedAddition}`;
}
this.userAgent = userAgent;
}
newRequest(method, id = "", datasetName) {
let url$$1;
if (this.datasetScoped) {
url$$1 = urljoin(this.apiHost, this.resourceEndpoint, datasetName, id);
} else {
url$$1 = urljoin(this.apiHost, this.resourceEndpoint, id);
}
return superagent[method](url$$1)
.set("X-Hny-Team", this.apiKey)
.set("User-Agent", this.userAgent)
.type("json");
}
create(resource, datasetName) {
if (this.datasetScoped && !datasetName) {
throw new Error(
`a datasetName is required to create a ${this.resourceType.name}`
);
} else if (!this.datasetScoped && datasetName) {
throw new Error(
`a datasetName cannot be used to create a ${this.resourceType.name}`
);
}
return new Promise((resolve, reject) => {
this.newRequest("post", undefined, datasetName)
.send(resource)
.end((err, res) => {
// more here
if (err) {
reject(err);
return;
}
resolve(this.resourceType.fromJSON(res.body));
});
});
}
get(id, datasetName) {
if (this.datasetScoped && !datasetName) {
throw new Error(
`a datasetName is required to fetch a ${this.resourceType.name}`
);
} else if (!this.datasetScoped && datasetName) {
throw new Error(
`a datasetName cannot be used to fetch a ${this.resourceType.name}`
);
}
return new Promise((resolve, reject) => {
this.newRequest("get", id, datasetName)
.send()
.end((err, res) => {
// more here
if (err) {
reject(err);
return;
}
resolve(this.resourceType.fromJSON(res.body));
});
});
}
delete(id, datasetName) {
if (this.datasetScoped && !datasetName) {
throw new Error(
`a datasetName is required to delete a ${this.resourceType.name}`
);
} else if (!this.datasetScoped && datasetName) {
throw new Error(
`a datasetName cannot be used to delete a ${this.resourceType.name}`
);
}
return new Promise((resolve, reject) => {
this.newRequest("delete", id, datasetName)
.send()
.end(err => {
// more here?
if (err) {
reject(err);
return;
}
resolve();
});
});
}
update(resource, datasetName) {
if (this.datasetScoped && !datasetName) {
throw new Error(
`a datasetName is required to update a ${this.resourceType.name}`
);
} else if (!this.datasetScoped && datasetName) {
throw new Error(
`a datasetName cannot be used to update a ${this.resourceType.name}`
);
}
return new Promise((resolve, reject) => {
this.newRequest("put", resource.id, datasetName)
.send(resource)
.end((err, res) => {
// more here
if (err) {
reject(err);
return;
}
resolve(this.resourceType.fromJSON(res.body));
});
});
}
list(datasetName) {
if (this.datasetScoped && !datasetName) {
throw new Error(
`a datasetName is required to list ${this.resourceType.name}s`
);
} else if (!this.datasetScoped && datasetName) {
throw new Error(
`a datasetName cannot be used to list ${this.resourceType.name}s`
);
}
return new Promise((resolve, reject) => {
this.newRequest("get", undefined, datasetName)
.send()
.end((err, res) => {
if (err) {
reject(err);
return;
}
resolve((res.body || []).map(r => this.resourceType.fromJSON(r)));
});
});
}
}
/* notyet
const validFilterOps = {
"=": true,
"!=": true,
">": true,
">=": true,
"<": true,
"<=": true,
"starts-with": true,
"does-not-start-with": true,
exists: true,
"does-not-exist": true,
contains: true,
"does-not-contain": true
};
*/
const validCalculateOps = {
NONE: true,
COUNT: true,
SUM: true,
AVG: true,
COUNT_DISTINCT: true,
MAX: true,
MIN: true,
P001: true,
P01: true,
P05: true,
P10: true,
P25: true,
P50: true,
P75: true,
P90: true,
P95: true,
P99: true,
P999: true,
HEATMAP: true
};
class Calculation {
constructor(column, op) {
this.column = column;
this.op = op;
if (this.op === "COUNT") {
this.column = "*";
}
}
static fromJSON(c) {
return new Calculation(c.column, c.op);
}
}
Object.keys(validCalculateOps).forEach(op => {
});
class Filter {
constructor(column, op, value) {
this.column = column;
this.op = op;
this.value = value;
}
static fromJSON(f) {
return new Filter(f.column, f.op, f.value);
}
}
class Order {
constructor(column, op, order = "ascending") {
this.column = column;
this.op = op;
this.order = order;
if (this.op === "COUNT") {
this.column = "*";
}
}
ascending() {
this.order = "ascending";
return this;
}
descending() {
this.order = "descending";
return this;
}
static fromJSON(o) {
return new Order(o.column, o.op, o.order);
}
}
Object.keys(validCalculateOps).forEach(op => {
});
class Query {
constructor(
breakdowns = [],
calculations = [],
filters = [],
filterCombination,
orders = [],
limit,
startTime,
endTime,
timeRange,
granularity
) {
this.breakdowns = breakdowns;
this.calculations = calculations;
this.filters = filters;
this.filterCombination = filterCombination;
this.orders = orders;
this.limit = limit;
this.startTime = startTime;
this.endTime = endTime;
this.timeRange = timeRange;
this.granularity = granularity;
}
static fromJSON(q) {
if (typeof q === "undefined") {
return q;
}
return new Query(
q.breakdowns || [],
(q.calculations || []).map(c => Calculation.fromJSON(c)),
(q.filter || []).map(f => Filter.fromJSON(f)),
q.filterCombination,
(q.orders || []).map(o => Order.fromJSON(o)),
q.limit,
q.startTime,
q.endTime,
q.timeRange,
q.granularity
);
}
}
class BoardQuery {
constructor(name, description, dataset, query$$1) {
this.name = name;
this.description = description;
this.dataset = dataset;
this.query = query$$1;
}
static fromJSON(bq) {
if (typeof bq === "undefined") {
return bq;
}
return new BoardQuery(
bq.name,
bq.description,
bq.dataset,
Query.fromJSON(bq.query)
);
}
}
class Board {
constructor(name, description, queries, id) {
this.name = name;
this.description = description;
this.queries = queries;
this.id = id;
}
static fromJSON(b) {
return new Board(
b.name,
b.description,
(b.queries || []).map(bq => BoardQuery.fromJSON(bq)),
b.id
);
}
}
const ENDPOINT = "/1/boards";
class Client extends ResourceClient {
constructor({ apiHost, apiKey, disabled, userAgentAddition }) {
super(
apiHost,
ENDPOINT,
Board,
apiKey,
disabled,
false /* not dataset scoped */,
userAgentAddition
);
}
}
// Copyright 2016 Hound Technology, Inc. All rights reserved.
const USER_AGENT$1 = "libhoney-js/1.2.0";
const USER_AGENT = "libhoney-js/1.2.0";

@@ -579,7 +226,7 @@ const _global =

/* keyfn */
ev => `${ev.apiHost}_${ev.apiKey}_${ev.dataset}`,
ev => `${ev.apiHost}_${ev.writeKey}_${ev.dataset}`,
/* createfn */
ev => ({
apiHost: ev.apiHost,
apiKey: ev.apiKey,
writeKey: ev.writeKey,
dataset: ev.dataset,

@@ -622,3 +269,3 @@ events: [ev]

postData,
apiKey,
writeKey,
dataset,

@@ -631,3 +278,3 @@ sampleRate,

this.postData = postData;
this.apiKey = apiKey;
this.writeKey = writeKey;
this.dataset = dataset;

@@ -720,2 +367,3 @@ this.sampleRate = sampleRate;

this._userAgentAddition = options.userAgentAddition || "";
this._proxy = options.proxy;

@@ -770,3 +418,3 @@ // Included for testing; to stub out randomness and verify that an event

let batch = this._eventQueue.splice(0, this._batchSizeTrigger);
var batch = this._eventQueue.splice(0, this._batchSizeTrigger);

@@ -790,4 +438,7 @@ let batchAgg = new BatchEndpointAggregator(batch);

eachPromise(batches, batch => {
let url$$1 = urljoin(batch.apiHost, "/1/batch", batch.dataset);
let req = superagent.post(url$$1);
var url$$1 = urljoin(batch.apiHost, "/1/batch", batch.dataset);
var req = superagent.post(url$$1);
if (this._proxy) {
req = proxy(req, this._proxy);
}

@@ -808,11 +459,11 @@ let { encoded, numEncoded } = batchAgg.encodeBatchEvents(batch.events);

let userAgent = USER_AGENT$1;
let userAgent = USER_AGENT;
let trimmedAddition = this._userAgentAddition.trim();
if (trimmedAddition) {
userAgent = `${USER_AGENT$1} ${trimmedAddition}`;
userAgent = `${USER_AGENT} ${trimmedAddition}`;
}
let start = Date.now();
var start = Date.now();
req
.set("X-Hny-Team", batch.apiKey)
.set("X-Hny-Team", batch.writeKey)
.set("User-Agent", userAgent)

@@ -867,3 +518,3 @@ .type("json")

_shouldSendEvent(ev) {
let { sampleRate } = ev;
var { sampleRate } = ev;
if (sampleRate <= 1) {

@@ -935,3 +586,3 @@ return true;

/**
* The Honeycomb authentication token for this event. Find you team api key at
* The Honeycomb authentication token for this event. Find your team write key at
* https://ui.honeycomb.io/account

@@ -941,3 +592,3 @@ *

*/
this.apiKey = "";
this.writeKey = "";
/**

@@ -1064,8 +715,8 @@ * The name of the Honeycomb dataset to which to send this event.

* The Honeycomb authentication token. If it is set on a libhoney instance it will be used as the
* default api key for all events. If absent, it must be explicitly set on a Builder or
* Event. Find your team api key at https://ui.honeycomb.io/account
* default write key for all events. If absent, it must be explicitly set on a Builder or
* Event. Find your team write key at https://ui.honeycomb.io/account
*
* @type {string}
*/
this.apiKey = "";
this.writeKey = "";
/**

@@ -1096,4 +747,4 @@ * The name of the Honeycomb dataset to which to send these events. If it is specified during

* @example <caption>using an object</caption>
* let honey = new libhoney();
* let builder = honey.newBuilder();
* var honey = new libhoney();
* var builder = honey.newBuilder();
* builder.add ({

@@ -1153,3 +804,3 @@ * component: "web",

sendNow(data) {
let ev = this.newEvent();
var ev = this.newEvent();
ev.add(data);

@@ -1168,5 +819,5 @@ ev.send();

newEvent() {
let ev = new Event(this._libhoney, this._fields, this._dyn_fields);
var ev = new Event(this._libhoney, this._fields, this._dyn_fields);
ev.apiHost = this.apiHost;
ev.apiKey = this.apiKey;
ev.writeKey = this.writeKey;
ev.dataset = this.dataset;

@@ -1185,8 +836,9 @@ ev.sampleRate = this.sampleRate;

* @example <caption>additional fields/dyn_field</caption>
* let anotherBuilder = builder.newBuilder({ requestId }, {
* process_heapUsed: () => process.memoryUsage().heapUsed
* });
* let anotherBuilder = builder.newBuilder({ requestId },
* {
* process_heapUsed: () => process.memoryUsage().heapUsed
* });
*/
newBuilder(fields, dyn_fields) {
let b = new Builder(this._libhoney, this._fields, this._dyn_fields);
var b = new Builder(this._libhoney, this._fields, this._dyn_fields);

@@ -1197,3 +849,3 @@ foreach(fields, (v, k) => b.addField(k, v));

b.apiHost = this.apiHost;
b.apiKey = this.apiKey;
b.writeKey = this.writeKey;
b.dataset = this.dataset;

@@ -1206,11 +858,85 @@ b.sampleRate = this.sampleRate;

class Client$1 extends events.EventEmitter {
constructor(options) {
// Copyright 2016 Hound Technology, Inc. All rights reserved.
const defaults = Object.freeze({
apiHost: "https://api.honeycomb.io/",
// http
proxy: undefined,
// sample rate of data. causes us to send 1/sample-rate of events
// i.e. `sampleRate: 10` means we only send 1/10th the events.
sampleRate: 1,
// 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
batchSizeTrigger: 50, // we send a batch to the api when we have this many outstanding events
batchTimeTrigger: 100, // ... or after this many ms has passed.
// batches are sent serially (one event at a time), so we allow multiple concurrent batches
// to increase parallelism while sending.
maxConcurrentBatches: 10,
// the maximum number of pending events we allow in our to-be-batched-and-transmitted queue before dropping them.
pendingWorkCapacity: 10000,
// the maximum number of responses we enqueue before we begin dropping them.
maxResponseQueueSize: 1000,
// if this is set to true, all sending is disabled. useful for disabling libhoney when testing
disabled: false,
// If this is non-empty, append it to the end of the User-Agent header.
userAgentAddition: ""
});
/**
* libhoney aims to make it as easy as possible to create events and send them on into Honeycomb.
*
* See https://honeycomb.io/docs for background on this library.
* @class
*/
class Libhoney extends events.EventEmitter {
/**
* Constructs a libhoney context in order to configure default behavior,
* though each of its members (`apiHost`, `writeKey`, `dataset`, and
* `sampleRate`) may in fact be overridden on a specific Builder or Event.
*
* @param {Object} [opts] overrides for the defaults
* @param {string} [opts.apiHost=https://api.honeycomb.io] - Server host to receive Honeycomb events.
* @param {string} opts.proxy - The proxy to send events through.
* @param {string} opts.writeKey - Write key for your Honeycomb team. (Required)
* @param {string} opts.dataset - Name of the dataset that should contain this event. The dataset will be created for your team if it doesn't already exist.
* @param {number} [opts.sampleRate=1] - Sample rate of data. If set, causes us to send 1/sampleRate of events and drop the rest.
* @param {number} [opts.batchSizeTrigger=50] - We send a batch to the API when this many outstanding events exist in our event queue.
* @param {number} [opts.batchTimeTrigger=100] - We send a batch to the API after this many milliseconds have passed.
* @param {number} [opts.maxConcurrentBatches=10] - We process batches concurrently to increase parallelism while sending.
* @param {number} [opts.pendingWorkCapacity=10000] - The maximum number of pending events we allow to accumulate in our sending queue before dropping them.
* @param {number} [opts.maxResponseQueueSize=1000] - The maximum number of responses we enqueue before dropping them.
* @param {boolean} [opts.disabled=false] - Disable transmission of events to the specified `apiHost`, particularly useful for testing or development.
* @constructor
* @example
* import Libhoney from 'libhoney';
* let honey = new Libhoney({
* writeKey: "YOUR_WRITE_KEY",
* dataset: "honeycomb-js-example",
* // disabled: true // uncomment when testing or in development
* });
*/
constructor(opts) {
super();
this._options = Object.assign(
{ responseCallback: this._responseCallback.bind(this) },
options
defaults,
opts
);
this._transmission = getAndInitTransmission(

@@ -1223,8 +949,6 @@ this._options.transmission,

Object.assign(this._builder, {
apiHost: this._options.apiHost,
apiKey: this._options.apiKey,
dataset: this._options.dataset,
sampleRate: this._options.sampleRate
});
this._builder.apiHost = this._options.apiHost;
this._builder.writeKey = this._options.writeKey;
this._builder.dataset = this._options.dataset;
this._builder.sampleRate = this._options.sampleRate;

@@ -1242,6 +966,25 @@ 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/
*
* @type {string}
*/
set apiHost(v) {
this._builder.apiHost = v;
}
/**
* The hostname for the Honeycomb API server to which to send events created through this libhoney
* instance. default: https://api.honeycomb.io/
*
* @type {string}
*/
get apiHost() {

@@ -1251,16 +994,21 @@ return this._builder.apiHost;

set apiKey(v) {
this._builder.apiKey = v;
/**
* The Honeycomb authentication token. If it is set on a libhoney instance it will be used as the
* default write key for all events. If absent, it must be explicitly set on a Builder or
* Event. Find your team write key at https://ui.honeycomb.io/account
*
* @type {string}
*/
set writeKey(v) {
this._builder.writeKey = v;
}
get apiKey() {
return this._builder.apiKey;
}
/**
* 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.)
* The Honeycomb authentication token. If it is set on a libhoney instance it will be used as the
* default write key for all events. If absent, it must be explicitly set on a Builder or
* Event. Find your team write key at https://ui.honeycomb.io/account
*
* @type {string}
*/
get transmission() {
return this._transmission;
get writeKey() {
return this._builder.writeKey;
}

@@ -1314,3 +1062,3 @@

* timestamp [optional]: time for this event, defaults to now()
* apiKey [optional]: your team's api key. overrides the libhoney instance's value.
* writeKey [optional]: your team's write key. overrides the libhoney instance's value.
* dataset [optional]: the data set name. overrides the libhoney instance's value.

@@ -1339,3 +1087,3 @@ * sampleRate [optional]: cause us to send 1 out of sampleRate events. overrides the libhoney instance's value.

* timestamp [optional]: time for this event, defaults to now()
* apiKey [optional]: your team's api key. overrides the libhoney instance's value.
* writeKey [optional]: your team's write key. overrides the libhoney instance's value.
* dataset [optional]: the data set name. overrides the libhoney instance's value.

@@ -1368,3 +1116,3 @@ * sampleRate: the rate this event has already been sampled.

let timestamp = event.timestamp || Date.now();
var timestamp = event.timestamp || Date.now();
if (typeof timestamp === "string" || typeof timestamp === "number")

@@ -1377,3 +1125,3 @@ timestamp = new Date(timestamp);

}
let postData;
var postData;
try {

@@ -1386,3 +1134,3 @@ postData = JSON.stringify(event.data);

let apiHost = event.apiHost;
var apiHost = event.apiHost;
if (typeof apiHost !== "string" || apiHost === "") {

@@ -1393,9 +1141,9 @@ console.error(".apiHost must be a non-empty string");

let apiKey = event.apiKey;
if (typeof apiKey !== "string" || apiKey === "") {
console.error(".apiKey must be a non-empty string");
var writeKey = event.writeKey;
if (typeof writeKey !== "string" || writeKey === "") {
console.error(".writeKey must be a non-empty string");
return null;
}
let dataset = event.dataset;
var dataset = event.dataset;
if (typeof dataset !== "string" || dataset === "") {

@@ -1406,3 +1154,3 @@ console.error(".dataset must be a non-empty string");

let sampleRate = event.sampleRate;
var sampleRate = event.sampleRate;
if (typeof sampleRate !== "number") {

@@ -1413,3 +1161,3 @@ console.error(".sampleRate must be a number");

let metadata = event.metadata;
var metadata = event.metadata;
return new ValidatedEvent({

@@ -1419,3 +1167,3 @@ timestamp,

postData,
apiKey,
writeKey,
dataset,

@@ -1583,448 +1331,2 @@ sampleRate,

class Marker {
constructor(message, type, url$$1) {
this.message = message;
this.type = type;
this.url = url$$1;
}
static fromJSON(m) {
return new Marker(m.message, m.type, m.url);
}
}
const ENDPOINT$1 = "/1/markers";
class Client$2 extends ResourceClient {
constructor({ apiHost, apiKey, disabled, userAgentAddition }) {
super(
apiHost,
ENDPOINT$1,
Marker,
apiKey,
disabled,
true /* dataset scoped */,
userAgentAddition
);
}
}
class Trigger {
constructor(name, description, frequency, query$$1, threshold, recipients, id) {
this.name = name;
this.description = description;
this.frequency = frequency;
this.query = query$$1;
this.threshold = threshold;
this.recipients = recipients;
this.id = id;
}
static fromJSON(t) {
if (typeof t === "undefined") {
return t;
}
return new Trigger(
t.name,
t.description,
t.frequency,
Query.fromJSON(t.query),
Threshold.fromJSON(t.threshold),
(t.recipients || []).map(r => Recipient.fromJSON(r)),
t.id
);
}
}
class Threshold {
constructor(op, value) {
this.op = op;
this.value = value;
}
static fromJSON(t) {
if (typeof t === "undefined") {
return t;
}
return new Threshold(t.op, t.value);
}
}
class Recipient {
constructor(type, target) {
this.type = type;
this.target = target;
}
static fromJSON(r) {
if (typeof r === "undefined") {
return r;
}
return new Recipient(r.type, r.target);
}
}
const ENDPOINT$2 = "/1/triggers";
class Client$3 extends ResourceClient {
constructor({ apiHost, apiKey, disabled, userAgentAddition }) {
super(
apiHost,
ENDPOINT$2,
Trigger,
apiKey,
disabled,
true /* dataset scoped */,
userAgentAddition
);
}
}
// Copyright 2016 Hound Technology, Inc. All rights reserved.
const defaults = Object.freeze({
apiHost: "https://api.honeycomb.io/",
// sample rate of data. causes us to send 1/sample-rate of events
// i.e. `sampleRate: 10` means we only send 1/10th the events.
sampleRate: 1,
// 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
batchSizeTrigger: 50, // we send a batch to the api when we have this many outstanding events
batchTimeTrigger: 100, // ... or after this many ms has passed.
// batches are sent serially (one event at a time), so we allow multiple concurrent batches
// to increase parallelism while sending.
maxConcurrentBatches: 10,
// the maximum number of pending events we allow in our to-be-batched-and-transmitted queue before dropping them.
pendingWorkCapacity: 10000,
// the maximum number of responses we enqueue before we begin dropping them.
maxResponseQueueSize: 1000,
// if this is set to true, all sending is disabled. useful for disabling libhoney when testing
disabled: false,
// If this is non-empty, append it to the end of the User-Agent header.
userAgentAddition: ""
});
/**
* libhoney aims to make it as easy as possible to create events and send them on into Honeycomb.
*
* See https://honeycomb.io/docs for background on this library.
* @class
*/
class Libhoney {
/**
* Constructs a libhoney context in order to configure default behavior,
* though each of its members (`apiHost`, `apiKey`, `dataset`, and
* `sampleRate`) may in fact be overridden on a specific Builder or Event.
*
* @param {Object} [opts] overrides for the defaults
* @param {string} [opts.apiHost=https://api.honeycomb.io] - Server host to receive Honeycomb events.
* @param {string} opts.apiKey - API key for your Honeycomb team. (Required)
* @param {string} opts.writeKey - (deprecated) API key for your Honeycomb team.
* @param {string} opts.dataset - For dataset scoped clients (events, markers), the name of the dataset that should contain the resource. If sending events, the dataset will be created if not present.
* @param {number} [opts.sampleRate=1] - Sample rate of data. If set, causes us to send 1/sampleRate of events and drop the rest.
* @param {number} [opts.batchSizeTrigger=50] - We send a batch to the API when this many outstanding events exist in our event queue.
* @param {number} [opts.batchTimeTrigger=100] - We send a batch to the API after this many milliseconds have passed.
* @param {number} [opts.maxConcurrentBatches=10] - We process batches concurrently to increase parallelism while sending.
* @param {number} [opts.pendingWorkCapacity=10000] - The maximum number of pending events we allow to accumulate in our sending queue before dropping them.
* @param {number} [opts.maxResponseQueueSize=1000] - The maximum number of responses we enqueue before dropping them.
* @param {boolean} [opts.disabled=false] - Disable communication to the specified `apiHost`, particularly useful for testing or development.
* @constructor
* @example
* import Libhoney from 'libhoney';
* let honey = new Libhoney({
* apiKey: "YOUR_API_KEY",
* dataset: "honeycomb-js-example",
* // disabled: true // uncomment when testing or in development
* });
*/
constructor(opts) {
this._options = Object.assign({}, defaults, opts);
if (this._options.writeKey && typeof this._options.apiKey === "undefined") {
// fall back to writeKey if apiKey isn't present
this._options.apiKey = this._options.writeKey;
}
}
/**
* The hostname for the Honeycomb API server to which to send events created through this libhoney
* instance. default: https://api.honeycomb.io/
*
* @type {string}
*/
set apiHost(v) {
this._options.apiHost = v;
// update all the clients
if (this._boards) {
this._boards.apiHost = v;
}
if (this._events) {
this._events.apiHost = v;
}
if (this._markers) {
this._markers.apiHost = v;
}
if (this._triggers) {
this._triggers.apiHost = v;
}
}
/**
* The hostname for the Honeycomb API server to which to send events created through this libhoney
* instance. default: https://api.honeycomb.io/
*
* @type {string}
*/
get apiHost() {
return this._options.apiHost;
}
/**
* The Honeycomb authentication token. If it is set on a libhoney instance it will be used as the
* default api key for all events. If absent, it must be explicitly set on a Builder or
* Event. Find your team api key at https://ui.honeycomb.io/account
*
* @type {string}
*/
set apiKey(v) {
this._options.apiKey = v;
// update all the clients
if (this._boards) {
this._boards.apiKey = v;
}
if (this._events) {
this._events.apiKey = v;
}
if (this._markers) {
this._markers.apiKey = v;
}
if (this._triggers) {
this._triggers.apiKey = v;
}
}
/**
* The Honeycomb authentication token. If it is set on a libhoney instance it will be used as the
* default api key for all events. If absent, it must be explicitly set on a Builder or
* Event. Find your team api key at https://ui.honeycomb.io/account
*
* @type {string}
*/
get apiKey() {
return this.options._apiKey;
}
get boards() {
if (!this._boards) {
this._boards = new Client(this._options);
}
return this._boards;
}
get events() {
if (!this._events) {
this._events = new Client$1(this._options);
}
return this._events;
}
get markers() {
if (!this._markers) {
this._markers = new Client$2(this._options);
}
return this._markers;
}
get triggers() {
if (!this._triggers) {
this._triggers = new Client$3(this._options);
}
return this._triggers;
}
// deprecated writeKey accessors. will go away with the next major version bump
set writeKey(v) {
this.apiKey = v;
}
get writeKey() {
return this.apiKey;
}
// proxies for the events client. these _may_ go away in a future major release.
/**
* The rate at which to sample events. Default is 1, meaning no sampling. If you want to send one
* event out of every 250 times send() is called, you would specify 250 here.
*
* @type {number}
*/
set sampleRate(v) {
this.events.sampleRate = v;
}
/**
* The rate at which to sample events. Default is 1, meaning no sampling. If you want to send one
* event out of every 250 times send() is called, you would specify 250 here.
*
* @type {number}
*/
get sampleRate() {
return this.events.sampleRate;
}
/**
* sendEvent takes events of the following form:
*
* {
* data: a JSON-serializable object, keys become colums in Honeycomb
* timestamp [optional]: time for this event, defaults to now()
* writeKey [optional]: your team's write key. overrides the libhoney instance's value.
* dataset [optional]: the data set name. overrides the libhoney instance's value.
* sampleRate [optional]: cause us to send 1 out of sampleRate events. overrides the libhoney instance's value.
* }
*
* Sampling is done based on the supplied sampleRate, so events passed to this method might not
* actually be sent to Honeycomb.
* @private
*/
sendEvent(event) {
return this.events.sendEvent(event);
}
/**
* sendPresampledEvent takes events of the following form:
*
* {
* data: a JSON-serializable object, keys become colums in Honeycomb
* timestamp [optional]: time for this event, defaults to now()
* writeKey [optional]: your team's write key. overrides the libhoney instance's value.
* dataset [optional]: the data set name. overrides the libhoney instance's value.
* sampleRate: the rate this event has already been sampled.
* }
*
* Sampling is presumed to have already been done (at the supplied sampledRate), so all events passed to this method
* are sent to Honeycomb.
* @private
*/
sendPresampledEvent(event) {
return this.events.sendPresampledEvent(event);
}
/**
* validateEvent takes an event and validates its structure and contents.
*
* @returns {Object} the validated libhoney Event. May return undefined if
* the event was invalid in some way or unable to be sent.
* @private
*/
validateEvent(event) {
return this.events.validateEvent(event);
}
/**
* adds a group of field->values to the global Builder.
* @param {Object|Map<string, any>} data field->value mapping.
* @returns {Libhoney} this libhoney instance.
* @example <caption>using an object</caption>
* honey.add ({
* buildID: "a6cc38a1",
* env: "staging"
* });
* @example <caption>using an ES2015 map</caption>
* let map = new Map();
* map.set("build_id", "a6cc38a1");
* map.set("env", "staging");
* honey.add (map);
*/
add(data) {
return this.events.add(data);
}
/**
* adds a single field->value mapping to the global Builder.
* @param {string} name name of field to add.
* @param {any} val value of field to add.
* @returns {Libhoney} this libhoney instance.
* @example
* honey.addField("build_id", "a6cc38a1");
*/
addField(name, val) {
return this.events.addField(name, val);
}
/**
* adds a single field->dynamic value function to the global Builder.
* @param {string} name name of field to add.
* @param {function(): any} fn function that will be called to generate the value whenever an event is created.
* @returns {Libhoney} this libhoney instance.
* @example
* honey.addDynamicField("process_heapUsed", () => process.memoryUsage().heapUsed);
*/
addDynamicField(name, fn) {
return this.events.addDynamicField(name, fn);
}
/**
* creates and sends an event, including all global builder fields/dyn_fields, as well as anything in the optional data parameter.
* @param {Object|Map<string, any>} data field->value mapping.
* @example <caption>using an object</caption>
* honey.sendNow ({
* responseTime_ms: 100,
* httpStatusCode: 200
* });
* @example <caption>using an ES2015 map</caption>
* let map = new Map();
* map.set("responseTime_ms", 100);
* map.set("httpStatusCode", 200);
* honey.sendNow (map);
*/
sendNow(data) {
return this.events.sendNow(data);
}
/**
* creates and returns a new Event containing all fields/dyn_fields from the global Builder, that can be further fleshed out and sent on its own.
* @returns {Event} an Event instance
* @example <caption>adding data at send-time</caption>
* let ev = honey.newEvent();
* ev.addField("additionalField", value);
* ev.send();
*/
newEvent() {
return this.events.newEvent();
}
/**
* creates and returns a clone of the global Builder, merged with fields and dyn_fields passed as arguments.
* @param {Object|Map<string, any>} fields a field->value mapping to merge into the new builder.
* @param {Object|Map<string, any>} dyn_fields a field->dynamic function mapping to merge into the new builder.
* @returns {Builder} a Builder instance
* @example <caption>no additional fields/dyn_field</caption>
* let builder = honey.newBuilder();
* @example <caption>additional fields/dyn_field</caption>
* let builder = honey.newBuilder({ requestId },
* {
* process_heapUsed: () => process.memoryUsage().heapUsed
* });
*/
newBuilder(fields, dyn_fields) {
return this.events.newBuilder(fields, dyn_fields);
}
}
// this will absolutely go away with the next major version bump. right now in normal node (CJS) usage,

@@ -2039,11 +1341,2 @@ // users have to do: `let Libhoney = require("libhoney").default;`

// this will absolutely go away with the next major version bump. right now in normal node (CJS) usage,
// users have to do: `let Libhoney = require("libhoney").default;`
//
// switching to rollup fixes that (yay!) but we need to keep it working until we do the major bump. hence
// this hack.
if (typeof module !== "undefined") {
Object.defineProperty(Libhoney, "default", { value: Libhoney });
}
module.exports = Libhoney;
import url from 'url';
import path from 'path';
import superagent from 'superagent';
import proxy from 'superagent-proxy';
import { EventEmitter } from 'events';

@@ -171,359 +172,5 @@

const USER_AGENT = "libhoney-js/1.2.0";
class ResourceClient {
constructor(
apiHost,
resourceEndpoint,
resourceType,
apiKey,
disabled,
datasetScoped,
userAgentAddition = ""
) {
this.apiHost = apiHost;
this.resourceEndpoint = resourceEndpoint;
this.resourceType = resourceType;
this.apiKey = apiKey;
this.disabled = disabled;
this.datasetScoped = datasetScoped;
let userAgent = USER_AGENT;
let trimmedAddition = userAgentAddition.trim();
if (trimmedAddition) {
userAgent = `${USER_AGENT} ${trimmedAddition}`;
}
this.userAgent = userAgent;
}
newRequest(method, id = "", datasetName) {
let url$$1;
if (this.datasetScoped) {
url$$1 = urljoin(this.apiHost, this.resourceEndpoint, datasetName, id);
} else {
url$$1 = urljoin(this.apiHost, this.resourceEndpoint, id);
}
return superagent[method](url$$1)
.set("X-Hny-Team", this.apiKey)
.set("User-Agent", this.userAgent)
.type("json");
}
create(resource, datasetName) {
if (this.datasetScoped && !datasetName) {
throw new Error(
`a datasetName is required to create a ${this.resourceType.name}`
);
} else if (!this.datasetScoped && datasetName) {
throw new Error(
`a datasetName cannot be used to create a ${this.resourceType.name}`
);
}
return new Promise((resolve, reject) => {
this.newRequest("post", undefined, datasetName)
.send(resource)
.end((err, res) => {
// more here
if (err) {
reject(err);
return;
}
resolve(this.resourceType.fromJSON(res.body));
});
});
}
get(id, datasetName) {
if (this.datasetScoped && !datasetName) {
throw new Error(
`a datasetName is required to fetch a ${this.resourceType.name}`
);
} else if (!this.datasetScoped && datasetName) {
throw new Error(
`a datasetName cannot be used to fetch a ${this.resourceType.name}`
);
}
return new Promise((resolve, reject) => {
this.newRequest("get", id, datasetName)
.send()
.end((err, res) => {
// more here
if (err) {
reject(err);
return;
}
resolve(this.resourceType.fromJSON(res.body));
});
});
}
delete(id, datasetName) {
if (this.datasetScoped && !datasetName) {
throw new Error(
`a datasetName is required to delete a ${this.resourceType.name}`
);
} else if (!this.datasetScoped && datasetName) {
throw new Error(
`a datasetName cannot be used to delete a ${this.resourceType.name}`
);
}
return new Promise((resolve, reject) => {
this.newRequest("delete", id, datasetName)
.send()
.end(err => {
// more here?
if (err) {
reject(err);
return;
}
resolve();
});
});
}
update(resource, datasetName) {
if (this.datasetScoped && !datasetName) {
throw new Error(
`a datasetName is required to update a ${this.resourceType.name}`
);
} else if (!this.datasetScoped && datasetName) {
throw new Error(
`a datasetName cannot be used to update a ${this.resourceType.name}`
);
}
return new Promise((resolve, reject) => {
this.newRequest("put", resource.id, datasetName)
.send(resource)
.end((err, res) => {
// more here
if (err) {
reject(err);
return;
}
resolve(this.resourceType.fromJSON(res.body));
});
});
}
list(datasetName) {
if (this.datasetScoped && !datasetName) {
throw new Error(
`a datasetName is required to list ${this.resourceType.name}s`
);
} else if (!this.datasetScoped && datasetName) {
throw new Error(
`a datasetName cannot be used to list ${this.resourceType.name}s`
);
}
return new Promise((resolve, reject) => {
this.newRequest("get", undefined, datasetName)
.send()
.end((err, res) => {
if (err) {
reject(err);
return;
}
resolve((res.body || []).map(r => this.resourceType.fromJSON(r)));
});
});
}
}
/* notyet
const validFilterOps = {
"=": true,
"!=": true,
">": true,
">=": true,
"<": true,
"<=": true,
"starts-with": true,
"does-not-start-with": true,
exists: true,
"does-not-exist": true,
contains: true,
"does-not-contain": true
};
*/
const validCalculateOps = {
NONE: true,
COUNT: true,
SUM: true,
AVG: true,
COUNT_DISTINCT: true,
MAX: true,
MIN: true,
P001: true,
P01: true,
P05: true,
P10: true,
P25: true,
P50: true,
P75: true,
P90: true,
P95: true,
P99: true,
P999: true,
HEATMAP: true
};
class Calculation {
constructor(column, op) {
this.column = column;
this.op = op;
if (this.op === "COUNT") {
this.column = "*";
}
}
static fromJSON(c) {
return new Calculation(c.column, c.op);
}
}
Object.keys(validCalculateOps).forEach(op => {
});
class Filter {
constructor(column, op, value) {
this.column = column;
this.op = op;
this.value = value;
}
static fromJSON(f) {
return new Filter(f.column, f.op, f.value);
}
}
class Order {
constructor(column, op, order = "ascending") {
this.column = column;
this.op = op;
this.order = order;
if (this.op === "COUNT") {
this.column = "*";
}
}
ascending() {
this.order = "ascending";
return this;
}
descending() {
this.order = "descending";
return this;
}
static fromJSON(o) {
return new Order(o.column, o.op, o.order);
}
}
Object.keys(validCalculateOps).forEach(op => {
});
class Query {
constructor(
breakdowns = [],
calculations = [],
filters = [],
filterCombination,
orders = [],
limit,
startTime,
endTime,
timeRange,
granularity
) {
this.breakdowns = breakdowns;
this.calculations = calculations;
this.filters = filters;
this.filterCombination = filterCombination;
this.orders = orders;
this.limit = limit;
this.startTime = startTime;
this.endTime = endTime;
this.timeRange = timeRange;
this.granularity = granularity;
}
static fromJSON(q) {
if (typeof q === "undefined") {
return q;
}
return new Query(
q.breakdowns || [],
(q.calculations || []).map(c => Calculation.fromJSON(c)),
(q.filter || []).map(f => Filter.fromJSON(f)),
q.filterCombination,
(q.orders || []).map(o => Order.fromJSON(o)),
q.limit,
q.startTime,
q.endTime,
q.timeRange,
q.granularity
);
}
}
class BoardQuery {
constructor(name, description, dataset, query$$1) {
this.name = name;
this.description = description;
this.dataset = dataset;
this.query = query$$1;
}
static fromJSON(bq) {
if (typeof bq === "undefined") {
return bq;
}
return new BoardQuery(
bq.name,
bq.description,
bq.dataset,
Query.fromJSON(bq.query)
);
}
}
class Board {
constructor(name, description, queries, id) {
this.name = name;
this.description = description;
this.queries = queries;
this.id = id;
}
static fromJSON(b) {
return new Board(
b.name,
b.description,
(b.queries || []).map(bq => BoardQuery.fromJSON(bq)),
b.id
);
}
}
const ENDPOINT = "/1/boards";
class Client extends ResourceClient {
constructor({ apiHost, apiKey, disabled, userAgentAddition }) {
super(
apiHost,
ENDPOINT,
Board,
apiKey,
disabled,
false /* not dataset scoped */,
userAgentAddition
);
}
}
// Copyright 2016 Hound Technology, Inc. All rights reserved.
const USER_AGENT$1 = "libhoney-js/1.2.0";
const USER_AGENT = "libhoney-js/1.2.0";

@@ -574,7 +221,7 @@ const _global =

/* keyfn */
ev => `${ev.apiHost}_${ev.apiKey}_${ev.dataset}`,
ev => `${ev.apiHost}_${ev.writeKey}_${ev.dataset}`,
/* createfn */
ev => ({
apiHost: ev.apiHost,
apiKey: ev.apiKey,
writeKey: ev.writeKey,
dataset: ev.dataset,

@@ -617,3 +264,3 @@ events: [ev]

postData,
apiKey,
writeKey,
dataset,

@@ -626,3 +273,3 @@ sampleRate,

this.postData = postData;
this.apiKey = apiKey;
this.writeKey = writeKey;
this.dataset = dataset;

@@ -715,2 +362,3 @@ this.sampleRate = sampleRate;

this._userAgentAddition = options.userAgentAddition || "";
this._proxy = options.proxy;

@@ -765,3 +413,3 @@ // Included for testing; to stub out randomness and verify that an event

let batch = this._eventQueue.splice(0, this._batchSizeTrigger);
var batch = this._eventQueue.splice(0, this._batchSizeTrigger);

@@ -785,4 +433,7 @@ let batchAgg = new BatchEndpointAggregator(batch);

eachPromise(batches, batch => {
let url$$1 = urljoin(batch.apiHost, "/1/batch", batch.dataset);
let req = superagent.post(url$$1);
var url$$1 = urljoin(batch.apiHost, "/1/batch", batch.dataset);
var req = superagent.post(url$$1);
if (this._proxy) {
req = proxy(req, this._proxy);
}

@@ -803,11 +454,11 @@ let { encoded, numEncoded } = batchAgg.encodeBatchEvents(batch.events);

let userAgent = USER_AGENT$1;
let userAgent = USER_AGENT;
let trimmedAddition = this._userAgentAddition.trim();
if (trimmedAddition) {
userAgent = `${USER_AGENT$1} ${trimmedAddition}`;
userAgent = `${USER_AGENT} ${trimmedAddition}`;
}
let start = Date.now();
var start = Date.now();
req
.set("X-Hny-Team", batch.apiKey)
.set("X-Hny-Team", batch.writeKey)
.set("User-Agent", userAgent)

@@ -862,3 +513,3 @@ .type("json")

_shouldSendEvent(ev) {
let { sampleRate } = ev;
var { sampleRate } = ev;
if (sampleRate <= 1) {

@@ -930,3 +581,3 @@ return true;

/**
* The Honeycomb authentication token for this event. Find you team api key at
* The Honeycomb authentication token for this event. Find your team write key at
* https://ui.honeycomb.io/account

@@ -936,3 +587,3 @@ *

*/
this.apiKey = "";
this.writeKey = "";
/**

@@ -1059,8 +710,8 @@ * The name of the Honeycomb dataset to which to send this event.

* The Honeycomb authentication token. If it is set on a libhoney instance it will be used as the
* default api key for all events. If absent, it must be explicitly set on a Builder or
* Event. Find your team api key at https://ui.honeycomb.io/account
* default write key for all events. If absent, it must be explicitly set on a Builder or
* Event. Find your team write key at https://ui.honeycomb.io/account
*
* @type {string}
*/
this.apiKey = "";
this.writeKey = "";
/**

@@ -1091,4 +742,4 @@ * The name of the Honeycomb dataset to which to send these events. If it is specified during

* @example <caption>using an object</caption>
* let honey = new libhoney();
* let builder = honey.newBuilder();
* var honey = new libhoney();
* var builder = honey.newBuilder();
* builder.add ({

@@ -1148,3 +799,3 @@ * component: "web",

sendNow(data) {
let ev = this.newEvent();
var ev = this.newEvent();
ev.add(data);

@@ -1163,5 +814,5 @@ ev.send();

newEvent() {
let ev = new Event(this._libhoney, this._fields, this._dyn_fields);
var ev = new Event(this._libhoney, this._fields, this._dyn_fields);
ev.apiHost = this.apiHost;
ev.apiKey = this.apiKey;
ev.writeKey = this.writeKey;
ev.dataset = this.dataset;

@@ -1180,8 +831,9 @@ ev.sampleRate = this.sampleRate;

* @example <caption>additional fields/dyn_field</caption>
* let anotherBuilder = builder.newBuilder({ requestId }, {
* process_heapUsed: () => process.memoryUsage().heapUsed
* });
* let anotherBuilder = builder.newBuilder({ requestId },
* {
* process_heapUsed: () => process.memoryUsage().heapUsed
* });
*/
newBuilder(fields, dyn_fields) {
let b = new Builder(this._libhoney, this._fields, this._dyn_fields);
var b = new Builder(this._libhoney, this._fields, this._dyn_fields);

@@ -1192,3 +844,3 @@ foreach(fields, (v, k) => b.addField(k, v));

b.apiHost = this.apiHost;
b.apiKey = this.apiKey;
b.writeKey = this.writeKey;
b.dataset = this.dataset;

@@ -1201,11 +853,85 @@ b.sampleRate = this.sampleRate;

class Client$1 extends EventEmitter {
constructor(options) {
// Copyright 2016 Hound Technology, Inc. All rights reserved.
const defaults = Object.freeze({
apiHost: "https://api.honeycomb.io/",
// http
proxy: undefined,
// sample rate of data. causes us to send 1/sample-rate of events
// i.e. `sampleRate: 10` means we only send 1/10th the events.
sampleRate: 1,
// 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
batchSizeTrigger: 50, // we send a batch to the api when we have this many outstanding events
batchTimeTrigger: 100, // ... or after this many ms has passed.
// batches are sent serially (one event at a time), so we allow multiple concurrent batches
// to increase parallelism while sending.
maxConcurrentBatches: 10,
// the maximum number of pending events we allow in our to-be-batched-and-transmitted queue before dropping them.
pendingWorkCapacity: 10000,
// the maximum number of responses we enqueue before we begin dropping them.
maxResponseQueueSize: 1000,
// if this is set to true, all sending is disabled. useful for disabling libhoney when testing
disabled: false,
// If this is non-empty, append it to the end of the User-Agent header.
userAgentAddition: ""
});
/**
* libhoney aims to make it as easy as possible to create events and send them on into Honeycomb.
*
* See https://honeycomb.io/docs for background on this library.
* @class
*/
class Libhoney extends EventEmitter {
/**
* Constructs a libhoney context in order to configure default behavior,
* though each of its members (`apiHost`, `writeKey`, `dataset`, and
* `sampleRate`) may in fact be overridden on a specific Builder or Event.
*
* @param {Object} [opts] overrides for the defaults
* @param {string} [opts.apiHost=https://api.honeycomb.io] - Server host to receive Honeycomb events.
* @param {string} opts.proxy - The proxy to send events through.
* @param {string} opts.writeKey - Write key for your Honeycomb team. (Required)
* @param {string} opts.dataset - Name of the dataset that should contain this event. The dataset will be created for your team if it doesn't already exist.
* @param {number} [opts.sampleRate=1] - Sample rate of data. If set, causes us to send 1/sampleRate of events and drop the rest.
* @param {number} [opts.batchSizeTrigger=50] - We send a batch to the API when this many outstanding events exist in our event queue.
* @param {number} [opts.batchTimeTrigger=100] - We send a batch to the API after this many milliseconds have passed.
* @param {number} [opts.maxConcurrentBatches=10] - We process batches concurrently to increase parallelism while sending.
* @param {number} [opts.pendingWorkCapacity=10000] - The maximum number of pending events we allow to accumulate in our sending queue before dropping them.
* @param {number} [opts.maxResponseQueueSize=1000] - The maximum number of responses we enqueue before dropping them.
* @param {boolean} [opts.disabled=false] - Disable transmission of events to the specified `apiHost`, particularly useful for testing or development.
* @constructor
* @example
* import Libhoney from 'libhoney';
* let honey = new Libhoney({
* writeKey: "YOUR_WRITE_KEY",
* dataset: "honeycomb-js-example",
* // disabled: true // uncomment when testing or in development
* });
*/
constructor(opts) {
super();
this._options = Object.assign(
{ responseCallback: this._responseCallback.bind(this) },
options
defaults,
opts
);
this._transmission = getAndInitTransmission(

@@ -1218,8 +944,6 @@ this._options.transmission,

Object.assign(this._builder, {
apiHost: this._options.apiHost,
apiKey: this._options.apiKey,
dataset: this._options.dataset,
sampleRate: this._options.sampleRate
});
this._builder.apiHost = this._options.apiHost;
this._builder.writeKey = this._options.writeKey;
this._builder.dataset = this._options.dataset;
this._builder.sampleRate = this._options.sampleRate;

@@ -1237,6 +961,25 @@ 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/
*
* @type {string}
*/
set apiHost(v) {
this._builder.apiHost = v;
}
/**
* The hostname for the Honeycomb API server to which to send events created through this libhoney
* instance. default: https://api.honeycomb.io/
*
* @type {string}
*/
get apiHost() {

@@ -1246,16 +989,21 @@ return this._builder.apiHost;

set apiKey(v) {
this._builder.apiKey = v;
/**
* The Honeycomb authentication token. If it is set on a libhoney instance it will be used as the
* default write key for all events. If absent, it must be explicitly set on a Builder or
* Event. Find your team write key at https://ui.honeycomb.io/account
*
* @type {string}
*/
set writeKey(v) {
this._builder.writeKey = v;
}
get apiKey() {
return this._builder.apiKey;
}
/**
* 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.)
* The Honeycomb authentication token. If it is set on a libhoney instance it will be used as the
* default write key for all events. If absent, it must be explicitly set on a Builder or
* Event. Find your team write key at https://ui.honeycomb.io/account
*
* @type {string}
*/
get transmission() {
return this._transmission;
get writeKey() {
return this._builder.writeKey;
}

@@ -1309,3 +1057,3 @@

* timestamp [optional]: time for this event, defaults to now()
* apiKey [optional]: your team's api key. overrides the libhoney instance's value.
* writeKey [optional]: your team's write key. overrides the libhoney instance's value.
* dataset [optional]: the data set name. overrides the libhoney instance's value.

@@ -1334,3 +1082,3 @@ * sampleRate [optional]: cause us to send 1 out of sampleRate events. overrides the libhoney instance's value.

* timestamp [optional]: time for this event, defaults to now()
* apiKey [optional]: your team's api key. overrides the libhoney instance's value.
* writeKey [optional]: your team's write key. overrides the libhoney instance's value.
* dataset [optional]: the data set name. overrides the libhoney instance's value.

@@ -1363,3 +1111,3 @@ * sampleRate: the rate this event has already been sampled.

let timestamp = event.timestamp || Date.now();
var timestamp = event.timestamp || Date.now();
if (typeof timestamp === "string" || typeof timestamp === "number")

@@ -1372,3 +1120,3 @@ timestamp = new Date(timestamp);

}
let postData;
var postData;
try {

@@ -1381,3 +1129,3 @@ postData = JSON.stringify(event.data);

let apiHost = event.apiHost;
var apiHost = event.apiHost;
if (typeof apiHost !== "string" || apiHost === "") {

@@ -1388,9 +1136,9 @@ console.error(".apiHost must be a non-empty string");

let apiKey = event.apiKey;
if (typeof apiKey !== "string" || apiKey === "") {
console.error(".apiKey must be a non-empty string");
var writeKey = event.writeKey;
if (typeof writeKey !== "string" || writeKey === "") {
console.error(".writeKey must be a non-empty string");
return null;
}
let dataset = event.dataset;
var dataset = event.dataset;
if (typeof dataset !== "string" || dataset === "") {

@@ -1401,3 +1149,3 @@ console.error(".dataset must be a non-empty string");

let sampleRate = event.sampleRate;
var sampleRate = event.sampleRate;
if (typeof sampleRate !== "number") {

@@ -1408,3 +1156,3 @@ console.error(".sampleRate must be a number");

let metadata = event.metadata;
var metadata = event.metadata;
return new ValidatedEvent({

@@ -1414,3 +1162,3 @@ timestamp,

postData,
apiKey,
writeKey,
dataset,

@@ -1578,448 +1326,2 @@ sampleRate,

class Marker {
constructor(message, type, url$$1) {
this.message = message;
this.type = type;
this.url = url$$1;
}
static fromJSON(m) {
return new Marker(m.message, m.type, m.url);
}
}
const ENDPOINT$1 = "/1/markers";
class Client$2 extends ResourceClient {
constructor({ apiHost, apiKey, disabled, userAgentAddition }) {
super(
apiHost,
ENDPOINT$1,
Marker,
apiKey,
disabled,
true /* dataset scoped */,
userAgentAddition
);
}
}
class Trigger {
constructor(name, description, frequency, query$$1, threshold, recipients, id) {
this.name = name;
this.description = description;
this.frequency = frequency;
this.query = query$$1;
this.threshold = threshold;
this.recipients = recipients;
this.id = id;
}
static fromJSON(t) {
if (typeof t === "undefined") {
return t;
}
return new Trigger(
t.name,
t.description,
t.frequency,
Query.fromJSON(t.query),
Threshold.fromJSON(t.threshold),
(t.recipients || []).map(r => Recipient.fromJSON(r)),
t.id
);
}
}
class Threshold {
constructor(op, value) {
this.op = op;
this.value = value;
}
static fromJSON(t) {
if (typeof t === "undefined") {
return t;
}
return new Threshold(t.op, t.value);
}
}
class Recipient {
constructor(type, target) {
this.type = type;
this.target = target;
}
static fromJSON(r) {
if (typeof r === "undefined") {
return r;
}
return new Recipient(r.type, r.target);
}
}
const ENDPOINT$2 = "/1/triggers";
class Client$3 extends ResourceClient {
constructor({ apiHost, apiKey, disabled, userAgentAddition }) {
super(
apiHost,
ENDPOINT$2,
Trigger,
apiKey,
disabled,
true /* dataset scoped */,
userAgentAddition
);
}
}
// Copyright 2016 Hound Technology, Inc. All rights reserved.
const defaults = Object.freeze({
apiHost: "https://api.honeycomb.io/",
// sample rate of data. causes us to send 1/sample-rate of events
// i.e. `sampleRate: 10` means we only send 1/10th the events.
sampleRate: 1,
// 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
batchSizeTrigger: 50, // we send a batch to the api when we have this many outstanding events
batchTimeTrigger: 100, // ... or after this many ms has passed.
// batches are sent serially (one event at a time), so we allow multiple concurrent batches
// to increase parallelism while sending.
maxConcurrentBatches: 10,
// the maximum number of pending events we allow in our to-be-batched-and-transmitted queue before dropping them.
pendingWorkCapacity: 10000,
// the maximum number of responses we enqueue before we begin dropping them.
maxResponseQueueSize: 1000,
// if this is set to true, all sending is disabled. useful for disabling libhoney when testing
disabled: false,
// If this is non-empty, append it to the end of the User-Agent header.
userAgentAddition: ""
});
/**
* libhoney aims to make it as easy as possible to create events and send them on into Honeycomb.
*
* See https://honeycomb.io/docs for background on this library.
* @class
*/
class Libhoney {
/**
* Constructs a libhoney context in order to configure default behavior,
* though each of its members (`apiHost`, `apiKey`, `dataset`, and
* `sampleRate`) may in fact be overridden on a specific Builder or Event.
*
* @param {Object} [opts] overrides for the defaults
* @param {string} [opts.apiHost=https://api.honeycomb.io] - Server host to receive Honeycomb events.
* @param {string} opts.apiKey - API key for your Honeycomb team. (Required)
* @param {string} opts.writeKey - (deprecated) API key for your Honeycomb team.
* @param {string} opts.dataset - For dataset scoped clients (events, markers), the name of the dataset that should contain the resource. If sending events, the dataset will be created if not present.
* @param {number} [opts.sampleRate=1] - Sample rate of data. If set, causes us to send 1/sampleRate of events and drop the rest.
* @param {number} [opts.batchSizeTrigger=50] - We send a batch to the API when this many outstanding events exist in our event queue.
* @param {number} [opts.batchTimeTrigger=100] - We send a batch to the API after this many milliseconds have passed.
* @param {number} [opts.maxConcurrentBatches=10] - We process batches concurrently to increase parallelism while sending.
* @param {number} [opts.pendingWorkCapacity=10000] - The maximum number of pending events we allow to accumulate in our sending queue before dropping them.
* @param {number} [opts.maxResponseQueueSize=1000] - The maximum number of responses we enqueue before dropping them.
* @param {boolean} [opts.disabled=false] - Disable communication to the specified `apiHost`, particularly useful for testing or development.
* @constructor
* @example
* import Libhoney from 'libhoney';
* let honey = new Libhoney({
* apiKey: "YOUR_API_KEY",
* dataset: "honeycomb-js-example",
* // disabled: true // uncomment when testing or in development
* });
*/
constructor(opts) {
this._options = Object.assign({}, defaults, opts);
if (this._options.writeKey && typeof this._options.apiKey === "undefined") {
// fall back to writeKey if apiKey isn't present
this._options.apiKey = this._options.writeKey;
}
}
/**
* The hostname for the Honeycomb API server to which to send events created through this libhoney
* instance. default: https://api.honeycomb.io/
*
* @type {string}
*/
set apiHost(v) {
this._options.apiHost = v;
// update all the clients
if (this._boards) {
this._boards.apiHost = v;
}
if (this._events) {
this._events.apiHost = v;
}
if (this._markers) {
this._markers.apiHost = v;
}
if (this._triggers) {
this._triggers.apiHost = v;
}
}
/**
* The hostname for the Honeycomb API server to which to send events created through this libhoney
* instance. default: https://api.honeycomb.io/
*
* @type {string}
*/
get apiHost() {
return this._options.apiHost;
}
/**
* The Honeycomb authentication token. If it is set on a libhoney instance it will be used as the
* default api key for all events. If absent, it must be explicitly set on a Builder or
* Event. Find your team api key at https://ui.honeycomb.io/account
*
* @type {string}
*/
set apiKey(v) {
this._options.apiKey = v;
// update all the clients
if (this._boards) {
this._boards.apiKey = v;
}
if (this._events) {
this._events.apiKey = v;
}
if (this._markers) {
this._markers.apiKey = v;
}
if (this._triggers) {
this._triggers.apiKey = v;
}
}
/**
* The Honeycomb authentication token. If it is set on a libhoney instance it will be used as the
* default api key for all events. If absent, it must be explicitly set on a Builder or
* Event. Find your team api key at https://ui.honeycomb.io/account
*
* @type {string}
*/
get apiKey() {
return this.options._apiKey;
}
get boards() {
if (!this._boards) {
this._boards = new Client(this._options);
}
return this._boards;
}
get events() {
if (!this._events) {
this._events = new Client$1(this._options);
}
return this._events;
}
get markers() {
if (!this._markers) {
this._markers = new Client$2(this._options);
}
return this._markers;
}
get triggers() {
if (!this._triggers) {
this._triggers = new Client$3(this._options);
}
return this._triggers;
}
// deprecated writeKey accessors. will go away with the next major version bump
set writeKey(v) {
this.apiKey = v;
}
get writeKey() {
return this.apiKey;
}
// proxies for the events client. these _may_ go away in a future major release.
/**
* The rate at which to sample events. Default is 1, meaning no sampling. If you want to send one
* event out of every 250 times send() is called, you would specify 250 here.
*
* @type {number}
*/
set sampleRate(v) {
this.events.sampleRate = v;
}
/**
* The rate at which to sample events. Default is 1, meaning no sampling. If you want to send one
* event out of every 250 times send() is called, you would specify 250 here.
*
* @type {number}
*/
get sampleRate() {
return this.events.sampleRate;
}
/**
* sendEvent takes events of the following form:
*
* {
* data: a JSON-serializable object, keys become colums in Honeycomb
* timestamp [optional]: time for this event, defaults to now()
* writeKey [optional]: your team's write key. overrides the libhoney instance's value.
* dataset [optional]: the data set name. overrides the libhoney instance's value.
* sampleRate [optional]: cause us to send 1 out of sampleRate events. overrides the libhoney instance's value.
* }
*
* Sampling is done based on the supplied sampleRate, so events passed to this method might not
* actually be sent to Honeycomb.
* @private
*/
sendEvent(event) {
return this.events.sendEvent(event);
}
/**
* sendPresampledEvent takes events of the following form:
*
* {
* data: a JSON-serializable object, keys become colums in Honeycomb
* timestamp [optional]: time for this event, defaults to now()
* writeKey [optional]: your team's write key. overrides the libhoney instance's value.
* dataset [optional]: the data set name. overrides the libhoney instance's value.
* sampleRate: the rate this event has already been sampled.
* }
*
* Sampling is presumed to have already been done (at the supplied sampledRate), so all events passed to this method
* are sent to Honeycomb.
* @private
*/
sendPresampledEvent(event) {
return this.events.sendPresampledEvent(event);
}
/**
* validateEvent takes an event and validates its structure and contents.
*
* @returns {Object} the validated libhoney Event. May return undefined if
* the event was invalid in some way or unable to be sent.
* @private
*/
validateEvent(event) {
return this.events.validateEvent(event);
}
/**
* adds a group of field->values to the global Builder.
* @param {Object|Map<string, any>} data field->value mapping.
* @returns {Libhoney} this libhoney instance.
* @example <caption>using an object</caption>
* honey.add ({
* buildID: "a6cc38a1",
* env: "staging"
* });
* @example <caption>using an ES2015 map</caption>
* let map = new Map();
* map.set("build_id", "a6cc38a1");
* map.set("env", "staging");
* honey.add (map);
*/
add(data) {
return this.events.add(data);
}
/**
* adds a single field->value mapping to the global Builder.
* @param {string} name name of field to add.
* @param {any} val value of field to add.
* @returns {Libhoney} this libhoney instance.
* @example
* honey.addField("build_id", "a6cc38a1");
*/
addField(name, val) {
return this.events.addField(name, val);
}
/**
* adds a single field->dynamic value function to the global Builder.
* @param {string} name name of field to add.
* @param {function(): any} fn function that will be called to generate the value whenever an event is created.
* @returns {Libhoney} this libhoney instance.
* @example
* honey.addDynamicField("process_heapUsed", () => process.memoryUsage().heapUsed);
*/
addDynamicField(name, fn) {
return this.events.addDynamicField(name, fn);
}
/**
* creates and sends an event, including all global builder fields/dyn_fields, as well as anything in the optional data parameter.
* @param {Object|Map<string, any>} data field->value mapping.
* @example <caption>using an object</caption>
* honey.sendNow ({
* responseTime_ms: 100,
* httpStatusCode: 200
* });
* @example <caption>using an ES2015 map</caption>
* let map = new Map();
* map.set("responseTime_ms", 100);
* map.set("httpStatusCode", 200);
* honey.sendNow (map);
*/
sendNow(data) {
return this.events.sendNow(data);
}
/**
* creates and returns a new Event containing all fields/dyn_fields from the global Builder, that can be further fleshed out and sent on its own.
* @returns {Event} an Event instance
* @example <caption>adding data at send-time</caption>
* let ev = honey.newEvent();
* ev.addField("additionalField", value);
* ev.send();
*/
newEvent() {
return this.events.newEvent();
}
/**
* creates and returns a clone of the global Builder, merged with fields and dyn_fields passed as arguments.
* @param {Object|Map<string, any>} fields a field->value mapping to merge into the new builder.
* @param {Object|Map<string, any>} dyn_fields a field->dynamic function mapping to merge into the new builder.
* @returns {Builder} a Builder instance
* @example <caption>no additional fields/dyn_field</caption>
* let builder = honey.newBuilder();
* @example <caption>additional fields/dyn_field</caption>
* let builder = honey.newBuilder({ requestId },
* {
* process_heapUsed: () => process.memoryUsage().heapUsed
* });
*/
newBuilder(fields, dyn_fields) {
return this.events.newBuilder(fields, dyn_fields);
}
}
// this will absolutely go away with the next major version bump. right now in normal node (CJS) usage,

@@ -2034,11 +1336,2 @@ // users have to do: `let Libhoney = require("libhoney").default;`

// this will absolutely go away with the next major version bump. right now in normal node (CJS) usage,
// users have to do: `let Libhoney = require("libhoney").default;`
//
// switching to rollup fixes that (yay!) but we need to keep it working until we do the major bump. hence
// this hack.
if (typeof module !== "undefined") {
Object.defineProperty(Libhoney, "default", { value: Libhoney });
}
export default Libhoney;
{
"name": "libhoney",
"version": "1.1.3",
"version": "1.2.1",
"description": " Honeycomb.io Javascript library",

@@ -42,5 +42,6 @@ "bugs": "https://github.com/honeycombio/libhoney-js/issues",

"prettier": "^1.14.0",
"rollup": "^0.63.4",
"rollup-plugin-babel": "^3.0.7",
"rollup": "^0.66.6",
"rollup-plugin-babel": "^4.0.3",
"rollup-plugin-commonjs": "^9.1.4",
"rollup-plugin-json": "^3.1.0",
"rollup-plugin-node-resolve": "^3.3.0",

@@ -52,4 +53,5 @@ "rollup-plugin-replace": "^2.0.0",

"superagent": "^3.8.3",
"superagent-proxy": "^2.0.0",
"urljoin": "^0.1.5"
}
}
# libhoney [![Build Status](https://travis-ci.org/honeycombio/libhoney-js.svg?branch=master)](https://travis-ci.org/honeycombio/libhoney-js) [![npm version](https://badge.fury.io/js/libhoney.svg)](https://badge.fury.io/js/libhoney)
A node (>=4) module for interacting with [Honeycomb](https://honeycomb.io). (For more information, see the [documentation](https://honeycomb.io/docs/) and [JavaScript SDK guide](https://honeycomb.io/docs/connect/javascript).)
A nodeJS module for sending events to [Honeycomb](https://www.honeycomb.io), a service for debugging your software in production.
**NOT** for use in browser-side JavaScript applications. Write keys are your auth tokens for sending data to Honeycomb and should be kept secure -- they're not per-site keys. Don't leave yourself vulnerable to malicious users.
**NOTE** For use in browser-side JavaScript applications, generate an api key that has permission only to send events.
## Installation
Requires node 4+.
### npm
```
npm install libhoney --save
```
### yarn
```
yarn add libhoney
```
- [Usage and Examples](https://docs.honeycomb.io/sdk/javascript/)
- [API Reference](https://doc.esdoc.org/github.com/honeycombio/libhoney-js/)
## Documentation
For tracing support and automatic instrumentation of Express and other common libraries, check out our [Beeline for NodeJS](https://github.com/honeycombio/beeline-nodejs).
An API reference is available at https://honeycomb.io/docs/connect/javascript/
## Example
Honeycomb can calculate all sorts of statistics, so send the values you care about and let us crunch the averages, percentiles, lower/upper bounds, cardinality -- whatever you want -- for you.
```js
import Libhoney from 'libhoney';
let hny = new Libhoney({
writeKey: "YOUR_WRITE_KEY",
dataset: "honeycomb-js-example"
});
hny.sendNow({
message: "Test Honeycomb event",
randomFloat: Math.random(),
hostname: os.hostname(),
favoriteColor: "chartreuse"
});
```
For more, see the [`examples/`](examples/) directory for sample code demonstrating how to use events,
builders, fields, and dynamic fields in an Express app.
## Contributions

@@ -52,1 +21,5 @@

All contributions will be released under the Apache License 2.0.
### Releasing a new version
Travis will automatically upload tagged releases to NPM.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc