Comparing version 1.1.3 to 1.2.1
@@ -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. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
19
0
98448
3
16
1
2465
25
+ Addedsuperagent-proxy@^2.0.0
+ Added@tootallnate/once@1.1.2(transitive)
+ Addedagent-base@6.0.2(transitive)
+ Addedast-types@0.13.4(transitive)
+ Addedbytes@3.1.2(transitive)
+ Addeddata-uri-to-buffer@3.0.1(transitive)
+ Addeddebug@4.3.7(transitive)
+ Addeddeep-is@0.1.4(transitive)
+ Addeddegenerator@2.2.0(transitive)
+ Addeddepd@2.0.0(transitive)
+ Addedescodegen@1.14.3(transitive)
+ Addedesprima@4.0.1(transitive)
+ Addedestraverse@4.3.0(transitive)
+ Addedesutils@2.0.3(transitive)
+ Addedfast-levenshtein@2.0.6(transitive)
+ Addedfile-uri-to-path@2.0.0(transitive)
+ Addedfs-extra@8.1.0(transitive)
+ Addedftp@0.3.10(transitive)
+ Addedget-uri@3.0.2(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedhttp-errors@2.0.0(transitive)
+ Addedhttp-proxy-agent@4.0.1(transitive)
+ Addedhttps-proxy-agent@5.0.1(transitive)
+ Addediconv-lite@0.4.24(transitive)
+ Addedip@1.1.9(transitive)
+ Addedip-address@9.0.5(transitive)
+ Addedisarray@0.0.1(transitive)
+ Addedjsbn@1.1.0(transitive)
+ Addedjsonfile@4.0.0(transitive)
+ Addedlevn@0.3.0(transitive)
+ Addedlru-cache@5.1.1(transitive)
+ Addednetmask@2.0.2(transitive)
+ Addedoptionator@0.8.3(transitive)
+ Addedpac-proxy-agent@4.1.0(transitive)
+ Addedpac-resolver@4.2.0(transitive)
+ Addedprelude-ls@1.1.2(transitive)
+ Addedproxy-agent@4.0.1(transitive)
+ Addedproxy-from-env@1.1.0(transitive)
+ Addedraw-body@2.5.2(transitive)
+ Addedreadable-stream@1.1.14(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsetprototypeof@1.2.0(transitive)
+ Addedsmart-buffer@4.2.0(transitive)
+ Addedsocks@2.8.3(transitive)
+ Addedsocks-proxy-agent@5.0.1(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addedsprintf-js@1.1.3(transitive)
+ Addedstatuses@2.0.1(transitive)
+ Addedstring_decoder@0.10.31(transitive)
+ Addedsuperagent-proxy@2.1.0(transitive)
+ Addedtoidentifier@1.0.1(transitive)
+ Addedtslib@2.8.1(transitive)
+ Addedtype-check@0.3.2(transitive)
+ Addeduniversalify@0.1.2(transitive)
+ Addedunpipe@1.0.0(transitive)
+ Addedword-wrap@1.2.5(transitive)
+ Addedxregexp@2.0.0(transitive)
+ Addedyallist@3.1.1(transitive)