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);
});
});
});
31 changes: 27 additions & 4 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 | undefined;
private _telemetryBlocked: boolean = false;

constructor() {
// Initialization is now lazy to avoid issues with mocking in tests
Expand All @@ -36,15 +38,24 @@ 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");
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;
}
};

if (typeof this._hasInternetConnection !== "undefined") {
void refetchConnection(); // check in background if connection became available
void refetchConnection();
return this._hasInternetConnection;
}

Expand All @@ -53,14 +64,26 @@ export class PosthogService {
}

get isEnabled() {
if (process.env.CONTINUE_TELEMETRY_ENABLED === "0") {
return false;
}
if (process.env.CONTINUE_TELEMETRY_ENABLED === "1") {
return true;
}
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
13 changes: 11 additions & 2 deletions extensions/cli/src/telemetry/telemetryService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,17 @@ class TelemetryService {
process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT ||
process.env.OTEL_METRICS_EXPORTER
);
const enabled =
process.env.CONTINUE_CLI_ENABLE_TELEMETRY !== "0" && hasOtelConfig;

let telemetryEnabled = true;
if (process.env.CONTINUE_METRICS_ENABLED === "0") {
telemetryEnabled = false;
} else if (process.env.CONTINUE_METRICS_ENABLED === "1") {
telemetryEnabled = true;
} else {
telemetryEnabled = process.env.CONTINUE_CLI_ENABLE_TELEMETRY !== "0";
}

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

return {
Expand Down
Loading