mirror of
https://github.com/hanzoai/insights-js.git
synced 2026-11-03 00:53:53 +00:00
Extends the sweep beyond packages/ to the whole repo (178 files): workflows,
.eslintrc, playground, examples, tooling, root docs. Zero upstream-brand refs and
zero such filenames outside the exemptions.
REVERTS A LICENSING ERROR (from earlier rebrand e43ab1af, not this sweep):
- LICENSE had its copyright holder rewritten to 'Insights'. Restored to the real
holder: 'Copyright 2020 Posthog / Hiberly, Inc.' (+ Mixpanel, Inc.).
- NOTICE credited a non-existent upstream (github.com/getinsights/insights-js).
Restored to the real one: github.com/PostHog/posthog-js.
Apache-2.0 4(c) requires retaining upstream attribution; rewriting a third
party's copyright line falsifies ownership. Both files are now excluded from the
guard and documented as exempt in LLM.md.
Also:
- Deleted junk: AGENTS.md~upstream_main (merge leftover), the now-obsolete
rebrand script; renamed upload-*-s3.ts tooling (still used by cli.ts).
- Removed 42 stale playground/example pnpm-lock.yaml files: they pinned upstream
packages the package.json no longer references. Regenerated on install —
sed-ing a lockfile would corrupt its integrity hashes.
- Guard renamed no-posthog.yml -> brand-guard.yml and now assembles the pattern
at runtime, so no filename or file content carries the string (the previous
guard was swept by its own rule, inverting it to forbid 'insights').
99 lines
4.0 KiB
TypeScript
99 lines
4.0 KiB
TypeScript
import { useState } from 'react'
|
|
import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native'
|
|
import Insights from 'insights-react-native'
|
|
|
|
// Counting storage: every setItem is one disk write. We track the count and the
|
|
// bytes serialized so the screen can show what a burst of captures actually
|
|
// costs at the storage layer.
|
|
let writeCount = 0
|
|
let totalBytes = 0
|
|
const cache: Record<string, string> = {}
|
|
const countingStorage = {
|
|
getItem: (key: string) => cache[key] ?? null,
|
|
setItem: (key: string, value: string) => {
|
|
writeCount += 1
|
|
totalBytes += value.length
|
|
cache[key] = value
|
|
},
|
|
}
|
|
|
|
// Dedicated instance for this demo. flushAt is set high so a burst stays in one
|
|
// batch and we observe storage *write coalescing* rather than a flush-per-capture.
|
|
// (The main app instance in app/insights.tsx uses flushAt: 1, which drains storage
|
|
// on every capture and would hide the effect.)
|
|
const burstInsights = new Insights(process.env.EXPO_PUBLIC_INSIGHTS_PROJECT_API_KEY ?? 'phc_storage_burst_demo', {
|
|
host: process.env.EXPO_PUBLIC_INSIGHTS_API_HOST,
|
|
flushAt: 1000,
|
|
captureAppLifecycleEvents: false,
|
|
customStorage: countingStorage,
|
|
})
|
|
|
|
const BURST_SIZE = 100
|
|
|
|
export default function StorageBurstScreen() {
|
|
const [result, setResult] = useState<{ writes: number; kb: string } | null>(null)
|
|
const [running, setRunning] = useState(false)
|
|
|
|
const fireBurst = async (): Promise<void> => {
|
|
setRunning(true)
|
|
setResult(null)
|
|
const beforeWrites = writeCount
|
|
const beforeBytes = totalBytes
|
|
|
|
for (let i = 0; i < BURST_SIZE; i++) {
|
|
burstInsights.capture('storage_burst_event', { index: i })
|
|
}
|
|
|
|
// Writes are debounced, so the coalesced write lands on a later tick.
|
|
// Wait past the window before reading the counters.
|
|
await new Promise((resolve) => setTimeout(resolve, 300))
|
|
|
|
setResult({
|
|
writes: writeCount - beforeWrites,
|
|
kb: ((totalBytes - beforeBytes) / 1024).toFixed(1),
|
|
})
|
|
setRunning(false)
|
|
}
|
|
|
|
return (
|
|
<ScrollView contentContainerStyle={styles.container}>
|
|
<Text style={styles.title}>Storage write coalescing</Text>
|
|
<Text style={styles.body}>
|
|
Fires {BURST_SIZE} captures in a tight loop and counts the disk writes the SDK performs. With
|
|
debounced coalescing, the burst collapses into a single write instead of one per capture.
|
|
</Text>
|
|
|
|
<Pressable
|
|
style={[styles.button, running && styles.buttonDisabled]}
|
|
onPress={fireBurst}
|
|
disabled={running}
|
|
testID="fire-burst"
|
|
>
|
|
<Text style={styles.buttonText}>{running ? 'Running…' : `Fire ${BURST_SIZE} events`}</Text>
|
|
</Pressable>
|
|
|
|
{result && (
|
|
<View style={styles.result} testID="burst-result">
|
|
<Text style={styles.resultLine}>Captures fired: {BURST_SIZE}</Text>
|
|
<Text style={styles.resultBig}>Disk writes: {result.writes}</Text>
|
|
<Text style={styles.resultLine}>Bytes serialized: {result.kb} KB</Text>
|
|
<Text style={styles.resultHint}>Without coalescing this would be {BURST_SIZE} writes.</Text>
|
|
</View>
|
|
)}
|
|
</ScrollView>
|
|
)
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: { padding: 24, paddingTop: 80, gap: 16 },
|
|
title: { fontSize: 22, fontWeight: '700' },
|
|
body: { fontSize: 15, lineHeight: 21, opacity: 0.8 },
|
|
button: { backgroundColor: '#1d4aff', paddingVertical: 14, paddingHorizontal: 20, borderRadius: 10, alignItems: 'center' },
|
|
buttonDisabled: { opacity: 0.5 },
|
|
buttonText: { color: '#fff', fontSize: 16, fontWeight: '600' },
|
|
result: { gap: 6, padding: 16, borderRadius: 10, backgroundColor: 'rgba(127,127,127,0.12)' },
|
|
resultLine: { fontSize: 15 },
|
|
resultBig: { fontSize: 24, fontWeight: '700', color: '#1d4aff' },
|
|
resultHint: { fontSize: 13, opacity: 0.7, marginTop: 4 },
|
|
})
|