Skip to content

Commit

Permalink
Add test for telemetry:update, fix grpc spelling, display drain after…
Browse files Browse the repository at this point in the history
… update
  • Loading branch information
eablack committed Oct 22, 2024
1 parent d872812 commit 1adcf02
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 21 deletions.
1 change: 0 additions & 1 deletion cspell-dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ Gdvb
getreqs
Ghpcy
githuborg
gprc
hamurai
herokai
herokuapp
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/telemetry/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default class Add extends Command {
space: Flags.string({char: 's', description: 'space to add a drain to'}),
signal: Flags.string({default: 'all', description: 'comma-delimited list of signals to collect (traces, metrics, logs). Use "all" to collect all signals.'}),
endpoint: Flags.string({required: true, description: 'drain url'}),
transport: Flags.string({required: true, options: ['http', 'gprc'], description: 'transport protocol for the drain'}),
transport: Flags.string({required: true, options: ['http', 'grpc'], description: 'transport protocol for the drain'}),
}

static args = {
Expand Down
18 changes: 3 additions & 15 deletions packages/cli/src/commands/telemetry/info.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Command} from '@heroku-cli/command'
import {Args, ux} from '@oclif/core'
import {Args} from '@oclif/core'
import {TelemetryDrain} from '../../lib/types/telemetry'

import {displayTelemetryDrain} from '../../lib/telemetry/util'
export default class Info extends Command {
static topic = 'telemetry'
static description = 'show a telemetry drain\'s info'
Expand All @@ -18,18 +18,6 @@ export default class Info extends Command {
Accept: 'application/vnd.heroku+json; version=3.sdk',
},
})
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.signals.join(', '),
Endpoint: telemetryDrain.exporter.endpoint,
Kind: telemetryDrain.exporter.type,
Headers: telemetryDrain.exporter.headers,
}, ['App', 'Space', 'Signals', 'Endpoint', 'Kind', 'Headers'])
displayTelemetryDrain(telemetryDrain)
}
}
10 changes: 6 additions & 4 deletions packages/cli/src/commands/telemetry/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {flags as Flags, Command} from '@heroku-cli/command'
import {Args, ux} from '@oclif/core'
import {TelemetryDrain, TelemetryDrainWithOptionalKeys, TelemetryExporterWithOptionalKeys} from '../../lib/types/telemetry'
import heredoc from 'tsheredoc'
import {validateAndFormatSignal} from '../../lib/telemetry/util'
import {displayTelemetryDrain, validateAndFormatSignal} from '../../lib/telemetry/util'

export default class Update extends Command {
static topic = 'telemetry'
Expand All @@ -13,9 +13,9 @@ export default class Update extends Command {
}

static flags = {
signal: Flags.string({default: 'all', description: 'comma-delimited list of signals to collect (traces, metrics, logs). Use "all" to collect all signals.'}),
signal: Flags.string({description: 'comma-delimited list of signals to collect (traces, metrics, logs). Use "all" to collect all signals.'}),
endpoint: Flags.string({description: 'drain url'}),
transport: Flags.string({options: ['http', 'gprc'], description: 'transport protocol for the drain'}),
transport: Flags.string({options: ['http', 'grpc'], description: 'transport protocol for the drain'}),
}

public async run(): Promise<void> {
Expand Down Expand Up @@ -51,13 +51,15 @@ export default class Update extends Command {
drainConfig.exporter = exporter
}

ux.action.start(`Updating telemetry drain ${telemetry_drain_id}`)
const {body: telemetryDrain} = await this.heroku.patch<TelemetryDrain>(`/telemetry-drains/${telemetry_drain_id}`, {
headers: {
Accept: 'application/vnd.heroku+json; version=3.sdk',
},
body: drainConfig,
})
ux.action.start(`Updating telemetry drain ${telemetry_drain_id}, which was configured for ${telemetryDrain.owner.type} ${telemetryDrain.owner.name}`)
ux.action.stop()

displayTelemetryDrain(telemetryDrain)
}
}
13 changes: 13 additions & 0 deletions packages/cli/src/lib/telemetry/util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {ux} from '@oclif/core'
import {TelemetryDrain} from '../types/telemetry'

export function validateAndFormatSignal(signalInput: string | undefined): string[] {
const signalOptions = ['traces', 'metrics', 'logs']
Expand All @@ -11,3 +12,15 @@ export function validateAndFormatSignal(signalInput: string | undefined): string
})
return signalArray
}

export function displayTelemetryDrain(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.signals.join(', '),
Endpoint: telemetryDrain.exporter.endpoint,
Kind: telemetryDrain.exporter.type,
Headers: telemetryDrain.exporter.headers,
}, ['App', 'Space', 'Signals', 'Endpoint', 'Kind', 'Headers'])
}
92 changes: 92 additions & 0 deletions packages/cli/test/unit/commands/telemetry/update.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {stderr, stdout} from 'stdout-stderr'
import Cmd from '../../../../src/commands/telemetry/update'
import runCommand from '../../../helpers/runCommand'
import * as nock from 'nock'
import expectOutput from '../../../helpers/utils/expectOutput'
import heredoc from 'tsheredoc'
import {expect} from 'chai'
import {appTelemetryDrain1} from '../../../fixtures/telemetry/fixtures'

describe('telemetry:update', function () {
afterEach(function () {
return nock.cleanAll()
})

it('updates a telemetry drain with one field', async function () {
const updatedAppTelemetryDrain = {...appTelemetryDrain1, signals: ['logs']}
nock('https://api.heroku.com', {reqheaders: {Accept: 'application/vnd.heroku+json; version=3.sdk'}})
.patch(`/telemetry-drains/${appTelemetryDrain1.id}`, {signals: ['logs']})
.reply(200, updatedAppTelemetryDrain)

await runCommand(Cmd, [
appTelemetryDrain1.id,
'--signal',
'logs',
])
expectOutput(stderr.output, heredoc(`
Updating telemetry drain ${appTelemetryDrain1.id}...
Updating telemetry drain ${appTelemetryDrain1.id}... done
`))
expectOutput(stdout.output, heredoc(`
=== ${updatedAppTelemetryDrain.id}
App: ${updatedAppTelemetryDrain.owner.name}
Signals: ${updatedAppTelemetryDrain.signals.join(', ')}
Endpoint: ${updatedAppTelemetryDrain.exporter.endpoint}
Kind: ${updatedAppTelemetryDrain.exporter.type}
Headers: x-honeycomb-team: 'your-api-key', x-honeycomb-dataset: 'your-dataset'
`))
})

it('updates a telemetry drain with multiple fields', async function () {
const updatedAppTelemetryDrain = {
...appTelemetryDrain1,
signals: ['logs'],
exporter: {
endpoint: 'https://api-new.honeycomb.io/',
type: 'otlpgrpc',
headers: {
'x-honeycomb-team': 'your-api-key',
'x-honeycomb-dataset': 'your-dataset',
},
},
}
nock('https://api.heroku.com', {reqheaders: {Accept: 'application/vnd.heroku+json; version=3.sdk'}})
.patch(`/telemetry-drains/${appTelemetryDrain1.id}`, {
signals: ['logs'],
exporter: {
endpoint: 'https://api-new.honeycomb.io/',
type: 'otlpgrpc',
},
})
.reply(200, updatedAppTelemetryDrain)

await runCommand(Cmd, [
appTelemetryDrain1.id,
'--signal',
'logs',
'--endpoint',
'https://api-new.honeycomb.io/',
'--transport',
'grpc',
])
expectOutput(stderr.output, heredoc(`
Updating telemetry drain ${appTelemetryDrain1.id}...
Updating telemetry drain ${appTelemetryDrain1.id}... done
`))
expectOutput(stdout.output, heredoc(`
=== ${updatedAppTelemetryDrain.id}
App: ${updatedAppTelemetryDrain.owner.name}
Signals: ${updatedAppTelemetryDrain.signals.join(', ')}
Endpoint: ${updatedAppTelemetryDrain.exporter.endpoint}
Kind: ${updatedAppTelemetryDrain.exporter.type}
Headers: x-honeycomb-team: 'your-api-key', x-honeycomb-dataset: 'your-dataset'
`))
})

it('requires an updated attribute to be provided', async function () {
const errorMessage = 'Requires either --signal, --endpoint, --transport or HEADERS to be provided.'
await runCommand(Cmd, [appTelemetryDrain1.id]).catch(error => {
expect(error.message).to.contain(errorMessage)
})
})
})

0 comments on commit 1adcf02

Please sign in to comment.