"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.CloudExperimentsPlugin = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _lodash = require("lodash"); var _moment = require("moment"); var _rxjs = require("rxjs"); var _launch_darkly_client = require("./launch_darkly_client"); var _metadata_service = require("../common/metadata_service"); var _constants = require("../common/constants"); /* * 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. */ /** * Browser-side implementation of the Cloud Experiments plugin */ class CloudExperimentsPlugin { /** Constructor of the plugin **/ constructor(initializerContext) { (0, _defineProperty2.default)(this, "metadataService", void 0); (0, _defineProperty2.default)(this, "launchDarklyClient", void 0); (0, _defineProperty2.default)(this, "kibanaVersion", void 0); (0, _defineProperty2.default)(this, "flagOverrides", void 0); (0, _defineProperty2.default)(this, "isDev", void 0); (0, _defineProperty2.default)(this, "getVariation", async (featureFlagName, defaultValue) => { const configKey = _constants.FEATURE_FLAG_NAMES[featureFlagName]; // Apply overrides if they exist without asking LaunchDarkly. if (this.flagOverrides && (0, _lodash.has)(this.flagOverrides, configKey)) { return (0, _lodash.get)(this.flagOverrides, configKey, defaultValue); } // Skip any action if no LD Client is defined if (!this.launchDarklyClient) { return defaultValue; } return await this.launchDarklyClient.getVariation(configKey, defaultValue); }); (0, _defineProperty2.default)(this, "reportMetric", ({ name, meta, value }) => { var _this$launchDarklyCli; const metricName = _constants.METRIC_NAMES[name]; (_this$launchDarklyCli = this.launchDarklyClient) === null || _this$launchDarklyCli === void 0 ? void 0 : _this$launchDarklyCli.reportMetric(metricName, meta, value); if (this.isDev) { // eslint-disable-next-line no-console console.debug(`Reported experimentation metric ${metricName}`, { experimentationMetric: { name, meta, value } }); } }); this.isDev = initializerContext.env.mode.dev; this.kibanaVersion = initializerContext.env.packageInfo.version; const config = initializerContext.config.get(); this.metadataService = new _metadata_service.MetadataService({ metadata_refresh_interval: (0, _moment.duration)(config.metadata_refresh_interval) }); if (config.flag_overrides) { this.flagOverrides = config.flag_overrides; } const ldConfig = config.launch_darkly; if (!(ldConfig !== null && ldConfig !== void 0 && ldConfig.client_id) && !initializerContext.env.mode.dev) { // If the plugin is enabled, and it's in prod mode, launch_darkly must exist // (config-schema should enforce it, but just in case). throw new Error('xpack.cloud_integrations.experiments.launch_darkly configuration should exist'); } if (ldConfig !== null && ldConfig !== void 0 && ldConfig.client_id) { this.launchDarklyClient = new _launch_darkly_client.LaunchDarklyClient(ldConfig, this.kibanaVersion); } } /** * Sets up the A/B testing client only if cloud is enabled * @param core {@link CoreSetup} * @param deps {@link CloudExperimentsPluginSetupDeps} */ setup(core, deps) { if (deps.cloud.isCloudEnabled && deps.cloud.deploymentId && this.launchDarklyClient) { var _deps$cloud$trialEndD; this.metadataService.setup({ userId: deps.cloud.deploymentId, kibanaVersion: this.kibanaVersion, trialEndDate: (_deps$cloud$trialEndD = deps.cloud.trialEndDate) === null || _deps$cloud$trialEndD === void 0 ? void 0 : _deps$cloud$trialEndD.toISOString(), isElasticStaff: deps.cloud.isElasticStaffOwned }); } } /** * Returns the contract {@link CloudExperimentsPluginStart} * @param core {@link CoreStart} */ start(core, { cloud, dataViews }) { if (cloud.isCloudEnabled) { this.metadataService.start({ hasDataFetcher: async () => ({ hasData: await dataViews.hasData.hasUserDataView() }) }); // We only subscribe to the user metadata updates if Cloud is enabled. // This way, since the user is not identified, it cannot retrieve Feature Flags from LaunchDarkly when not running on Cloud. this.metadataService.userMetadata$.pipe( // Using concatMap to ensure we call the promised update in an orderly manner to avoid concurrency issues (0, _rxjs.concatMap)(async userMetadata => await this.launchDarklyClient.updateUserMetadata(userMetadata))).subscribe(); // This subscription will stop on when the metadataService stops because it completes the Observable } return { getVariation: this.getVariation, reportMetric: this.reportMetric }; } /** * Cleans up and flush the sending queues. */ stop() { var _this$launchDarklyCli2; (_this$launchDarklyCli2 = this.launchDarklyClient) === null || _this$launchDarklyCli2 === void 0 ? void 0 : _this$launchDarklyCli2.stop(); this.metadataService.stop(); } } exports.CloudExperimentsPlugin = CloudExperimentsPlugin;