diff --git a/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/controls/components/logs-search/index.tsx b/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/controls/components/logs-search/index.tsx index f7fe9cb659..e6a189c231 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/controls/components/logs-search/index.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/controls/components/logs-search/index.tsx @@ -44,6 +44,11 @@ export const LogsSearch = ({ apiId }: { apiId: string }) => { return ( diff --git a/apps/dashboard/app/(app)/apis/_components/controls/components/logs-search/index.tsx b/apps/dashboard/app/(app)/apis/_components/controls/components/logs-search/index.tsx index 1fa166d144..920c21459f 100644 --- a/apps/dashboard/app/(app)/apis/_components/controls/components/logs-search/index.tsx +++ b/apps/dashboard/app/(app)/apis/_components/controls/components/logs-search/index.tsx @@ -46,6 +46,11 @@ export const LogsSearch = ({ onSearch, onApiListChange, apiList }: Props) => { return ( { return ( diff --git a/apps/dashboard/app/(app)/logs/components/controls/components/logs-search/index.tsx b/apps/dashboard/app/(app)/logs/components/controls/components/logs-search/index.tsx index 523aa0eea5..19e73a1c45 100644 --- a/apps/dashboard/app/(app)/logs/components/controls/components/logs-search/index.tsx +++ b/apps/dashboard/app/(app)/logs/components/controls/components/logs-search/index.tsx @@ -44,6 +44,11 @@ export const LogsSearch = () => { return ( diff --git a/apps/dashboard/app/(app)/ratelimits/[namespaceId]/_overview/components/controls/components/logs-search/index.tsx b/apps/dashboard/app/(app)/ratelimits/[namespaceId]/_overview/components/controls/components/logs-search/index.tsx index b562471c46..f48739ef8e 100644 --- a/apps/dashboard/app/(app)/ratelimits/[namespaceId]/_overview/components/controls/components/logs-search/index.tsx +++ b/apps/dashboard/app/(app)/ratelimits/[namespaceId]/_overview/components/controls/components/logs-search/index.tsx @@ -44,6 +44,11 @@ export const LogsSearch = () => { return ( diff --git a/apps/dashboard/app/(app)/ratelimits/[namespaceId]/logs/components/controls/components/logs-search/index.tsx b/apps/dashboard/app/(app)/ratelimits/[namespaceId]/logs/components/controls/components/logs-search/index.tsx index 5ca0864afb..6b01b93bdd 100644 --- a/apps/dashboard/app/(app)/ratelimits/[namespaceId]/logs/components/controls/components/logs-search/index.tsx +++ b/apps/dashboard/app/(app)/ratelimits/[namespaceId]/logs/components/controls/components/logs-search/index.tsx @@ -44,6 +44,11 @@ export const LogsSearch = () => { return ( diff --git a/apps/dashboard/app/(app)/ratelimits/_components/controls/components/logs-search/index.tsx b/apps/dashboard/app/(app)/ratelimits/_components/controls/components/logs-search/index.tsx index 2a73b38bcb..c56fcb9702 100644 --- a/apps/dashboard/app/(app)/ratelimits/_components/controls/components/logs-search/index.tsx +++ b/apps/dashboard/app/(app)/ratelimits/_components/controls/components/logs-search/index.tsx @@ -41,6 +41,11 @@ export const LogsSearch = ({ setNamespaces, initialNamespaces }: LogsSearchProps return ( = ({ + exampleQueries, searchText, hideClear, hideExplainer, @@ -43,7 +45,9 @@ export const SearchActions: React.FC = ({ } if (searchText.length === 0 && !hideExplainer) { - return ; + return ( + + ); } return null; diff --git a/apps/dashboard/components/logs/llm-search/components/search-example-tooltip.tsx b/apps/dashboard/components/logs/llm-search/components/search-example-tooltip.tsx index 8fbdd68d37..7ad599b177 100644 --- a/apps/dashboard/components/logs/llm-search/components/search-example-tooltip.tsx +++ b/apps/dashboard/components/logs/llm-search/components/search-example-tooltip.tsx @@ -3,13 +3,17 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "compon type SearchExampleTooltipProps = { onSelectExample: (query: string) => void; + exampleQueries?: string[]; }; -export const SearchExampleTooltip: React.FC = ({ onSelectExample }) => { - const examples = [ - { id: "failed-requests", text: "Show failed requests today" }, - { id: "auth-errors", text: "auth errors in the last 3h" }, - { id: "api-calls", text: "API calls from a path that includes /api/v1/oz" }, +export const SearchExampleTooltip: React.FC = ({ + onSelectExample, + exampleQueries, +}) => { + const examples = exampleQueries ?? [ + "Show failed requests today", + "auth errors in the last 3h", + "API calls from a path that includes /api/v1/oz", ]; return ( @@ -31,15 +35,15 @@ export const SearchExampleTooltip: React.FC = ({ onSe
    {examples.map((example) => ( -
  • +
  • ))} diff --git a/apps/dashboard/components/logs/llm-search/index.tsx b/apps/dashboard/components/logs/llm-search/index.tsx index d2d2e7d1aa..1c48576f52 100644 --- a/apps/dashboard/components/logs/llm-search/index.tsx +++ b/apps/dashboard/components/logs/llm-search/index.tsx @@ -9,6 +9,7 @@ import { useSearchStrategy } from "./hooks/use-search-strategy"; type SearchMode = "allowTypeDuringSearch" | "debounced" | "manual"; type Props = { + exampleQueries?: string[]; onSearch: (query: string) => void; onClear?: () => void; placeholder?: string; @@ -22,6 +23,7 @@ type Props = { }; export const LogsLLMSearch = ({ + exampleQueries, onSearch, isLoading, onClear, @@ -154,6 +156,7 @@ export const LogsLLMSearch = ({ { }, }; - it("should return null if openai is not configured", async () => { + it("should return TRPCError if openai is not configured", async () => { const result = await getStructuredSearchFromLLM(null as any, "test query", 1706024400000); - expect(result).toBeNull(); + expect(result).rejects.toThrowError( + new TRPCError({ + code: "PRECONDITION_FAILED", + message: "OpenAI isn't configured correctly, please check your API key", + }), + ); }); it("should handle successful LLM response", async () => { diff --git a/apps/dashboard/lib/trpc/routers/logs/llm-search/utils.ts b/apps/dashboard/lib/trpc/routers/logs/llm-search/utils.ts index 3228d3c279..1c9ae73d01 100644 --- a/apps/dashboard/lib/trpc/routers/logs/llm-search/utils.ts +++ b/apps/dashboard/lib/trpc/routers/logs/llm-search/utils.ts @@ -11,7 +11,10 @@ export async function getStructuredSearchFromLLM( ) { try { if (!openai) { - return null; // Skip LLM processing in development environment when OpenAI API key is not configured + throw new TRPCError({ + code: "PRECONDITION_FAILED", + message: "OpenAI isn't configured correctly, please check your API key", + }); } const completion = await openai.beta.chat.completions.parse({ // Don't change the model only a few models allow structured outputs diff --git a/apps/dashboard/lib/trpc/routers/ratelimit/llm-search/utils.test.ts b/apps/dashboard/lib/trpc/routers/ratelimit/llm-search/utils.test.ts index 5ae0ef763b..538160e156 100644 --- a/apps/dashboard/lib/trpc/routers/ratelimit/llm-search/utils.test.ts +++ b/apps/dashboard/lib/trpc/routers/ratelimit/llm-search/utils.test.ts @@ -43,9 +43,14 @@ describe("getStructuredSearchFromLLM", () => { }, }; - it("should return null if openai is not configured", async () => { + it("should return TRPCError if openai is not configured", async () => { const result = await getStructuredSearchFromLLM(null as any, "test query", 1706024400000); - expect(result).toBeNull(); + expect(result).rejects.toThrowError( + new TRPCError({ + code: "PRECONDITION_FAILED", + message: "OpenAI isn't configured correctly, please check your API key", + }), + ); }); it("should handle successful LLM response", async () => { diff --git a/apps/dashboard/lib/trpc/routers/ratelimit/llm-search/utils.ts b/apps/dashboard/lib/trpc/routers/ratelimit/llm-search/utils.ts index 861e40db92..fa703beb56 100644 --- a/apps/dashboard/lib/trpc/routers/ratelimit/llm-search/utils.ts +++ b/apps/dashboard/lib/trpc/routers/ratelimit/llm-search/utils.ts @@ -30,7 +30,10 @@ export async function getStructuredSearchFromLLM( ) { try { if (!openai) { - return null; // Skip LLM processing in development environment when OpenAI API key is not configured + throw new TRPCError({ + code: "PRECONDITION_FAILED", + message: "OpenAI isn't configured correctly, please check your API key", + }); } const completion = await openai.beta.chat.completions.parse({ // Don't change the model only a few models allow structured outputs