amberflo-metering-typescript
Version:
Amberflo metering client for TypeScript
159 lines • 6.69 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Metering = void 0;
const meterMessage_1 = require("./model/meterMessage");
const ingestClientFactory_1 = require("./ingestClient/ingestClientFactory");
const Errors = __importStar(require("./model/errors"));
const customerApiPayload_1 = require("./model/customerApiPayload");
const customerDetailsApiClient_1 = require("./ingestClient/customerDetailsApiClient");
/**
* Metering is the main class to ingest meters into Amberflo
*/
class Metering {
/**
* Initialize a new metering client without any side effects. Call start() to start up the ingestion client.
* @param apiKey
* @param debug
* @param ingestOptions
*/
constructor(apiKey, debug, ingestOptions) {
this.isStarted = false;
if (!apiKey.trim()) {
throw new Error(Errors.MISSING_API_KEY);
}
this.signature = '[amberflo-metering Metering]:';
this.apiKey = apiKey;
this.debug = debug;
this.ingestClient = ingestClientFactory_1.IngestClientFactory.getNewInstance(apiKey, debug, ingestOptions);
this.customerDetailsApiClient = new customerDetailsApiClient_1.CustomerDetailsApiClient(apiKey, debug);
}
/**
* Start and initialize the ingestion client. If this is not called, all ingestion calls will fail.
*/
start() {
if (this.isStarted) {
return;
}
this.ingestClient.start();
this.isStarted = true;
}
/**
* Queue a meter for ingestion.
* In auto flush mode, queue will be flushed automatically when ingestOptions.batchSize is exceeded or periodically ingestOptions.frequencyMillis
* In manual flush mode, call flush() To ingest messages in the queue
* @param {string} meterApiName
* @param {number} meterValue
* @param {number} meterTimeInMillis
* @param {string} customerId
* @param {Map<string,string>} dimensions
*/
meter(meterApiName, meterValue, meterTimeInMillis, customerId, dimensions) {
if (!this.isStarted) {
throw new Error(Errors.START_NOT_CALLED);
}
const meterMessage = new meterMessage_1.MeterMessage(meterApiName, meterValue, meterTimeInMillis, customerId, dimensions);
const validations = Metering.validateMeterMessage(meterMessage);
if (validations.length > 0) {
throw new Error(`Invalid meter message: ${validations}`);
}
this.ingestClient.ingestMeter(meterMessage);
}
static validateMeterMessage(meterMessage) {
const validations = [];
//threshold of 5 mins in the future
const currentMillis = Date.now() + (5 * 60 * 1000);
if (!meterMessage.customerId.trim()) {
validations.push(Errors.MISSING_CUSTOMER_ID);
}
if (!meterMessage.meterApiName.trim()) {
validations.push(Errors.MISSING_METER_NAME);
}
if (meterMessage.meterTimeInMillis < 1) {
validations.push(Errors.INVALID_UTC_TIME_MILLIS);
}
if (meterMessage.meterTimeInMillis > currentMillis) {
validations.push(Errors.UTC_TIME_MILLIS_FROM_FUTURE);
}
return validations;
}
/**
* Add or update customer details.
* @param customerId
* @param customerName
* @param traits
*/
addOrUpdateCustomerDetails(customerId, customerName, traits) {
return __awaiter(this, void 0, void 0, function* () {
const validations = [];
if (!customerId.trim()) {
validations.push(Errors.MISSING_CUSTOMER_ID);
}
if (!customerName.trim()) {
validations.push(Errors.MISSING_CUSTOMER_NAME);
}
if (validations.length > 0) {
throw new Error(`Invalid customer message: ${validations}`);
}
const payload = new customerApiPayload_1.CustomerDetailsApiPayload(customerId, customerName, traits);
return this.customerDetailsApiClient.post(payload);
});
}
/**
* Process all pending ingestion meter messages and wait for all requests to API to complete.
*/
flush() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.isStarted) {
throw new Error(Errors.START_NOT_CALLED);
}
console.log(new Date(), this.signature, 'flushing ...');
return this.ingestClient.flush();
});
}
/**
* Shutdown the ingestion client.
*/
shutdown() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.isStarted) {
throw new Error(Errors.START_NOT_CALLED);
}
console.log(new Date(), this.signature, 'shutting down ...');
return this.ingestClient.shutdown();
});
}
}
exports.Metering = Metering;
//# sourceMappingURL=metering.js.map