"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.registerStatusRoute = void 0; var _rxjs = require("rxjs"); var _configSchema = require("@kbn/config-schema"); var _coreStatusCommon = require("@kbn/core-status-common"); var _legacy_status = require("../legacy_status"); /* * 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 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ const SNAPSHOT_POSTFIX = /-SNAPSHOT$/; const registerStatusRoute = ({ router, config, metrics, status, incrementUsageCounter }) => { // Since the status.plugins$ observable is not subscribed to elsewhere, we need to subscribe it here to eagerly load // the plugins status when Kibana starts up so this endpoint responds quickly on first boot. const combinedStatus$ = new _rxjs.ReplaySubject(1); (0, _rxjs.combineLatest)([status.overall$, status.coreOverall$, status.core$, status.plugins$]).subscribe(combinedStatus$); router.get({ path: '/api/status', options: { authRequired: 'optional', tags: ['api'], // ensures that unauthenticated calls receive a 401 rather than a 302 redirect to login page access: 'public' // needs to be public to allow access from "system" users like k8s readiness probes. }, validate: { query: _configSchema.schema.object({ v7format: _configSchema.schema.maybe(_configSchema.schema.boolean()), v8format: _configSchema.schema.maybe(_configSchema.schema.boolean()) }, { validate: ({ v7format, v8format }) => { if (typeof v7format === 'boolean' && typeof v8format === 'boolean') { return `provide only one format option: v7format or v8format`; } } }) } }, async (context, req, res) => { const authRequired = !config.allowAnonymous; const isAuthenticated = req.auth.isAuthenticated; const redactedStatus = authRequired && !isAuthenticated; const [overall, coreOverall, core, plugins] = await (0, _rxjs.firstValueFrom)(combinedStatus$); const responseBody = redactedStatus ? getRedactedStatusResponse({ coreOverall }) : await getFullStatusResponse({ incrementUsageCounter, config, query: req.query, metrics, statuses: { overall, core, plugins } }); const statusCode = coreOverall.level >= _coreStatusCommon.ServiceStatusLevels.unavailable ? 503 : 200; return res.custom({ body: responseBody, statusCode, bypassErrorFormat: true }); }); }; exports.registerStatusRoute = registerStatusRoute; const getFullStatusResponse = async ({ config, incrementUsageCounter, metrics, statuses: { plugins, overall, core }, query: { v7format = false, v8format = true } }) => { const { version, buildSha, buildNum, buildDate } = config.packageInfo; const versionWithoutSnapshot = version.replace(SNAPSHOT_POSTFIX, ''); let statusInfo; if (!v7format && v8format) { statusInfo = { overall, core, plugins }; } else { incrementUsageCounter({ counterName: 'status_v7format' }); statusInfo = (0, _legacy_status.calculateLegacyStatus)({ overall, core, plugins, versionWithoutSnapshot }); } const lastMetrics = await (0, _rxjs.firstValueFrom)(metrics.getOpsMetrics$()); const body = { name: config.serverName, uuid: config.uuid, version: { number: versionWithoutSnapshot, build_hash: buildSha, build_number: buildNum, build_snapshot: SNAPSHOT_POSTFIX.test(version), build_date: buildDate.toISOString() }, status: statusInfo, metrics: { last_updated: lastMetrics.collected_at.toISOString(), collection_interval_in_millis: metrics.collectionInterval, os: lastMetrics.os, process: lastMetrics.process, processes: lastMetrics.processes, response_times: lastMetrics.response_times, concurrent_connections: lastMetrics.concurrent_connections, requests: { ...lastMetrics.requests, status_codes: lastMetrics.requests.statusCodes }, elasticsearch_client: lastMetrics.elasticsearch_client } }; return body; }; const getRedactedStatusResponse = ({ coreOverall }) => { const body = { status: { overall: { level: coreOverall.level } } }; return body; };