Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ export const LogsSearch = ({ apiId }: { apiId: string }) => {

return (
<LogsLLMSearch
exampleQueries={[
"Show rate limited outcomes",
"Show identity that starts with test_",
"Show name that starts with test_ in the last hour",
]}
isLoading={queryLLMForStructuredOutput.isLoading}
searchMode="manual"
onSearch={(query) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ export const LogsSearch = ({ onSearch, onApiListChange, apiList }: Props) => {

return (
<LogsLLMSearch
exampleQueries={[
"Show rate limited requests today",
"Show requests that were not rate limited today",
"Show requests in the last 5 minutes",
]}
hideExplainer
onClear={handleClear}
placeholder="Search API using name or ID"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ export const LogsSearch = () => {

return (
<LogsLLMSearch
exampleQueries={[
"Show keys created in the last 3h",
"Show all ratelimit events",
"Show all role deletions",
]}
isLoading={queryLLMForStructuredOutput.isLoading}
searchMode="manual"
onSearch={(query) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ export const LogsSearch = () => {

return (
<LogsLLMSearch
exampleQueries={[
"Show failed requests today",
"Show auth errors in the last 3h",
"Show API calls from a path that includes api/v1/",
]}
isLoading={queryLLMForStructuredOutput.isLoading}
searchMode="manual"
onSearch={(query) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ export const LogsSearch = () => {

return (
<LogsLLMSearch
exampleQueries={[
"Show all identifiers that is test",
"Show all identifiers that include cust_",
"Show all identifiers for customer in the last 1h",
]}
isLoading={queryLLMForStructuredOutput.isLoading}
searchMode="manual"
onSearch={(query) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ export const LogsSearch = () => {

return (
<LogsLLMSearch
exampleQueries={[
"Show failed requests today",
"Show passed requests from the last 1 hour",
"Show failed requests that includes cust_ in the identifier",
]}
isLoading={queryLLMForStructuredOutput.isLoading}
searchMode="manual"
onSearch={(query) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ export const LogsSearch = ({ setNamespaces, initialNamespaces }: LogsSearchProps

return (
<LogsLLMSearch
exampleQueries={[
"Show failed requests today",
"Show passed requests from the last 1 hour",
"Show failed requests that includes cust_ in the identifier",
]}
hideExplainer
onClear={handleClear}
placeholder="Search namespaces"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { XMark } from "@unkey/icons";
import { SearchExampleTooltip } from "./search-example-tooltip";

type SearchActionsProps = {
exampleQueries?: string[];
searchText: string;
hideClear: boolean;
hideExplainer: boolean;
Expand All @@ -15,6 +16,7 @@ type SearchActionsProps = {
* SearchActions component renders the right-side actions (clear button or examples tooltip)
*/
export const SearchActions: React.FC<SearchActionsProps> = ({
exampleQueries,
searchText,
hideClear,
hideExplainer,
Expand Down Expand Up @@ -43,7 +45,9 @@ export const SearchActions: React.FC<SearchActionsProps> = ({
}

if (searchText.length === 0 && !hideExplainer) {
return <SearchExampleTooltip onSelectExample={onSelectExample} />;
return (
<SearchExampleTooltip onSelectExample={onSelectExample} exampleQueries={exampleQueries} />
);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "compon

type SearchExampleTooltipProps = {
onSelectExample: (query: string) => void;
exampleQueries?: string[];
};

export const SearchExampleTooltip: React.FC<SearchExampleTooltipProps> = ({ 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<SearchExampleTooltipProps> = ({
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 (
Expand All @@ -31,15 +35,15 @@ export const SearchExampleTooltip: React.FC<SearchExampleTooltipProps> = ({ onSe
</div>
<ul className="space-y-1.5 pl-1 [&_svg]:size-[10px] ">
{examples.map((example) => (
<li key={example.id} className="flex items-center gap-2">
<li key={example} className="flex items-center gap-2">
<CaretRightOutline className="text-accent-9" />
<button
type="button"
className="hover:text-accent-11 transition-colors cursor-pointer hover:underline"
onClick={() => onSelectExample(example.text)}
data-testid={`example-${example.id}`}
onClick={() => onSelectExample(example)}
data-testid={`example-${example}`}
>
"{example.text}"
"{example}"
</button>
</li>
))}
Expand Down
3 changes: 3 additions & 0 deletions apps/dashboard/components/logs/llm-search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -22,6 +23,7 @@ type Props = {
};

export const LogsLLMSearch = ({
exampleQueries,
onSearch,
isLoading,
onClear,
Expand Down Expand Up @@ -154,6 +156,7 @@ export const LogsLLMSearch = ({
</div>

<SearchActions
exampleQueries={exampleQueries}
searchText={searchText}
hideClear={hideClear}
hideExplainer={hideExplainer}
Expand Down
6 changes: 5 additions & 1 deletion apps/dashboard/lib/trpc/routers/audit/llm-search/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ export async function getStructuredAuditSearchFromLLM(
usersReferenceMS: number,
) {
try {
// Skip LLM processing in development environment when OpenAI API key is not configured
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({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,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 () => {
Expand Down
5 changes: 4 additions & 1 deletion apps/dashboard/lib/trpc/routers/logs/llm-search/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading