Skip to content

Commit e3de588

Browse files
committed
final touches for new log types
1 parent 7730145 commit e3de588

4 files changed

Lines changed: 471 additions & 258 deletions

File tree

site/app/docs/integrations/page.tsx

Lines changed: 55 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import React from 'react';
12
import { CodeBlock } from '@/components/code-block';
23
import { EditPageLink } from '@/components/edit-page-link';
34
import { RubyCodeExample } from '@/components/ruby-code-example';
@@ -10,15 +11,17 @@ import {
1011
getLogTypeInfo,
1112
getTitleId,
1213
} from '@/lib/integration-helpers';
13-
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
14+
// Tabs are now handled inside IntegrationExamples
15+
import { IntegrationExamples } from '@/components/integration-examples';
16+
import { FilteringProvider } from '@/components/filtering-context';
1417

1518
// Helper to format logs as JSON strings for display
1619
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1720
function formatLog(log: Record<string, any>): string {
1821
return JSON.stringify(log, null, 2);
1922
}
2023

21-
// Create a single log generator with a fixed seed for consistent examples
24+
// Create a single log generator with a fixed seed for consistent examples (kept for code samples above, not used for examples)
2225
const logGenerator = new LogGenerator(12345);
2326

2427
export default function IntegrationsPage() {
@@ -34,95 +37,62 @@ export default function IntegrationsPage() {
3437
relevant context for better observability.
3538
</p>
3639

37-
{/* Dynamically generate sections for each log type */}
38-
{AllLogTypes.map((logType) => {
39-
const logTypeInfo = getLogTypeInfo(logType);
40-
if (!logTypeInfo) return null; // Skip plain logs, etc.
40+
<FilteringProvider>
41+
{/* Dynamically generate sections for each log type */}
42+
{AllLogTypes.map((logType) => {
43+
const logTypeInfo = getLogTypeInfo(logType);
44+
if (!logTypeInfo) return null; // Skip plain logs, etc.
4145

42-
const { title, description, configuration_code, preferredEvent } =
43-
logTypeInfo;
46+
const { title, description, configuration_code, preferredEvent } =
47+
logTypeInfo;
4448

45-
return (
46-
<div key={logType} className="mt-10">
47-
<HeadingWithAnchor id={getTitleId(title)}>
48-
{title}
49-
</HeadingWithAnchor>
50-
<p className="text-neutral-600 dark:text-neutral-400 mb-4">
51-
{description}
52-
</p>
49+
return (
50+
<div key={logType} className="mt-10">
51+
<HeadingWithAnchor id={getTitleId(title)}>
52+
{title}
53+
</HeadingWithAnchor>
54+
<p className="text-neutral-600 dark:text-neutral-400 mb-4">
55+
{description}
56+
</p>
5357

54-
{/* Show Ruby code example if one is specified */}
55-
{configuration_code && (
56-
<>
57-
<HeadingWithAnchor
58-
id={`${getTitleId(title)}-configuration`}
59-
level={2}
60-
className="text-xl font-semibold mt-6 mb-3"
61-
>
62-
Configuration
63-
</HeadingWithAnchor>
64-
<div className="mb-4">
65-
<RubyCodeExample name={configuration_code} />
66-
</div>
67-
</>
68-
)}
58+
{/* Show Ruby code example if one is specified */}
59+
{configuration_code && (
60+
<>
61+
<HeadingWithAnchor
62+
id={`${getTitleId(title)}-configuration`}
63+
level={2}
64+
className="text-xl font-semibold mt-6 mb-3"
65+
>
66+
Configuration
67+
</HeadingWithAnchor>
68+
<div className="mb-4">
69+
<RubyCodeExample name={configuration_code} />
70+
</div>
71+
</>
72+
)}
6973

70-
{/* Generate a log example for this type */}
71-
<HeadingWithAnchor
72-
id={`${getTitleId(title)}-examples`}
73-
level={2}
74-
className="text-xl font-semibold mt-6 mb-3"
75-
>
76-
Example Logs
77-
</HeadingWithAnchor>
78-
{(() => {
79-
const events = getEventsForLogType(logType);
80-
if (events.length <= 1) {
81-
const only = events[0];
74+
{/* Generate a log example for this type */}
75+
<HeadingWithAnchor
76+
id={`${getTitleId(title)}-examples`}
77+
level={2}
78+
className="text-xl font-semibold mt-6 mb-3"
79+
>
80+
Example Logs
81+
</HeadingWithAnchor>
82+
{(() => {
83+
const events = getEventsForLogType(logType);
8284
return (
83-
<CodeBlock language="json">
84-
{formatLog(
85-
logGenerator.generateLogWithOptions(logType, {
86-
preferredEvent: preferredEvent ?? only,
87-
}),
88-
)}
89-
</CodeBlock>
85+
<IntegrationExamples
86+
logType={logType}
87+
events={events}
88+
preferredEvent={preferredEvent}
89+
/>
9090
);
91-
}
92-
return (
93-
<Tabs defaultValue={String(events[0])}>
94-
<TabsList className="cursor-pointer w-fit flex flex-wrap gap-2">
95-
{events.map((evt) => (
96-
<TabsTrigger
97-
key={String(evt)}
98-
value={String(evt)}
99-
className="cursor-pointer"
100-
>
101-
{String(evt)}
102-
</TabsTrigger>
103-
))}
104-
</TabsList>
105-
{events.map((evt) => (
106-
<TabsContent
107-
key={String(evt)}
108-
value={String(evt)}
109-
className="mt-0.5"
110-
>
111-
<CodeBlock language="json">
112-
{formatLog(
113-
logGenerator.generateLogWithOptions(logType, {
114-
preferredEvent: evt as Event,
115-
}),
116-
)}
117-
</CodeBlock>
118-
</TabsContent>
119-
))}
120-
</Tabs>
121-
);
122-
})()}
123-
</div>
124-
);
125-
})}
91+
})()}
92+
</div>
93+
);
94+
})}
95+
</FilteringProvider>
12696

12797
{/* Special case for Sorbet that doesn't fit the standard pattern */}
12898
<div className="mt-10">
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use client';
2+
3+
import React, { createContext, useContext, useState } from 'react';
4+
5+
type FilteringCtx = {
6+
filtering: boolean;
7+
setFiltering: (enabled: boolean) => void;
8+
};
9+
10+
const Ctx = createContext<FilteringCtx | null>(null);
11+
12+
export function FilteringProvider({ children }: { children: React.ReactNode }) {
13+
const [filtering, setFiltering] = useState(true);
14+
return (
15+
<Ctx.Provider value={{ filtering, setFiltering }}>{children}</Ctx.Provider>
16+
);
17+
}
18+
19+
export function useFiltering(): FilteringCtx {
20+
const ctx = useContext(Ctx);
21+
if (!ctx)
22+
throw new Error('useFiltering must be used within FilteringProvider');
23+
return ctx;
24+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
'use client';
2+
3+
import React from 'react';
4+
import { useFiltering } from '@/components/filtering-context';
5+
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
6+
import { CodeBlock } from '@/components/code-block';
7+
import { LogGenerator } from '@/lib/log-generation';
8+
import { Event, LogType } from '@/generated/logstruct';
9+
10+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
11+
const formatLog = (log: Record<string, any>) => JSON.stringify(log, null, 2);
12+
13+
export function IntegrationExamples({
14+
logType,
15+
events,
16+
preferredEvent,
17+
}: {
18+
logType: LogType;
19+
events: Event[];
20+
preferredEvent?: Event;
21+
}) {
22+
const { filtering, setFiltering } = useFiltering();
23+
const gen = new LogGenerator(12345, filtering);
24+
25+
if (events.length <= 1) {
26+
const only = events[0];
27+
return (
28+
<div className="relative">
29+
<CodeBlock language="json">
30+
{formatLog(
31+
gen.generateLogWithOptions(logType, {
32+
preferredEvent: preferredEvent ?? only,
33+
filtering,
34+
}),
35+
)}
36+
</CodeBlock>
37+
<div className="absolute bottom-2 right-3 text-xs text-neutral-500 dark:text-neutral-400 flex items-center gap-2 bg-white/60 dark:bg-neutral-900/60 px-2 py-1 rounded">
38+
<label className="cursor-pointer select-none">Apply filtering</label>
39+
<input
40+
aria-label="Apply filtering"
41+
type="checkbox"
42+
className="cursor-pointer"
43+
checked={filtering}
44+
onChange={(e) => setFiltering(e.target.checked)}
45+
/>
46+
</div>
47+
</div>
48+
);
49+
}
50+
51+
return (
52+
<div>
53+
<Tabs defaultValue={String(events[0])}>
54+
<TabsList className="cursor-pointer w-fit flex flex-wrap gap-2">
55+
{events.map((evt) => (
56+
<TabsTrigger
57+
key={String(evt)}
58+
value={String(evt)}
59+
className="cursor-pointer"
60+
>
61+
{String(evt)}
62+
</TabsTrigger>
63+
))}
64+
</TabsList>
65+
{events.map((evt) => (
66+
<TabsContent key={String(evt)} value={String(evt)} className="mt-0.5">
67+
<div className="relative">
68+
<CodeBlock language="json">
69+
{formatLog(
70+
gen.generateLogWithOptions(logType, {
71+
preferredEvent: evt,
72+
filtering,
73+
}),
74+
)}
75+
</CodeBlock>
76+
<div className="absolute bottom-2 right-3 text-xs text-neutral-500 dark:text-neutral-400 flex items-center gap-2 bg-white/60 dark:bg-neutral-900/60 px-2 py-1 rounded">
77+
<label className="cursor-pointer select-none">
78+
Apply filtering
79+
</label>
80+
<input
81+
aria-label="Apply filtering"
82+
type="checkbox"
83+
className="cursor-pointer"
84+
checked={filtering}
85+
onChange={(e) => setFiltering(e.target.checked)}
86+
/>
87+
</div>
88+
</div>
89+
</TabsContent>
90+
))}
91+
</Tabs>
92+
</div>
93+
);
94+
}

0 commit comments

Comments
 (0)