• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / cli / 18718316541

22 Oct 2025 01:46PM UTC coverage: 54.587% (-0.02%) from 54.604%
18718316541

Pull #4334

github

web-flow
Merge 7159aa5e9 into 8d34a0f7e
Pull Request #4334: feat: command to analyze table read/write I/O patterns

14 of 24 new or added lines in 2 files covered. (58.33%)

7 existing lines in 2 files now uncovered.

6403 of 11730 relevant lines covered (54.59%)

6.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/cmd/inspect.go
1
package cmd
2

3
import (
4
        "os"
5
        "os/signal"
6

7
        "github.com/spf13/afero"
8
        "github.com/spf13/cobra"
9
        "github.com/supabase/cli/internal/inspect"
10
        "github.com/supabase/cli/internal/inspect/bloat"
11
        "github.com/supabase/cli/internal/inspect/blocking"
12
        "github.com/supabase/cli/internal/inspect/calls"
13
        "github.com/supabase/cli/internal/inspect/db_stats"
14
        "github.com/supabase/cli/internal/inspect/index_stats"
15
        "github.com/supabase/cli/internal/inspect/locks"
16
        "github.com/supabase/cli/internal/inspect/long_running_queries"
17
        "github.com/supabase/cli/internal/inspect/outliers"
18
        "github.com/supabase/cli/internal/inspect/replication_slots"
19
        "github.com/supabase/cli/internal/inspect/role_stats"
20
        "github.com/supabase/cli/internal/inspect/table_stats"
21
        "github.com/supabase/cli/internal/inspect/traffic_profile"
22
        "github.com/supabase/cli/internal/inspect/vacuum_stats"
23
        "github.com/supabase/cli/internal/utils/flags"
24
)
25

26
var (
27
        inspectCmd = &cobra.Command{
28
                GroupID: groupLocalDev,
29
                Use:     "inspect",
30
                Short:   "Tools to inspect your Supabase project",
31
        }
32

33
        inspectDBCmd = &cobra.Command{
34
                Use:   "db",
35
                Short: "Tools to inspect your Supabase database",
36
                PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
×
37
                        ctx, _ := signal.NotifyContext(cmd.Context(), os.Interrupt)
×
38
                        cmd.SetContext(ctx)
×
39
                        return cmd.Root().PersistentPreRunE(cmd, args)
×
40
                },
×
41
        }
42

43
        inspectDBStatsCmd = &cobra.Command{
44
                Use:   "db-stats",
45
                Short: "Show stats such as cache hit rates, total sizes, and WAL size",
46
                RunE: func(cmd *cobra.Command, args []string) error {
×
47
                        return db_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
48
                },
×
49
        }
50

51
        inspectReplicationSlotsCmd = &cobra.Command{
52
                Use:   "replication-slots",
53
                Short: "Show information about replication slots on the database",
54
                RunE: func(cmd *cobra.Command, args []string) error {
×
55
                        return replication_slots.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
56
                },
×
57
        }
58

59
        inspectLocksCmd = &cobra.Command{
60
                Use:   "locks",
61
                Short: "Show queries which have taken out an exclusive lock on a relation",
62
                RunE: func(cmd *cobra.Command, args []string) error {
×
63
                        return locks.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
64
                },
×
65
        }
66

67
        inspectBlockingCmd = &cobra.Command{
68
                Use:   "blocking",
69
                Short: "Show queries that are holding locks and the queries that are waiting for them to be released",
70
                RunE: func(cmd *cobra.Command, args []string) error {
×
71
                        return blocking.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
72
                },
×
73
        }
74

75
        inspectOutliersCmd = &cobra.Command{
76
                Use:   "outliers",
77
                Short: "Show queries from pg_stat_statements ordered by total execution time",
78
                RunE: func(cmd *cobra.Command, args []string) error {
×
79
                        return outliers.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
80
                },
×
81
        }
82

83
        inspectCallsCmd = &cobra.Command{
84
                Use:   "calls",
85
                Short: "Show queries from pg_stat_statements ordered by total times called",
86
                RunE: func(cmd *cobra.Command, args []string) error {
×
87
                        return calls.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
88
                },
×
89
        }
90

91
        inspectIndexStatsCmd = &cobra.Command{
92
                Use:   "index-stats",
93
                Short: "Show combined index size, usage percent, scan counts, and unused status",
94
                RunE: func(cmd *cobra.Command, args []string) error {
×
95
                        return index_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
96
                },
×
97
        }
98

99
        inspectLongRunningQueriesCmd = &cobra.Command{
100
                Use:   "long-running-queries",
101
                Short: "Show currently running queries running for longer than 5 minutes",
102
                RunE: func(cmd *cobra.Command, args []string) error {
×
103
                        return long_running_queries.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
104
                },
×
105
        }
106

107
        inspectBloatCmd = &cobra.Command{
108
                Use:   "bloat",
109
                Short: "Estimates space allocated to a relation that is full of dead tuples",
110
                RunE: func(cmd *cobra.Command, args []string) error {
×
111
                        return bloat.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
112
                },
×
113
        }
114

115
        inspectRoleStatsCmd = &cobra.Command{
116
                Use:   "role-stats",
117
                Short: "Show information about roles on the database",
118
                RunE: func(cmd *cobra.Command, args []string) error {
×
119
                        return role_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
120
                },
×
121
        }
122

123
        inspectVacuumStatsCmd = &cobra.Command{
124
                Use:   "vacuum-stats",
125
                Short: "Show statistics related to vacuum operations per table",
126
                RunE: func(cmd *cobra.Command, args []string) error {
×
127
                        return vacuum_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
128
                },
×
129
        }
130

131
        inspectTableStatsCmd = &cobra.Command{
132
                Use:   "table-stats",
133
                Short: "Show combined table size, index size, and estimated row count",
134
                RunE: func(cmd *cobra.Command, args []string) error {
×
135
                        return table_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
136
                },
×
137
        }
138

139
        inspectTrafficProfileCmd = &cobra.Command{
140
                Use:   "traffic-profile",
141
                Short: "Show read/write activity ratio for tables based on block I/O operations",
NEW
142
                RunE: func(cmd *cobra.Command, args []string) error {
×
NEW
143
                        return traffic_profile.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
NEW
144
                },
×
145
        }
146

147
        inspectCacheHitCmd = &cobra.Command{
148
                Deprecated: `use "db-stats" instead.`,
149
                Use:        "cache-hit",
150
                Short:      "Show cache hit rates for tables and indices",
151
                RunE: func(cmd *cobra.Command, args []string) error {
×
152
                        return db_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
153
                },
×
154
        }
155

156
        inspectIndexUsageCmd = &cobra.Command{
157
                Deprecated: `use "index-stats" instead.`,
158
                Use:        "index-usage",
159
                Short:      "Show information about the efficiency of indexes",
160
                RunE: func(cmd *cobra.Command, args []string) error {
×
161
                        return index_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
162
                },
×
163
        }
164

165
        inspectTotalIndexSizeCmd = &cobra.Command{
166
                Deprecated: `use "index-stats" instead.`,
167
                Use:        "total-index-size",
168
                Short:      "Show total size of all indexes",
169
                RunE: func(cmd *cobra.Command, args []string) error {
×
170
                        return index_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
171
                },
×
172
        }
173

174
        inspectIndexSizesCmd = &cobra.Command{
175
                Deprecated: `use "index-stats" instead.`,
176
                Use:        "index-sizes",
177
                Short:      "Show index sizes of individual indexes",
178
                RunE: func(cmd *cobra.Command, args []string) error {
×
179
                        return index_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
180
                },
×
181
        }
182

183
        inspectTableSizesCmd = &cobra.Command{
184
                Deprecated: `use "table-stats" instead.`,
185
                Use:        "table-sizes",
186
                Short:      "Show table sizes of individual tables without their index sizes",
187
                RunE: func(cmd *cobra.Command, args []string) error {
×
188
                        return table_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
189
                },
×
190
        }
191

192
        inspectTableIndexSizesCmd = &cobra.Command{
193
                Deprecated: `use "table-stats" instead.`,
194
                Use:        "table-index-sizes",
195
                Short:      "Show index sizes of individual tables",
196
                RunE: func(cmd *cobra.Command, args []string) error {
×
197
                        return table_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
198
                },
×
199
        }
200

201
        inspectTotalTableSizesCmd = &cobra.Command{
202
                Deprecated: `use "table-stats" instead.`,
203
                Use:        "total-table-sizes",
204
                Short:      "Show total table sizes, including table index sizes",
205
                RunE: func(cmd *cobra.Command, args []string) error {
×
206
                        return table_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
207
                },
×
208
        }
209

210
        inspectUnusedIndexesCmd = &cobra.Command{
211
                Deprecated: `use "index-stats" instead.`,
212
                Use:        "unused-indexes",
213
                Short:      "Show indexes with low usage",
214
                RunE: func(cmd *cobra.Command, args []string) error {
×
215
                        return index_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
216
                },
×
217
        }
218

219
        inspectTableRecordCountsCmd = &cobra.Command{
220
                Deprecated: `use "table-stats" instead.`,
221
                Use:        "table-record-counts",
222
                Short:      "Show estimated number of rows per table",
223
                RunE: func(cmd *cobra.Command, args []string) error {
×
224
                        return index_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
225
                },
×
226
        }
227

228
        inspectSeqScansCmd = &cobra.Command{
229
                Deprecated: `use "index-stats" instead.`,
230
                Use:        "seq-scans",
231
                Short:      "Show number of sequential scans recorded against all tables",
232
                RunE: func(cmd *cobra.Command, args []string) error {
×
233
                        return index_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
234
                },
×
235
        }
236

237
        inspectRoleConfigsCmd = &cobra.Command{
238
                Deprecated: `use "role-stats" instead.`,
239
                Use:        "role-configs",
240
                Short:      "Show configuration settings for database roles when they have been modified",
241
                RunE: func(cmd *cobra.Command, args []string) error {
×
242
                        return role_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
243
                },
×
244
        }
245

246
        inspectRoleConnectionsCmd = &cobra.Command{
247
                Deprecated: `use "role-stats" instead.`,
248
                Use:        "role-connections",
249
                Short:      "Show number of active connections for all database roles",
250
                RunE: func(cmd *cobra.Command, args []string) error {
×
251
                        return role_stats.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
×
252
                },
×
253
        }
254

255
        outputDir string
256

257
        reportCmd = &cobra.Command{
258
                Use:   "report",
259
                Short: "Generate a CSV output for all inspect commands",
260
                RunE: func(cmd *cobra.Command, args []string) error {
×
261
                        return inspect.Report(cmd.Context(), outputDir, flags.DbConfig, afero.NewOsFs())
×
262
                },
×
263
        }
264
)
265

266
func init() {
×
267
        inspectFlags := inspectCmd.PersistentFlags()
×
268
        inspectFlags.String("db-url", "", "Inspect the database specified by the connection string (must be percent-encoded).")
×
269
        inspectFlags.Bool("linked", true, "Inspect the linked project.")
×
270
        inspectFlags.Bool("local", false, "Inspect the local database.")
×
271
        inspectCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
272
        inspectDBCmd.AddCommand(inspectReplicationSlotsCmd)
×
273
        inspectDBCmd.AddCommand(inspectIndexStatsCmd)
×
274
        inspectDBCmd.AddCommand(inspectLocksCmd)
×
275
        inspectDBCmd.AddCommand(inspectBlockingCmd)
×
276
        inspectDBCmd.AddCommand(inspectOutliersCmd)
×
277
        inspectDBCmd.AddCommand(inspectCallsCmd)
×
278
        inspectDBCmd.AddCommand(inspectLongRunningQueriesCmd)
×
279
        inspectDBCmd.AddCommand(inspectBloatCmd)
×
280
        inspectDBCmd.AddCommand(inspectVacuumStatsCmd)
×
281
        inspectDBCmd.AddCommand(inspectTableStatsCmd)
×
NEW
282
        inspectDBCmd.AddCommand(inspectTrafficProfileCmd)
×
283
        inspectDBCmd.AddCommand(inspectRoleStatsCmd)
×
284
        inspectDBCmd.AddCommand(inspectDBStatsCmd)
×
285
        // DEPRECATED
×
286
        inspectDBCmd.AddCommand(inspectCacheHitCmd)
×
287
        inspectDBCmd.AddCommand(inspectIndexUsageCmd)
×
288
        inspectDBCmd.AddCommand(inspectSeqScansCmd)
×
289
        inspectDBCmd.AddCommand(inspectUnusedIndexesCmd)
×
290
        inspectDBCmd.AddCommand(inspectTotalTableSizesCmd)
×
291
        inspectDBCmd.AddCommand(inspectTableIndexSizesCmd)
×
292
        inspectDBCmd.AddCommand(inspectTotalIndexSizeCmd)
×
293
        inspectDBCmd.AddCommand(inspectIndexSizesCmd)
×
294
        inspectDBCmd.AddCommand(inspectTableSizesCmd)
×
295
        inspectDBCmd.AddCommand(inspectTableRecordCountsCmd)
×
296
        inspectDBCmd.AddCommand(inspectRoleConfigsCmd)
×
297
        inspectDBCmd.AddCommand(inspectRoleConnectionsCmd)
×
298
        inspectCmd.AddCommand(inspectDBCmd)
×
299
        reportCmd.Flags().StringVar(&outputDir, "output-dir", ".", "Path to save CSV files in")
×
300
        inspectCmd.AddCommand(reportCmd)
×
301
        rootCmd.AddCommand(inspectCmd)
×
302
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc