mirror of
https://github.com/hanzoai/insights.git
synced 2026-10-30 16:15:31 +00:00
716 files rewritten, 30 renamed, same family mapping as the frontend pass.
Held back, and each for a reason rather than by oversight:
db_table values insights_hogfunction, insights_hogflow,
insights_hogfunctiontemplate, hogflow_templates.
Renaming a table is ALTER TABLE, so it ships as a
migration with the raw SQL in nodejs that names it.
hog_invocation_results a Datastore table with Kafka engine tables on it
products/review_hog the module path is the Django app path; moving it
moves app_label and every migration is recorded under
(app_label, name). That is the same history break as
renaming a migration file, one level up.
*/migrations/* five files, untouched
whogho an integration vendor
Checked: 395 of 397 changed Python files compile. The two that do not —
insightsql/database/database.py and temporal/schedule.py — fail identically at
origin/main under the same interpreter, because they use `type X = ...` and
`except*`, which need the 3.13 this repo pins and not the 3.9 doing the check.
Running the check against the original is what told those apart from a real
break.
Co-authored-by: Hanzo Dev <[email protected]>
186 lines
7.8 KiB
TypeScript
186 lines
7.8 KiB
TypeScript
import insights from 'insights-js'
|
||
import { useActions, useValues } from 'kea'
|
||
import { useEffect, useState } from 'react'
|
||
|
||
import { Button, Tabs, Link, Spinner } from '@hanzo/elements'
|
||
|
||
import { pngMascot } from 'lib/brand/mascot'
|
||
import { CodeSnippet, Language } from 'lib/components/CodeSnippet'
|
||
import { ProductIntroduction } from 'lib/components/ProductIntroduction/ProductIntroduction'
|
||
import { useInterval } from 'lib/hooks/useInterval'
|
||
import { apiHostOrigin } from 'lib/utils/apiHost'
|
||
import { teamLogic } from 'scenes/teamLogic'
|
||
|
||
import { ProductIntentContext, ProductKey } from '~/queries/schema/schema-general'
|
||
|
||
import { metricsIngestionLogic } from '../metricsIngestionLogic'
|
||
|
||
const MascotGreek = pngMascot()
|
||
|
||
const POLLING_INTERVAL_MS = 5000
|
||
|
||
export const MetricsSetupPrompt = ({
|
||
children,
|
||
className,
|
||
}: {
|
||
children: React.ReactNode
|
||
className?: string
|
||
}): JSX.Element => {
|
||
const { hasMetrics, teamHasMetricsLoading, teamHasMetricsCheckFailed } = useValues(metricsIngestionLogic)
|
||
const { currentTeam } = useValues(teamLogic)
|
||
|
||
if ((teamHasMetricsLoading && hasMetrics === undefined) || !currentTeam) {
|
||
return (
|
||
<div className="flex justify-center">
|
||
<Spinner />
|
||
</div>
|
||
)
|
||
}
|
||
|
||
if (teamHasMetricsCheckFailed || hasMetrics === undefined) {
|
||
return <>{children}</>
|
||
}
|
||
|
||
if (!hasMetrics) {
|
||
return <NoMetricsPrompt className={className} />
|
||
}
|
||
|
||
return <>{children}</>
|
||
}
|
||
|
||
const NoMetricsPrompt = ({ className }: { className?: string }): JSX.Element | null => {
|
||
const { addProductIntent } = useActions(teamLogic)
|
||
const { currentTeam } = useValues(teamLogic)
|
||
const { hasMetrics } = useValues(metricsIngestionLogic)
|
||
const { loadTeamHasMetrics, reportScrapeSnippetCopied } = useActions(metricsIngestionLogic)
|
||
const [agentTab, setAgentTab] = useState<'docker' | 'kubernetes'>('docker')
|
||
|
||
useEffect(() => {
|
||
insights.capture('metrics setup prompt viewed')
|
||
}, [])
|
||
|
||
useInterval(() => {
|
||
if (!hasMetrics) {
|
||
loadTeamHasMetrics()
|
||
}
|
||
}, POLLING_INTERVAL_MS)
|
||
|
||
const onDocsLinkClick = (docsType: string): void => {
|
||
insights.capture('metrics onboarding docs clicked', { docs_type: docsType })
|
||
addProductIntent({
|
||
product_type: ProductKey.METRICS,
|
||
intent_context: ProductIntentContext.METRICS_DOCS_VIEWED,
|
||
})
|
||
}
|
||
|
||
const apiKey = currentTeam?.api_token ?? '<your project API key>'
|
||
const dockerSnippet = [
|
||
'docker run -d --name insights-metrics-agent \\',
|
||
` -e INSIGHTS_API_KEY=${apiKey} \\`,
|
||
` -e INSIGHTS_HOST=${apiHostOrigin()} \\`,
|
||
' -e SCRAPE_TARGETS=your-app:9090 \\',
|
||
' insights/metrics-agent:latest',
|
||
].join('\n')
|
||
const helmSnippet = [
|
||
'helm install insights-metrics-agent \\',
|
||
' oci://ghcr.io/insights/charts/insights-metrics-agent \\',
|
||
` --set insights.apiKey=${apiKey} \\`,
|
||
` --set insights.host=${apiHostOrigin()}`,
|
||
'',
|
||
'# then annotate the pods you want scraped:',
|
||
'# prometheus.io/scrape: "true"',
|
||
'# prometheus.io/port: "9090"',
|
||
].join('\n')
|
||
|
||
return (
|
||
<ProductIntroduction
|
||
productName="Metrics"
|
||
thingName="metric"
|
||
titleOverride="You haven't sent any metrics yet"
|
||
description="Insights metrics works with any OpenTelemetry-compatible client. You don't need any Insights-specific packages – just use standard OpenTelemetry libraries to send metrics via OTLP."
|
||
isEmpty={true}
|
||
productKey={ProductKey.METRICS}
|
||
className={className}
|
||
customScript={MascotGreek}
|
||
actionElementOverride={
|
||
<div className="flex flex-col items-start gap-4">
|
||
<p className="text-sm text-secondary m-0">
|
||
Read our{' '}
|
||
<Link to="https://hanzo.ai/docs/metrics" onClick={() => onDocsLinkClick('Metrics')}>
|
||
metrics docs
|
||
</Link>{' '}
|
||
or learn more about{' '}
|
||
<Link
|
||
to="https://opentelemetry.io/docs/what-is-opentelemetry/"
|
||
target="_blank"
|
||
disableDocsPanel
|
||
onClick={() => onDocsLinkClick('OpenTelemetry')}
|
||
>
|
||
OpenTelemetry
|
||
</Link>
|
||
.
|
||
</p>
|
||
<div className="flex flex-col gap-1 w-full max-w-160">
|
||
<h5 className="m-0">Or scrape your existing Prometheus metrics</h5>
|
||
<p className="text-sm text-secondary m-0">
|
||
Already exposing Prometheus metrics? Deploy the Insights metrics agent in your infra and it
|
||
forwards them for you, no code changes needed. Counters and histograms with OpenMetrics
|
||
exemplars get clickable trace links automatically.
|
||
</p>
|
||
<Tabs
|
||
activeKey={agentTab}
|
||
onChange={(key) => {
|
||
setAgentTab(key)
|
||
onDocsLinkClick(key === 'docker' ? 'agent-docker' : 'agent-helm')
|
||
}}
|
||
tabs={[
|
||
{
|
||
key: 'docker' as const,
|
||
label: 'Docker',
|
||
content: (
|
||
<CodeSnippet
|
||
language={Language.Bash}
|
||
onCopy={() => reportScrapeSnippetCopied('docker')}
|
||
>
|
||
{dockerSnippet}
|
||
</CodeSnippet>
|
||
),
|
||
},
|
||
{
|
||
key: 'kubernetes' as const,
|
||
label: 'Kubernetes',
|
||
content: (
|
||
<CodeSnippet
|
||
language={Language.Bash}
|
||
onCopy={() => reportScrapeSnippetCopied('kubernetes')}
|
||
>
|
||
{helmSnippet}
|
||
</CodeSnippet>
|
||
),
|
||
},
|
||
]}
|
||
/>
|
||
</div>
|
||
<div className="flex items-center gap-4">
|
||
<div className="flex items-center gap-2 px-3 py-1.5 border border-accent rounded">
|
||
<div className="relative flex items-center justify-center">
|
||
<div className="absolute w-3 h-3 border-2 border-accent rounded-full animate-ping" />
|
||
<div className="w-2 h-2 bg-accent rounded-full" />
|
||
</div>
|
||
<span className="text-sm">Watching for metrics</span>
|
||
</div>
|
||
<Button
|
||
type="secondary"
|
||
size="small"
|
||
to="https://hanzo.ai/docs/metrics"
|
||
onClick={() => onDocsLinkClick('Docs')}
|
||
>
|
||
View docs
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
}
|
||
/>
|
||
)
|
||
}
|