diff --git a/surfsense_web/app/global-error.tsx b/surfsense_web/app/global-error.tsx index add207cfd..05f14813e 100644 --- a/surfsense_web/app/global-error.tsx +++ b/surfsense_web/app/global-error.tsx @@ -4,6 +4,7 @@ import "./globals.css"; import posthog from "posthog-js"; import { useEffect, useMemo } from "react"; import { Button } from "@/components/ui/button"; +import { detectEnvironment } from "@/lib/env-config"; const ISSUES_URL = "https://github.com/MODSetter/SurfSense/issues/new"; @@ -19,6 +20,7 @@ function buildBasicIssueUrl(error: Error & { digest?: string }) { "", `- **Error:** ${error.message}`, ...(error.digest ? [`- **Digest:** \`${error.digest}\``] : []), + `- **Environment:** ${detectEnvironment()}`, `- **Timestamp:** ${new Date().toISOString()}`, `- **Page:** \`${typeof window !== "undefined" ? window.location.pathname : "unknown"}\``, `- **User Agent:** \`${typeof navigator !== "undefined" ? navigator.userAgent : "unknown"}\``, diff --git a/surfsense_web/lib/env-config.ts b/surfsense_web/lib/env-config.ts index c60ada372..818ccddab 100644 --- a/surfsense_web/lib/env-config.ts +++ b/surfsense_web/lib/env-config.ts @@ -67,6 +67,21 @@ export const BUILD_TIME_ETL_SERVICE = process.env.NEXT_PUBLIC_ETL_SERVICE || "DO // DEPLOYMENT_MODE through the runtime config provider first, then falls back to this baked value. export const BUILD_TIME_DEPLOYMENT_MODE = process.env.NEXT_PUBLIC_DEPLOYMENT_MODE || "self-hosted"; +/** + * Detect the environment for diagnostics (e.g. GitHub issue auto-fill). + * Inferred from the hostname so it needs no configuration from the operator. + * + * - "SurfSense Cloud": served from the official SurfSense domain (root + subdomains) + * - "self-hosted": everything else (covers self-hosted and community cloud deploys) + */ +export function detectEnvironment(): "SurfSense Cloud" | "self-hosted" { + const hostname = typeof window !== "undefined" ? window.location.hostname : ""; + if (hostname === "surfsense.com" || hostname.endsWith(".surfsense.com")) { + return "SurfSense Cloud"; + } + return "self-hosted"; +} + // App version - defaults to package.json version // Can be overridden at build time with NEXT_PUBLIC_APP_VERSION for full git tag version export const APP_VERSION = process.env.NEXT_PUBLIC_APP_VERSION || packageJson.version; diff --git a/surfsense_web/lib/error-toast.ts b/surfsense_web/lib/error-toast.ts index 55be6b544..6d0695a26 100644 --- a/surfsense_web/lib/error-toast.ts +++ b/surfsense_web/lib/error-toast.ts @@ -1,5 +1,6 @@ import { toast } from "sonner"; import { AbortedError, AppError, AuthenticationError, SURFSENSE_ISSUES_URL } from "./error"; +import { detectEnvironment } from "./env-config"; /** * Build a GitHub issue URL pre-filled with diagnostic context. @@ -8,6 +9,8 @@ import { AbortedError, AppError, AuthenticationError, SURFSENSE_ISSUES_URL } fro export function buildIssueUrl(error: unknown): string { const params = new URLSearchParams(); + const environment = detectEnvironment(); + const lines: string[] = ["## Bug Report", "", "**Describe what happened:**", "", ""]; if (error instanceof AppError) { @@ -16,9 +19,11 @@ export function buildIssueUrl(error: unknown): string { if (error.requestId) lines.push(`- **Request ID:** \`${error.requestId}\``); if (error.status) lines.push(`- **HTTP status:** ${error.status}`); lines.push(`- **Message:** ${error.message}`); + lines.push(`- **Environment:** ${environment}`); } else if (error instanceof Error) { lines.push("## Diagnostics (auto-filled)", ""); lines.push(`- **Error:** ${error.message}`); + lines.push(`- **Environment:** ${environment}`); } lines.push(`- **Timestamp:** ${new Date().toISOString()}`);