UNPKG

firestore-metrics

Version:

A library which uses the Cloud Monitoring API v3 to view Firestore metrics.

311 lines 13.9 kB
"use strict"; 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.FirestoreMetrics = void 0; const google_auth_library_1 = require("google-auth-library"); class FirestoreMetrics { constructor(params) { var _a; this.projectId = null; this.accessToken = null; this.googleAuth = null; this.baseUrl = "https://monitoring.googleapis.com/v3/projects"; this.scopes = [ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/monitoring", "https://www.googleapis.com/auth/monitoring.read", ]; this.googleAuthArgs = Object.assign({}, params); this.projectId = (_a = params.projectId) !== null && _a !== void 0 ? _a : null; } /** * Helper function to compose the metric type filter. * @param {string} metricName Name of the metric type. * @returns {string} A string filter to be passed to the request. */ metricFilter(metricName) { const encodedMetricName = encodeURI(metricName); return `filter=metric.type%20%3D%20%22firestore.googleapis.com%2F${encodedMetricName}%22`; } /** * Creates a Google Auth instance if null. */ createGoogleAuthInstance() { if (this.googleAuth === null) { this.googleAuth = new google_auth_library_1.GoogleAuth(Object.assign(Object.assign({}, this.googleAuthArgs), { scopes: this.scopes })); } } /** * Gets the project ID and sets its value if it is still null. */ getProjectId() { return __awaiter(this, void 0, void 0, function* () { this.createGoogleAuthInstance(); this.projectId = this.projectId || (yield this.googleAuth.getProjectId()); return this.projectId; }); } /** * Generates an access token. * @param {boolean} overwriteExisting If true, overwrites the existing access token. * @returns {Promise<string>} Access token used to authenticate requests. */ generateToken(overwriteExisting = true) { return __awaiter(this, void 0, void 0, function* () { if (this.accessToken === null || overwriteExisting === true) { this.createGoogleAuthInstance(); this.accessToken = yield this.googleAuth.getAccessToken(); } // Makes sure that the project id is always loaded before being used. yield this.getProjectId(); return this.accessToken; }); } /** * Sets the access token. * @param {boolean} accessToken Value of the new access token. */ setAccessToken(accessToken) { this.accessToken = accessToken; return; } /** * Makes a request to the Cloud monitoring API. * @param {string} filter A monitoring filter that specifies which time series should be returned. * @param {string} startTime The beginning of the time interval. * @param {string} endTime The end of the time interval. * @returns */ makeRequest(filter, startTime, endTime) { return __awaiter(this, void 0, void 0, function* () { const encodedStartTime = encodeURI(startTime); const encodedEndTime = encodeURI(endTime); const timeInterval = `interval.endTime=${encodedEndTime}&interval.startTime=${encodedStartTime}`; const url = `${this.baseUrl}/${this.projectId}/timeSeries?${filter}&${timeInterval}`; const response = yield fetch(url, { headers: { accept: "*/*", authorization: `Bearer ${this.accessToken}`, }, body: null, method: "GET", }); if (response.status !== 200) { const errMesage = yield response.text(); throw Error(errMesage); } return response; }); } /** * Check if the list contains an the object. * @param obj Object. * @param list List of objects. * @returns True if the list contains the object. */ containsObject(obj, list) { if (JSON.stringify(list).includes(JSON.stringify(obj))) { return true; } return false; } /** * Removes keys in an object with null, undefined, etc. value. * @param obj Object. * @param args Additional values to be removes. * @returns An object with keys with invalid values removed. */ cleanObject(obj, ...args) { const invalidValues = [null, undefined, ...args]; for (let propName in obj) { if (invalidValues.includes(obj[propName])) { delete obj[propName]; } } return obj; } /** * Cleans/formats the response into something more understandable. * @param {Response} response Fetch response. * @returns {Promise<Array<TimeIntervalMetric>>} An array of time intervals and count of transactions for that time. */ cleanResponseTimeSeries(response) { return __awaiter(this, void 0, void 0, function* () { const cleanTimeSeries = []; const responseContent = yield response.text(); const timeSeriesResponse = JSON.parse(responseContent); if (timeSeriesResponse.timeSeries === undefined) { return cleanTimeSeries; } for (let timeSeries of timeSeriesResponse.timeSeries) { for (let point of timeSeries.points) { if (point.value.int64Value !== "0") { const labels = this.cleanObject(timeSeries.metric.labels, "__unknown__", ""); const pointMetric = Object.assign(Object.assign({}, labels), { interval: { endTime: point.interval.endTime, startTime: point.interval.startTime, }, count: parseInt(point.value.int64Value) }); if (!this.containsObject(pointMetric, cleanTimeSeries)) { cleanTimeSeries.push(pointMetric); } } } } return cleanTimeSeries; }); } /** * Get Firestore read count metrics. * @param {DateTimeStringISO} startTime The beginning of the time interval. * @param {DateTimeStringISO} endTime The end of the time interval. * @param {string?} accessToken Access token used to authenticate. * @returns {Promise<Array<TimeIntervalMetric>>} */ getReadCount(startTime, endTime, accessToken = null) { return __awaiter(this, void 0, void 0, function* () { if (accessToken === null) { yield this.generateToken(false); } const filter = this.metricFilter("document/read_count"); const res = yield this.makeRequest(filter, startTime, endTime); const cleanTimeSeries = yield this.cleanResponseTimeSeries(res); return cleanTimeSeries; }); } /** * Get Firestore write count metrics. * @param {DateTimeStringISO} startTime The beginning of the time interval. * @param {DateTimeStringISO} endTime The end of the time interval. * @param {string?} accessToken Access token used to authenticate. * @returns {Promise<Array<TimeIntervalMetric>>} */ getWriteCount(startTime, endTime, accessToken = null) { return __awaiter(this, void 0, void 0, function* () { if (accessToken === null) { yield this.generateToken(false); } const filter = this.metricFilter("document/write_count"); const res = yield this.makeRequest(filter, startTime, endTime); const cleanTimeSeries = yield this.cleanResponseTimeSeries(res); return cleanTimeSeries; }); } /** * Get Firestore delete count metrics. * @param {DateTimeStringISO} startTime The beginning of the time interval. * @param {DateTimeStringISO} endTime The end of the time interval. * @param {string?} accessToken Access token used to authenticate. * @returns {Promise<Array<TimeIntervalMetric>>} */ getDeleteCount(startTime, endTime, accessToken = null) { return __awaiter(this, void 0, void 0, function* () { if (accessToken === null) { yield this.generateToken(false); } const filter = this.metricFilter("document/delete_count"); const res = yield this.makeRequest(filter, startTime, endTime); const cleanTimeSeries = yield this.cleanResponseTimeSeries(res); return cleanTimeSeries; }); } /** * Get Firestore snapshot listeners count metrics. * @param {DateTimeStringISO} startTime The beginning of the time interval. * @param {DateTimeStringISO} endTime The end of the time interval. * @param {string?} accessToken Access token used to authenticate. * @returns {Promise<Array<TimeIntervalMetric>>} */ getSnapshotListeners(startTime, endTime, accessToken = null) { return __awaiter(this, void 0, void 0, function* () { if (accessToken === null) { yield this.generateToken(false); } const filter = this.metricFilter("network/snapshot_listeners"); const res = yield this.makeRequest(filter, startTime, endTime); const cleanTimeSeries = yield this.cleanResponseTimeSeries(res); return cleanTimeSeries; }); } /** * Get Firestore active connections count metrics. * @param {DateTimeStringISO} startTime The beginning of the time interval. * @param {DateTimeStringISO} endTime The end of the time interval. * @param {string?} accessToken Access token used to authenticate. * @returns {Promise<Array<TimeIntervalMetric>>} */ getActiveConnections(startTime, endTime, accessToken = null) { return __awaiter(this, void 0, void 0, function* () { if (accessToken === null) { yield this.generateToken(false); } const filter = this.metricFilter("network/active_connections"); const res = yield this.makeRequest(filter, startTime, endTime); const cleanTimeSeries = yield this.cleanResponseTimeSeries(res); return cleanTimeSeries; }); } /** * Get Firestore documents deleted by TTL services count. * @param {DateTimeStringISO} startTime The beginning of the time interval. * @param {DateTimeStringISO} endTime The end of the time interval. * @param {string?} accessToken Access token used to authenticate. * @returns {Promise<Array<TimeIntervalMetric>>} */ getTTLDeletionCount(startTime, endTime, accessToken = null) { return __awaiter(this, void 0, void 0, function* () { if (accessToken === null) { yield this.generateToken(false); } const filter = this.metricFilter("document/ttl_deletion_count"); const res = yield this.makeRequest(filter, startTime, endTime); const cleanTimeSeries = yield this.cleanResponseTimeSeries(res); return cleanTimeSeries; }); } /** * Get Firestore Security Rule evaluations count performed in response to write read requests. * @param {DateTimeStringISO} startTime The beginning of the time interval. * @param {DateTimeStringISO} endTime The end of the time interval. * @param {string?} accessToken Access token used to authenticate. * @returns {Promise<Array<TimeIntervalMetric>>} */ getRulesEvaluationCount(startTime, endTime, accessToken = null) { return __awaiter(this, void 0, void 0, function* () { if (accessToken === null) { yield this.generateToken(false); } const filter = this.metricFilter("rules/evaluation_count"); const res = yield this.makeRequest(filter, startTime, endTime); const cleanTimeSeries = yield this.cleanResponseTimeSeries(res); return cleanTimeSeries; }); } /** * Get Firestore API calls count. * @param {DateTimeStringISO} startTime The beginning of the time interval. * @param {DateTimeStringISO} endTime The end of the time interval. * @param {string?} accessToken Access token used to authenticate. * @returns {Promise<Array<TimeIntervalMetric>>} */ getRequestCount(startTime, endTime, accessToken = null) { return __awaiter(this, void 0, void 0, function* () { if (accessToken === null) { yield this.generateToken(false); } const filter = this.metricFilter("api/request_count"); const res = yield this.makeRequest(filter, startTime, endTime); const cleanTimeSeries = yield this.cleanResponseTimeSeries(res); return cleanTimeSeries; }); } } exports.FirestoreMetrics = FirestoreMetrics; //# sourceMappingURL=index.js.map