1 | 'use strict'
|
2 |
|
3 | const cli = require('heroku-cli-util')
|
4 | const { capitalize } = require('lodash')
|
5 | const PGDIAGNOSE_HOST = process.env.PGDIAGNOSE_URL || 'https://pgdiagnose.herokai.com'
|
6 |
|
7 | async function run(context, heroku) {
|
8 | const fetcher = require('../lib/fetcher')(heroku)
|
9 | const host = require('../lib/host')
|
10 | const util = require('../lib/util')
|
11 | const URL = require('url')
|
12 | const uuid = require('uuid')
|
13 |
|
14 | const { app, args, flags } = context
|
15 |
|
16 | let generateParams = async function (url, db, dbName) {
|
17 | let base_params = {
|
18 | url: URL.format(url),
|
19 | plan: db.plan.name.split(':')[1],
|
20 | app: db.app.name,
|
21 | database: dbName,
|
22 | }
|
23 |
|
24 | if (!util.starterPlan(db)) {
|
25 | base_params.metrics = await heroku.get(`/client/v11/databases/${db.id}/metrics`, { host: host(db) })
|
26 | let burstData = await heroku.get(`/client/v11/databases/${db.id}/burst_status`, { host: host(db) })
|
27 | if (burstData && Object.keys(burstData).length !== 0) {
|
28 | base_params.burst_data_present = true
|
29 | base_params.burst_status = burstData.burst_status
|
30 | }
|
31 | }
|
32 |
|
33 | return base_params
|
34 | }
|
35 |
|
36 | let generateReport = async function (database) {
|
37 | let attachment = await fetcher.attachment(app, database)
|
38 | const { addon: db } = attachment
|
39 | let config = await heroku.get(`/apps/${app}/config-vars`)
|
40 |
|
41 | const { url } = util.getConnectionDetails(attachment, config)
|
42 | const dbName = util.getConfigVarNameFromAttachment(attachment, config)
|
43 |
|
44 | let params = await generateParams(url, db, dbName)
|
45 | return await heroku.post('/reports', {
|
46 | host: PGDIAGNOSE_HOST,
|
47 | body: params,
|
48 | });
|
49 | }
|
50 |
|
51 | let displayReport = (report) => {
|
52 | if (flags.json) {
|
53 | cli.styledJSON(report)
|
54 | return
|
55 | }
|
56 |
|
57 | cli.log(`Report ${report.id} for ${report.app}::${report.database}
|
58 | available for one month after creation on ${report.created_at}
|
59 | `)
|
60 | let display = (checks) => {
|
61 | checks.forEach((check) => {
|
62 | let color = cli.color[check.status] || ((txt) => txt)
|
63 | cli.log(color(`${check.status.toUpperCase()}: ${check.name}`))
|
64 |
|
65 | if (check.status === 'green') return
|
66 | if (!check.results) return
|
67 |
|
68 | if (Array.isArray(check.results)) {
|
69 | if (!check.results.length) return
|
70 |
|
71 | let keys = Object.keys(check.results[0])
|
72 | cli.table(check.results, {
|
73 | columns: keys.map((key) => ({ label: capitalize(key), key: key })),
|
74 | })
|
75 | } else {
|
76 | if (!Object.keys(check.results).length) return
|
77 |
|
78 | let key = Object.keys(check.results)[0]
|
79 | cli.log(
|
80 | `${key
|
81 | .split('_')
|
82 | .map((s) => capitalize(s))
|
83 | .join(' ')} ${check.results[key]}`,
|
84 | )
|
85 | }
|
86 | })
|
87 | }
|
88 | display(report.checks.filter((c) => c.status === 'red'))
|
89 | display(report.checks.filter((c) => c.status === 'yellow'))
|
90 | display(report.checks.filter((c) => c.status === 'green'))
|
91 | display(report.checks.filter((c) => !['red', 'yellow', 'green'].find((d) => d === c.status)))
|
92 | }
|
93 |
|
94 | let report
|
95 | let id = args['DATABASE|REPORT_ID']
|
96 | if (id && uuid.validate(id)) {
|
97 | report = await heroku.get(`/reports/${encodeURIComponent(id)}`, { host: PGDIAGNOSE_HOST })
|
98 | } else {
|
99 | report = await generateReport(id)
|
100 | }
|
101 |
|
102 | displayReport(report)
|
103 | }
|
104 |
|
105 | module.exports = {
|
106 | topic: 'pg',
|
107 | command: 'diagnose',
|
108 | description: 'run or view diagnostics report',
|
109 | help: `
|
110 | defaults to DATABASE_URL database if no DATABASE is specified
|
111 | if REPORT_ID is specified instead, a previous report is displayed
|
112 | `,
|
113 | needsApp: true,
|
114 | needsAuth: true,
|
115 | args: [{ name: 'DATABASE|REPORT_ID', optional: true }],
|
116 | flags: [{ name: 'json', description: "format output as JSON", hasValue: false }],
|
117 | run: cli.command({ preauth: true }, run),
|
118 | }
|