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
Original file line number Diff line number Diff line change
Expand Up @@ -13,52 +13,82 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useState } from "react";
import type { Attribute } from "@/types/javaagent";
import { ChevronDown } from "lucide-react";

interface AttributeTableProps {
attributes: Attribute[];
expandVersion?: number;
collapseVersion?: number;
}

export function AttributeTable({ attributes }: AttributeTableProps) {
export function AttributeTable({ attributes, expandVersion = 0, collapseVersion = 0 }: AttributeTableProps) {
const [isOpen, setIsOpen] = useState(false);
const [prevExpand, setPrevExpand] = useState(expandVersion);
const [prevCollapse, setPrevCollapse] = useState(collapseVersion);

if (expandVersion > prevExpand) {
setPrevExpand(expandVersion);
setIsOpen(true);
}

if (collapseVersion > prevCollapse) {
setPrevCollapse(collapseVersion);
setIsOpen(false);
}

if (attributes.length === 0) {
return null;
}

return (
<div className="border-border/30 overflow-x-auto rounded-lg border">
<table aria-label="Attributes" className="w-full min-w-[260px] border-collapse">
<thead>
<tr className="bg-white/5">
<th
scope="col"
className="text-muted-foreground p-2 text-left text-[10px] font-bold tracking-widest uppercase sm:p-3"
>
Key
</th>
<th
scope="col"
className="text-muted-foreground p-2 text-left text-[10px] font-bold tracking-widest uppercase sm:p-3"
>
Type
</th>
</tr>
</thead>
<tbody>
{attributes.map((attr, index) => (
<tr
key={attr.name}
className={`attribute-row ${index % 2 === 1 ? "bg-white/[0.03]" : ""}`}
>
<td className="p-2 font-mono text-xs sm:p-4 sm:text-sm">{attr.name}</td>
<td className="p-2 sm:p-4">
<span className="border-border/30 bg-card/80 text-muted-foreground inline-block w-fit rounded border px-2 py-1 text-xs font-bold tracking-wider uppercase">
{attr.type}
</span>
</td>
<details
open={isOpen}
onToggle={(e) => setIsOpen((e.target as HTMLDetailsElement).open)}
className="group border-border/30 bg-card/50 overflow-hidden rounded-lg border open:bg-transparent"
>
<summary className="hover:bg-card/80 flex cursor-pointer items-center justify-between p-3 text-sm font-medium transition-colors">
<span className="text-muted-foreground text-xs font-black tracking-[0.2em] uppercase">
View {attributes.length} Attribute{attributes.length === 1 ? "" : "s"}
</span>
<ChevronDown className="text-muted-foreground h-4 w-4 transition-transform group-open:rotate-180" />
</summary>
<div className="border-border/30 overflow-x-auto border-t">
<table aria-label="Attributes" className="w-full min-w-[260px] border-collapse">
<thead>
<tr className="bg-white/5">
<th
scope="col"
className="text-muted-foreground p-2 text-left text-[10px] font-bold tracking-widest uppercase sm:p-3"
>
Key
</th>
<th
scope="col"
className="text-muted-foreground p-2 text-left text-[10px] font-bold tracking-widest uppercase sm:p-3"
>
Type
</th>
</tr>
))}
</tbody>
</table>
</div>
</thead>
<tbody>
{attributes.map((attr, index) => (
<tr
key={attr.name}
className={`attribute-row ${index % 2 === 1 ? "bg-white/[0.03]" : ""}`}
>
<td className="p-2 font-mono text-xs sm:p-4 sm:text-sm">{attr.name}</td>
<td className="p-2 sm:p-4">
<span className="border-border/30 bg-card/80 text-muted-foreground inline-block w-fit rounded border px-2 py-1 text-xs font-bold tracking-wider uppercase">
{attr.type}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</details>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,15 @@ import type { Telemetry } from "@/types/javaagent";

interface TelemetrySectionProps {
telemetry: Telemetry[];
expandVersion?: number;
collapseVersion?: number;
}

export function TelemetrySection({ telemetry }: TelemetrySectionProps) {
export function TelemetrySection({
telemetry,
expandVersion = 0,
collapseVersion = 0
}: TelemetrySectionProps) {
const [selectedWhen, setSelectedWhen] = useState(telemetry[0]?.when ?? "default");

// Validate selected value and fall back to first option if invalid
Expand Down Expand Up @@ -90,11 +96,12 @@ export function TelemetrySection({ telemetry }: TelemetrySectionProps) {

{/* Attributes section */}
{metric.attributes && metric.attributes.length > 0 && (
<div className="space-y-4">
<h4 className="text-muted-foreground text-xs font-black tracking-[0.2em] uppercase">
Attributes
</h4>
<AttributeTable attributes={metric.attributes} />
<div className="pt-2">
<AttributeTable
attributes={metric.attributes}
expandVersion={expandVersion}
collapseVersion={collapseVersion}
/>
</div>
)}
</div>
Expand Down Expand Up @@ -128,11 +135,12 @@ export function TelemetrySection({ telemetry }: TelemetrySectionProps) {

{/* Attributes section */}
{span.attributes && span.attributes.length > 0 && (
<div className="space-y-4">
<h4 className="text-muted-foreground text-xs font-black tracking-[0.2em] uppercase">
Attributes
</h4>
<AttributeTable attributes={span.attributes} />
<div className="pt-2">
<AttributeTable
attributes={span.attributes}
expandVersion={expandVersion}
collapseVersion={collapseVersion}
/>
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import {
AlertCircle,
Loader2,
HelpCircle,
ChevronsDown,
ChevronsUp,
} from "lucide-react";

import { BackButton } from "@/components/ui/back-button";
Expand All @@ -39,6 +41,8 @@ import {
getSemanticConventionInfo,
getFeatureInfo,
} from "./utils/format";
import { getBadgeInfo } from "./utils/badge-info";
import { TelemetryBadges } from "./components/instrumentation-badges";
import { TelemetrySection } from "./components/telemetry-section";
import { TelemetryComparisonSection } from "./components/telemetry-comparison/telemetry-comparison-section";
import { VersionSelector } from "./components/version-selector";
Expand Down Expand Up @@ -76,6 +80,8 @@ export function InstrumentationDetailPage() {
const navigate = useNavigate();
const [showComparison, setShowComparison] = useState(false);
const [activeTab, setActiveTab] = useState("details");
const [expandVersion, setExpandVersion] = useState(0);
const [collapseVersion, setCollapseVersion] = useState(0);

const { data: versionsData, loading: versionsLoading } = useVersions();

Expand Down Expand Up @@ -156,6 +162,7 @@ export function InstrumentationDetailPage() {
const displayName = getInstrumentationDisplayName(instrumentation);
const showRawName =
instrumentation.display_name && instrumentation.display_name !== instrumentation.name;
const badgeInfo = getBadgeInfo(instrumentation);

return (
<PageContainer>
Expand Down Expand Up @@ -217,6 +224,7 @@ export function InstrumentationDetailPage() {
? "Disabled by Default"
: "Enabled by Default"}
</GlowBadge>
<TelemetryBadges badges={badgeInfo} />
</div>
</div>

Expand Down Expand Up @@ -275,6 +283,80 @@ export function InstrumentationDetailPage() {

<TabsContent value="details" className="mt-0 p-4 sm:p-6">
<div className="space-y-8">
{/* Value Proposition Summary */}
{(badgeInfo.hasMetrics || badgeInfo.hasSpans) && (
<div>
<SectionHeader>Telemetry Overview</SectionHeader>
<div className="grid gap-4 md:grid-cols-2">
{badgeInfo.hasSpans && (
<DetailCard withHoverEffect>
<div className="flex items-start gap-3">
<Activity
className="text-info mt-0.5 h-5 w-5 flex-shrink-0"
aria-hidden="true"
/>
<div className="flex-1 space-y-1">
<h3 className="text-foreground text-sm font-semibold">
Traces & Spans
</h3>
<p className="text-muted-foreground text-sm">
Provides visibility into application activity and execution flow across services and components.
</p>
{instrumentation.telemetry &&
instrumentation.telemetry[0] &&
instrumentation.telemetry[0].spans && (
<div className="mt-2 flex flex-wrap gap-1">
{instrumentation.telemetry[0].spans.map((span, idx) => (
<GlowBadge key={idx} variant="info" className="text-[10px]">
{span.span_kind}
</GlowBadge>
))}
</div>
)}
</div>
</div>
</DetailCard>
)}

{badgeInfo.hasMetrics && (
<DetailCard withHoverEffect>
<div className="flex items-start gap-3">
<Activity
className="text-success mt-0.5 h-5 w-5 flex-shrink-0"
aria-hidden="true"
/>
<div className="flex-1 space-y-1">
<h3 className="text-foreground text-sm font-semibold">
Metrics
</h3>
<p className="text-muted-foreground text-sm">
Gives you the big picture of system health, like total request
Comment thread
hussainjamal760 marked this conversation as resolved.
counts, error rates, and average speeds over time.
</p>
{instrumentation.telemetry &&
instrumentation.telemetry[0] &&
instrumentation.telemetry[0].metrics && (
<div className="mt-2 flex flex-wrap gap-1">
{instrumentation.telemetry[0].metrics.map((metric, idx) => (
<span
key={idx}
className="bg-success/10 text-success border-success/20 truncate rounded border px-1.5 py-0.5 font-mono text-[10px]"
title={metric.name}
>
{metric.name.length > 50
? metric.name.substring(0, 50) + "..."
: metric.name}
</span>
))}
</div>
)}
</div>
</div>
</DetailCard>
)}
</div>
</div>
)}
{((instrumentation.features && instrumentation.features.length > 0) ||
(instrumentation.semantic_conventions &&
instrumentation.semantic_conventions.length > 0)) && (
Expand Down Expand Up @@ -494,7 +576,7 @@ export function InstrumentationDetailPage() {
<TabsContent value="telemetry" className="mt-0 p-4 sm:p-6">
{instrumentation.telemetry && instrumentation.telemetry.length > 0 ? (
<div className="space-y-8">
<div className="flex justify-center">
<div className="flex flex-col items-center gap-6">
<div
className="border-border inline-flex w-full rounded-lg border bg-transparent p-1 sm:w-auto"
role="group"
Expand Down Expand Up @@ -524,10 +606,34 @@ export function InstrumentationDetailPage() {
Version Comparison
</button>
</div>

{!showComparison && instrumentation.telemetry && instrumentation.telemetry.length > 0 && (
<div className="flex items-center gap-3">
<button
onClick={() => setExpandVersion((v) => v + 1)}
className="hover:border-primary/30 hover:bg-primary/5 border-border/30 bg-card/50 text-muted-foreground hover:text-primary flex items-center gap-2 rounded-lg border px-3 py-1.5 text-[10px] font-black tracking-[0.15em] uppercase transition-all duration-200 hover:scale-[1.02] active:scale-[0.98]"
>
<ChevronsDown className="h-3.5 w-3.5" />
Expand All
</button>
<div className="bg-border/30 h-4 w-px" />
<button
onClick={() => setCollapseVersion((v) => v + 1)}
className="hover:border-primary/30 hover:bg-primary/5 border-border/30 bg-card/50 text-muted-foreground hover:text-primary flex items-center gap-2 rounded-lg border px-3 py-1.5 text-[10px] font-black tracking-[0.15em] uppercase transition-all duration-200 hover:scale-[1.02] active:scale-[0.98]"
>
<ChevronsUp className="h-3.5 w-3.5" />
Collapse All
</button>
</div>
)}
</div>

{!showComparison ? (
<TelemetrySection telemetry={instrumentation.telemetry} />
<TelemetrySection
telemetry={instrumentation.telemetry}
expandVersion={expandVersion}
collapseVersion={collapseVersion}
/>
) : (
versionsData && (
<TelemetryComparisonSection
Expand Down