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
33 changes: 33 additions & 0 deletions extensions/cli/src/telemetry/posthogService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,5 +152,38 @@ describe("PosthogService", () => {
expect(client).toBeUndefined();
expect(dns.lookup).toHaveBeenCalledTimes(1);
});

it("returns false when DNS resolves to 0.0.0.0 (blocked)", async () => {
const dns: any = (await import("dns/promises")).default;
dns.lookup.mockResolvedValueOnce({
address: "0.0.0.0",
family: 4,
} as any);
const result = await (service as any).hasInternetConnection();
expect(result).toBe(false);
expect(dns.lookup).toHaveBeenCalledTimes(1);
});

it("returns false when DNS resolves to localhost", async () => {
const dns: any = (await import("dns/promises")).default;
dns.lookup.mockResolvedValueOnce({
address: "127.0.0.1",
family: 4,
} as any);
const result = await (service as any).hasInternetConnection();
expect(result).toBe(false);
expect(dns.lookup).toHaveBeenCalledTimes(1);
});

it("returns true when DNS resolves to valid address", async () => {
const dns: any = (await import("dns/promises")).default;
dns.lookup.mockResolvedValueOnce({
address: "1.1.1.1",
family: 4,
} as any);
const result = await (service as any).hasInternetConnection();
expect(result).toBe(true);
expect(dns.lookup).toHaveBeenCalledTimes(1);
});
});
});
32 changes: 29 additions & 3 deletions extensions/cli/src/telemetry/posthogService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import node_machine_id from "node-machine-id";
import type { PostHog as PostHogType } from "posthog-node";

import { isAuthenticatedConfig, loadAuthConfig } from "../auth/workos.js";
import { loggers } from "../logging.js";
import { isHeadlessMode, isServe } from "../util/cli.js";
import { isGitHubActions } from "../util/git.js";
import { logger } from "../util/logger.js";
Expand All @@ -13,6 +14,7 @@ import { getVersion } from "../version.js";
export class PosthogService {
private os: string | undefined;
private uniqueId: string;
private _telemetryBlocked: boolean = false;

constructor() {
this.os = os.platform();
Expand All @@ -23,10 +25,20 @@ export class PosthogService {
private async hasInternetConnection() {
const refetchConnection = async () => {
try {
await dns.lookup("app.posthog.com");
this._hasInternetConnection = true;
const result = await dns.lookup("app.posthog.com");
// Check that the resolved address is not 0.0.0.0 or other invalid addresses
const isValidAddress =
result.address !== "0.0.0.0" && !result.address.startsWith("127.");
this._hasInternetConnection = isValidAddress;
this._telemetryBlocked = !isValidAddress;
if (!isValidAddress) {
logger.debug(
"DNS lookup returned invalid address for PostHog, skipping telemetry",
);
}
} catch {
this._hasInternetConnection = false;
this._telemetryBlocked = false;
}
};

Expand All @@ -40,14 +52,28 @@ export class PosthogService {
}

get isEnabled() {
// Check for the unified telemetry control first
if (process.env.CONTINUE_TELEMETRY_ENABLED === "0") {
return false;
}
if (process.env.CONTINUE_TELEMETRY_ENABLED === "1") {
return true;
}
// Fall back to the legacy variable for backward compatibility
return process.env.CONTINUE_ALLOW_ANONYMOUS_TELEMETRY !== "0";
}

private _client: PostHogType | undefined;
private async getClient() {
if (!(await this.hasInternetConnection())) {
this._client = undefined;
logger.warn("No internet connection, skipping telemetry");
if (this._telemetryBlocked && this.isEnabled) {
loggers.warning(
"Telemetry appears to be blocked by your network. To disable telemetry entirely, set CONTINUE_TELEMETRY_ENABLED=0",
);
} else if (this.isEnabled) {
logger.warn("No internet connection, skipping telemetry");
}
} else if (this.isEnabled) {
if (!this._client) {
const { PostHog } = await import("posthog-node");
Expand Down
15 changes: 13 additions & 2 deletions extensions/cli/src/telemetry/telemetryService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,19 @@ class TelemetryService {
process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT ||
process.env.OTEL_METRICS_EXPORTER
);
const enabled =
process.env.CONTINUE_CLI_ENABLE_TELEMETRY !== "0" && hasOtelConfig;

// Check for unified telemetry control first
let telemetryEnabled = true; // default to enabled if OTEL config exists
if (process.env.CONTINUE_TELEMETRY_ENABLED === "0") {
telemetryEnabled = false;
} else if (process.env.CONTINUE_TELEMETRY_ENABLED === "1") {
telemetryEnabled = true;
} else {
// Fall back to legacy variable for backward compatibility
telemetryEnabled = process.env.CONTINUE_CLI_ENABLE_TELEMETRY !== "0";
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONTINUE_TELEMETRY_ENABLED="false" still enables telemetry because the code falls back to the legacy flag instead of honoring the new value.

Prompt for AI agents
Address the following comment on extensions/cli/src/telemetry/telemetryService.ts at line 83:

<comment>CONTINUE_TELEMETRY_ENABLED=&quot;false&quot; still enables telemetry because the code falls back to the legacy flag instead of honoring the new value.</comment>

<file context>
@@ -71,8 +71,19 @@ class TelemetryService {
+      telemetryEnabled = true;
+    } else {
+      // Fall back to legacy variable for backward compatibility
+      telemetryEnabled = process.env.CONTINUE_CLI_ENABLE_TELEMETRY !== &quot;0&quot;;
+    }
+
</file context>
Fix with Cubic

}

const enabled = telemetryEnabled && hasOtelConfig;
const sessionId = uuidv4();

return {
Expand Down
Loading