Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/cli-go/cmd/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@ without the envelope.`,
outputFormat = "table"
}
}
// db query resolves --output into a command-local flag, so mirror the
// resolved value onto the global that telemetry's output_format reads.
utils.OutputFormat.Value = outputFormat
if flag := cmd.Flags().Lookup("linked"); flag != nil && flag.Changed {
return query.RunLinked(cmd.Context(), sql, flags.ProjectRef, outputFormat, agentMode, os.Stdout)
}
Expand Down
5 changes: 3 additions & 2 deletions apps/cli-go/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,9 @@ func Execute() {
if service := telemetry.FromContext(executedCmd.Context()); service != nil {
ensureProjectGroupsCached(executedCmd.Context(), service)
_ = service.Capture(executedCmd.Context(), telemetry.EventCommandExecuted, map[string]any{
telemetry.PropExitCode: exitCode(err),
telemetry.PropDurationMs: time.Since(startedAt).Milliseconds(),
telemetry.PropExitCode: exitCode(err),
telemetry.PropDurationMs: time.Since(startedAt).Milliseconds(),
telemetry.PropOutputFormat: utils.OutputFormat.Value,
}, nil)
_ = service.Close()
}
Expand Down
11 changes: 8 additions & 3 deletions apps/cli-go/internal/telemetry/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import "context"
const (
// - EventCommandExecuted: sent after a CLI command finishes, whether it
// succeeds or fails. This helps measure command usage, failure rates, and
// runtime. Event-specific properties are PropExitCode (process exit code)
// and PropDurationMs (command runtime in milliseconds). Related groups:
// none added directly by this event.
// runtime. Event-specific properties are PropExitCode (process exit code),
// PropDurationMs (command runtime in milliseconds), and PropOutputFormat
// (the resolved output format the command used). Related groups: none
// added directly by this event.
EventCommandExecuted = "cli_command_executed"
// - EventProjectLinked: sent after the local CLI directory is linked to a
// Supabase project. This helps measure project-linking adoption and connect
Expand Down Expand Up @@ -109,6 +110,10 @@ const (
PropExitCode = "exit_code"
// PropDurationMs is the command runtime in milliseconds.
PropDurationMs = "duration_ms"
// PropOutputFormat is the resolved output format the command used (for
// example "pretty", "json", "yaml"), after agent auto-detection and any
// command-local override are applied.
PropOutputFormat = "output_format"
)

// Group identifiers associate events with higher-level entities in PostHog.
Expand Down
2 changes: 1 addition & 1 deletion apps/cli/src/legacy/telemetry/legacy-analytics.layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export const legacyAnalyticsLayer = Layer.effect(

const loadLinkedProject = makeLoadLinkedProject(fs, path);

const isAgent = Option.isSome(aiTool.name) || runtime.isCi;
const isAgent = Option.isSome(aiTool.name);
const envSignals = collectEnvSignals();

const baseProperties = stripUndefined({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import {
getCommandRuntimeCommand,
getCommandRuntimeSpanName,
} from "../../shared/runtime/command-runtime.service.ts";
import { Output } from "../../shared/output/output.service.ts";
import { withAnalyticsContext } from "../../shared/telemetry/analytics-context.ts";
import { Analytics } from "../../shared/telemetry/analytics.service.ts";
import {
EventCommandExecuted,
PropDurationMs,
PropExitCode,
PropOutputFormat,
} from "../../shared/telemetry/event-catalog.ts";

interface LegacyCommandInstrumentationOptions<Flags extends Record<string, unknown> = never> {
Expand Down Expand Up @@ -114,6 +116,7 @@ function withLegacyCommandAnalyticsImplementation<Flags extends Record<string, u
});

const analytics = yield* Analytics;
const output = yield* Output;
const stdio = yield* Stdio.Stdio;
const args = yield* stdio.args;
const startedAt = yield* Clock.currentTimeMillis;
Expand All @@ -132,6 +135,7 @@ function withLegacyCommandAnalyticsImplementation<Flags extends Record<string, u
.capture(EventCommandExecuted, {
[PropExitCode]: Exit.isSuccess(exit) ? 0 : 1,
[PropDurationMs]: finishedAt - startedAt,
[PropOutputFormat]: output.format,
})
.pipe(withAnalyticsContext(analyticsContext));

Expand All @@ -145,12 +149,12 @@ function withLegacyCommandAnalyticsImplementation<Flags extends Record<string, u

export function withLegacyCommandInstrumentation(): <A, E, R>(
self: Effect.Effect<A, E, R>,
) => Effect.Effect<A, E, R | Analytics | CommandRuntime | Stdio.Stdio>;
) => Effect.Effect<A, E, R | Analytics | CommandRuntime | Stdio.Stdio | Output>;
export function withLegacyCommandInstrumentation<Flags extends Record<string, unknown>>(
options: LegacyCommandInstrumentationOptions<Flags>,
): <A, E, R>(
self: Effect.Effect<A, E, R>,
) => Effect.Effect<A, E, R | Analytics | CommandRuntime | Stdio.Stdio>;
) => Effect.Effect<A, E, R | Analytics | CommandRuntime | Stdio.Stdio | Output>;
export function withLegacyCommandInstrumentation<Flags extends Record<string, unknown>>(
options?: LegacyCommandInstrumentationOptions<Flags>,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { commandRuntimeLayer } from "../../shared/runtime/command-runtime.layer.
import { CurrentAnalyticsContext } from "../../shared/telemetry/analytics-context.ts";
import { Analytics } from "../../shared/telemetry/analytics.service.ts";
import { withLegacyCommandInstrumentation } from "./legacy-command-instrumentation.ts";
import { mockOutput } from "../../../tests/helpers/mocks.ts";

function mockContextualAnalytics() {
const captured: Array<{
Expand Down Expand Up @@ -46,6 +47,7 @@ describe("withLegacyCommandInstrumentation", () => {
}).pipe(
withLegacyCommandInstrumentation(),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed(["backups", "list"]),
Expand Down Expand Up @@ -73,6 +75,7 @@ describe("withLegacyCommandInstrumentation", () => {
flags: { projectRef: Option.some("abcdefghijklmnopqrst") },
}),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed(["secrets", "list", "--project-ref", "abcdefghijklmnopqrst"]),
Expand All @@ -99,6 +102,7 @@ describe("withLegacyCommandInstrumentation", () => {
flags: { envFile: Option.some("/path/to/.env") },
}),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed(["secrets", "set", "--env-file=/path/to/.env"]),
Expand All @@ -125,6 +129,7 @@ describe("withLegacyCommandInstrumentation", () => {
},
}),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed([
Expand Down Expand Up @@ -157,6 +162,7 @@ describe("withLegacyCommandInstrumentation", () => {
safeFlags: ["project-ref"],
}),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed(["link", "--project-ref", "abcdefghijklmnopqrst"]),
Expand All @@ -180,6 +186,7 @@ describe("withLegacyCommandInstrumentation", () => {
return Effect.void.pipe(
withLegacyCommandInstrumentation({ flags: {} }),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(Stdio.layerTest({ args: Effect.succeed(["backups", "list"]) })),
Effect.provide(commandRuntimeLayer(["backups", "list"])),
Effect.tap(() =>
Expand All @@ -196,6 +203,7 @@ describe("withLegacyCommandInstrumentation", () => {

return withLegacyCommandInstrumentation()(Effect.fail(new Error("boom"))).pipe(
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(Stdio.layerTest({ args: Effect.succeed(["backups", "list"]) })),
Effect.provide(commandRuntimeLayer(["backups", "list"])),
Effect.exit,
Expand All @@ -215,6 +223,7 @@ describe("withLegacyCommandInstrumentation", () => {
return Effect.sync(() => "ok").pipe(
withLegacyCommandInstrumentation({ analytics: false }),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(Stdio.layerTest({ args: Effect.succeed(["telemetry", "enable"]) })),
Effect.provide(commandRuntimeLayer(["telemetry", "enable"])),
Effect.tap(() =>
Expand All @@ -236,6 +245,7 @@ describe("withLegacyCommandInstrumentation", () => {
},
}),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed([
Expand Down
2 changes: 2 additions & 0 deletions apps/cli/src/next/auth/platform-api.layer.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { withCommandInstrumentation } from "../../shared/telemetry/command-instr
import { Credentials } from "./credentials.service.ts";
import { PlatformApi } from "./platform-api.service.ts";
import { makePlatformApiServices } from "./platform-api.layer.ts";
import { mockOutput } from "../../../tests/helpers/mocks.ts";

function httpClientLayer(
handler: (
Expand Down Expand Up @@ -243,6 +244,7 @@ describe("platformApiLayer", () => {
Effect.provide(layer),
Effect.provide(runtimeLayer),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed(["branches", "list"]),
Expand Down
7 changes: 5 additions & 2 deletions apps/cli/src/shared/telemetry/command-instrumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
getCommandRuntimeCommand,
getCommandRuntimeSpanName,
} from "../runtime/command-runtime.service.ts";
import { Output } from "../output/output.service.ts";
import { withAnalyticsContext } from "./analytics-context.ts";
import { Analytics } from "./analytics.service.ts";

Expand Down Expand Up @@ -99,6 +100,7 @@ function withCommandAnalyticsImplementation<Flags extends Record<string, unknown
});

const analytics = yield* Analytics;
const output = yield* Output;
const stdio = yield* Stdio.Stdio;
const args = yield* stdio.args;
const startedAt = yield* Clock.currentTimeMillis;
Expand All @@ -120,6 +122,7 @@ function withCommandAnalyticsImplementation<Flags extends Record<string, unknown
.capture("cli_command_executed", {
exit_code: Exit.isSuccess(exit) ? 0 : 1,
duration_ms: finishedAt - startedAt,
output_format: output.format,
})
.pipe(withAnalyticsContext(analyticsContext));

Expand All @@ -133,12 +136,12 @@ function withCommandAnalyticsImplementation<Flags extends Record<string, unknown

export function withCommandInstrumentation(): <A, E, R>(
self: Effect.Effect<A, E, R>,
) => Effect.Effect<A, E, R | Analytics | CommandRuntime | Stdio.Stdio>;
) => Effect.Effect<A, E, R | Analytics | CommandRuntime | Stdio.Stdio | Output>;
export function withCommandInstrumentation<Flags extends Record<string, unknown>>(
options: CommandInstrumentationOptions<Flags>,
): <A, E, R>(
self: Effect.Effect<A, E, R>,
) => Effect.Effect<A, E, R | Analytics | CommandRuntime | Stdio.Stdio>;
) => Effect.Effect<A, E, R | Analytics | CommandRuntime | Stdio.Stdio | Output>;
export function withCommandInstrumentation<Flags extends Record<string, unknown>>(
options?: CommandInstrumentationOptions<Flags>,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { commandRuntimeLayer } from "../runtime/command-runtime.layer.ts";
import { CurrentAnalyticsContext } from "./analytics-context.ts";
import { Analytics } from "./analytics.service.ts";
import { withCommandInstrumentation } from "./command-instrumentation.ts";
import { mockOutput } from "../../../tests/helpers/mocks.ts";

function mockContextualAnalytics() {
const captured: Array<{
Expand Down Expand Up @@ -46,6 +47,7 @@ describe("withCommandInstrumentation", () => {
}).pipe(
withCommandInstrumentation({ analytics: false }),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed(["branches", "list"]),
Expand All @@ -68,6 +70,7 @@ describe("withCommandInstrumentation", () => {
}).pipe(
withCommandInstrumentation(),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed(["start", "--detach", "--exclude=auth"]),
Expand Down Expand Up @@ -99,6 +102,7 @@ describe("withCommandInstrumentation", () => {

const program = withCommandInstrumentation()(Effect.fail(new Error("boom"))).pipe(
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed(["login"]),
Expand Down Expand Up @@ -133,6 +137,7 @@ describe("withCommandInstrumentation", () => {
allowedFlagValues: ["exclude", "mode", "stack"],
}),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed([
Expand Down Expand Up @@ -177,6 +182,7 @@ describe("withCommandInstrumentation", () => {
allowedFlagValues: ["token", "name", "noBrowser"],
}),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed(["login", "--name", "my-machine", "--no-browser"]),
Expand All @@ -202,6 +208,7 @@ describe("withCommandInstrumentation", () => {
return Effect.sync(() => "ok").pipe(
withCommandInstrumentation({ analytics: false }),
Effect.provide(analytics.layer),
Effect.provide(mockOutput({ format: "text" }).layer),
Effect.provide(
Stdio.layerTest({
args: Effect.succeed(["telemetry", "enable"]),
Expand Down
1 change: 1 addition & 0 deletions apps/cli/src/shared/telemetry/event-catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const PropCommand = "command";
export const PropFlags = "flags";
export const PropExitCode = "exit_code";
export const PropDurationMs = "duration_ms";
export const PropOutputFormat = "output_format";

export const GroupOrganization = "organization";
export const GroupProject = "project";
Expand Down
Loading