From 78f3d4251e21f9052123d1e82121107c9ce6bab3 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 11 Oct 2024 09:11:43 -0700 Subject: [PATCH] Add telemetry info command (#3034) --- packages/cli/src/commands/telemetry/info.ts | 35 ++++++++ .../unit/commands/telemetry/info.unit.test.ts | 83 +++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 packages/cli/src/commands/telemetry/info.ts create mode 100644 packages/cli/test/unit/commands/telemetry/info.unit.test.ts diff --git a/packages/cli/src/commands/telemetry/info.ts b/packages/cli/src/commands/telemetry/info.ts new file mode 100644 index 0000000000..d39907cf4a --- /dev/null +++ b/packages/cli/src/commands/telemetry/info.ts @@ -0,0 +1,35 @@ +import {Command} from '@heroku-cli/command' +import {Args, ux} from '@oclif/core' +import {TelemetryDrain} from '../../lib/types/telemetry' + +export default class Info extends Command { + static topic = 'telemetry' + static description = 'show a telemetry drain\'s info' + static args = { + telemetry_drain_id: Args.string({required: true, description: 'ID of the drain to show info for'}), + }; + + public async run(): Promise { + const {args} = await this.parse(Info) + const {telemetry_drain_id} = args + + const {body: telemetryDrain} = await this.heroku.get(`/telemetry-drains/${telemetry_drain_id}`, { + headers: { + Accept: 'application/vnd.heroku+json; version=3.fir', + }, + }) + this.display(telemetryDrain) + } + + protected display(telemetryDrain: TelemetryDrain) { + ux.styledHeader(telemetryDrain.id) + const drainType = telemetryDrain.owner.type.charAt(0).toUpperCase() + telemetryDrain.owner.type.slice(1) + ux.styledObject({ + [drainType]: telemetryDrain.owner.name, + Signals: telemetryDrain.capabilities.join(', '), + Endpoint: telemetryDrain.exporter.endpoint, + Kind: telemetryDrain.exporter.type, + Headers: telemetryDrain.exporter.headers, + }, ['App', 'Space', 'Signals', 'Endpoint', 'Kind', 'Headers']) + } +} diff --git a/packages/cli/test/unit/commands/telemetry/info.unit.test.ts b/packages/cli/test/unit/commands/telemetry/info.unit.test.ts new file mode 100644 index 0000000000..39db9ac1e6 --- /dev/null +++ b/packages/cli/test/unit/commands/telemetry/info.unit.test.ts @@ -0,0 +1,83 @@ +import {stdout} from 'stdout-stderr' +import Cmd from '../../../../src/commands/telemetry/info' +import runCommand from '../../../helpers/runCommand' +import * as nock from 'nock' +import expectOutput from '../../../helpers/utils/expectOutput' +import heredoc from 'tsheredoc' +import {TelemetryDrain} from '../../../../src/lib/types/telemetry' + +describe('telemetry:info', function () { + const appId = '87654321-5717-4562-b3fc-2c963f66afa6' + const spaceId = '12345678-5717-4562-b3fc-2c963f66afa6' + let appTelemetryDrain: TelemetryDrain + let spaceTelemetryDrain: TelemetryDrain + + beforeEach(function () { + spaceTelemetryDrain = { + id: '44444321-5717-4562-b3fc-2c963f66afa6', + owner: {id: spaceId, type: 'space', name: 'myspace'}, + capabilities: ['traces', 'metrics', 'logs'], + exporter: { + type: 'otlphttp', + endpoint: 'https://api.honeycomb.io/', + headers: { + 'x-honeycomb-team': 'your-api-key', + 'x-honeycomb-dataset': 'your-dataset', + }, + }, + } + appTelemetryDrain = { + id: '3fa85f64-5717-4562-b3fc-2c963f66afa6', + owner: {id: appId, type: 'app', name: 'myapp'}, + capabilities: ['traces', 'metrics'], + exporter: { + type: 'otlphttp', + endpoint: 'https://api.honeycomb.io/', + headers: { + 'x-honeycomb-team': 'your-api-key', + 'x-honeycomb-dataset': 'your-dataset', + }, + }, + } + }) + + afterEach(function () { + return nock.cleanAll() + }) + + it('shows info for space telemetry drain', async function () { + nock('https://api.heroku.com', {reqheaders: {Accept: 'application/vnd.heroku+json; version=3.fir'}}) + .get(`/telemetry-drains/${spaceTelemetryDrain.id}`) + .reply(200, spaceTelemetryDrain) + + await runCommand(Cmd, [ + spaceTelemetryDrain.id, + ]) + expectOutput(stdout.output, heredoc(` + === ${spaceTelemetryDrain.id} + Space: ${spaceTelemetryDrain.owner.name} + Signals: ${spaceTelemetryDrain.capabilities.join(', ')} + Endpoint: ${spaceTelemetryDrain.exporter.endpoint} + Kind: ${spaceTelemetryDrain.exporter.type} + Headers: x-honeycomb-team: 'your-api-key', x-honeycomb-dataset: 'your-dataset' + `)) + }) + + it('shows info for app telemetry drains', async function () { + nock('https://api.heroku.com', {reqheaders: {Accept: 'application/vnd.heroku+json; version=3.fir'}}) + .get(`/telemetry-drains/${appTelemetryDrain.id}`) + .reply(200, appTelemetryDrain) + + await runCommand(Cmd, [ + appTelemetryDrain.id, + ]) + expectOutput(stdout.output, heredoc(` + === ${appTelemetryDrain.id} + App: ${appTelemetryDrain.owner.name} + Signals: ${appTelemetryDrain.capabilities.join(', ')} + Endpoint: ${appTelemetryDrain.exporter.endpoint} + Kind: ${appTelemetryDrain.exporter.type} + Headers: x-honeycomb-team: 'your-api-key', x-honeycomb-dataset: 'your-dataset' + `)) + }) +})