"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.endpointMeteringService = exports.EndpointMeteringService = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _constants = require("@kbn/security-solution-plugin/common/endpoint/constants"); var _product = require("../../../common/product"); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ // 1 hour const SAMPLE_PERIOD_SECONDS = 3600; const THRESHOLD_MINUTES = 30; class EndpointMeteringService { constructor() { (0, _defineProperty2.default)(this, "tier", void 0); (0, _defineProperty2.default)(this, "getUsageRecords", async ({ taskId, cloudSetup, esClient, abortController, lastSuccessfulReport, config }) => { var _heartbeatsResponse$h; this.setTier(config); const heartbeatsResponse = await this.getHeartbeatsSince(esClient, abortController, lastSuccessfulReport); if (!(heartbeatsResponse !== null && heartbeatsResponse !== void 0 && (_heartbeatsResponse$h = heartbeatsResponse.hits) !== null && _heartbeatsResponse$h !== void 0 && _heartbeatsResponse$h.hits)) { return []; } if (!this.tier) { throw new Error(`no product tier information found for heartbeats: ${JSON.stringify(heartbeatsResponse.hits.hits)}`); } return heartbeatsResponse.hits.hits.reduce((acc, { _source }) => { var _cloudSetup$serverles; if (!_source) { return acc; } const { agent, event } = _source; const record = this.buildMeteringRecord({ agentId: agent.id, timestampStr: event.ingested, taskId, projectId: cloudSetup === null || cloudSetup === void 0 ? void 0 : (_cloudSetup$serverles = cloudSetup.serverless) === null || _cloudSetup$serverles === void 0 ? void 0 : _cloudSetup$serverles.projectId }); return [...acc, record]; }, []); }); } async getHeartbeatsSince(esClient, abortController, since) { const thresholdDate = new Date(Date.now() - THRESHOLD_MINUTES * 60 * 1000); const searchFrom = since && since > thresholdDate ? since : thresholdDate; return esClient.search({ index: _constants.ENDPOINT_HEARTBEAT_INDEX, sort: 'event.ingested', query: { range: { 'event.ingested': { gt: searchFrom.toISOString() } } } }, { signal: abortController.signal, ignore: [404] }); } buildMeteringRecord({ agentId, timestampStr, taskId, projectId = '' }) { const timestamp = new Date(timestampStr); timestamp.setMinutes(0); timestamp.setSeconds(0); timestamp.setMilliseconds(0); return { id: `endpoint-${agentId}-${timestamp}`, usage_timestamp: timestampStr, creation_timestamp: timestampStr, usage: { type: 'security_solution_endpoint', period_seconds: SAMPLE_PERIOD_SECONDS, quantity: 1 }, source: { id: taskId, instance_group_id: projectId, metadata: { tier: this.tier } } }; } setTier(config) { if (this.tier) { return; } const endpoint = config.productTypes.find(productType => productType.product_line === _product.ProductLine.endpoint); this.tier = endpoint === null || endpoint === void 0 ? void 0 : endpoint.product_tier; } } exports.EndpointMeteringService = EndpointMeteringService; const endpointMeteringService = new EndpointMeteringService(); exports.endpointMeteringService = endpointMeteringService;