1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

feat: count number of combinations from playground (#4077)

This PR adds plausible tracking of the number of feature combinations
that we get from the advanced playground API.

The event type has been added to plausible

 Relates to #3545
This commit is contained in:
Thomas Heartman 2023-06-23 11:29:13 +02:00 committed by GitHub
parent 89cf16f915
commit 12c00733d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 136 additions and 1 deletions

View File

@ -62,6 +62,7 @@
"@uiw/codemirror-theme-duotone": "4.21.3",
"@uiw/react-codemirror": "4.21.1",
"@vitejs/plugin-react": "3.1.0",
"cartesian": "^1.0.1",
"chart.js": "3.9.1",
"chartjs-adapter-date-fns": "3.0.0",
"classnames": "2.3.2",

View File

@ -36,6 +36,8 @@ import {
} from 'openapi';
import { capitalizeFirst } from 'utils/capitalizeFirst';
import { AdvancedPlaygroundEnvironmentDiffCell } from './AdvancedPlaygroundEnvironmentCell/AdvancedPlaygroundEnvironmentDiffCell';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
import { countCombinations } from './combinationCounter';
const defaultSort: SortingRule<string> = { id: 'name' };
const { value, setValue } = createLocalStorage(
@ -61,6 +63,16 @@ export const AdvancedPlaygroundResultsTable = ({
input,
loading,
}: IAdvancedPlaygroundResultsTableProps) => {
const { trackEvent } = usePlausibleTracker();
if (features) {
trackEvent('playground', {
props: {
eventType: 'number-of-combinations',
count: countCombinations(features),
},
});
}
const [searchParams, setSearchParams] = useSearchParams();
const ref = useLoading(loading);
const [searchValue, setSearchValue] = useState(

View File

@ -0,0 +1,97 @@
import { countCombinations } from './combinationCounter';
import {
AdvancedPlaygroundEnvironmentFeatureSchema,
AdvancedPlaygroundFeatureSchema,
} from 'openapi';
// @ts-expect-error no types available
import cartesian from 'cartesian';
const generateFeature = (
context: Record<string, string>
): AdvancedPlaygroundEnvironmentFeatureSchema => ({
isEnabled: false,
isEnabledInCurrentEnvironment: true,
variant: {
name: 'disabled',
enabled: false,
},
context: {
appName: 'playground',
},
variants: [],
name: 'default',
environment: 'development',
projectId: 'default',
strategies: {
result: false,
data: [
{
name: 'default',
id: '7b233aae-cbc4-45ea-ace2-4c78c8e7e760',
disabled: false,
parameters: {},
result: {
enabled: false,
evaluationStatus: 'complete' as 'complete',
},
constraints: [
{
inverted: false,
values: ['k'],
operator: 'IN',
contextName: 'appName',
caseInsensitive: false,
result: false,
},
],
segments: [],
links: {
edit: '/projects/default/features/default/strategies/edit?environmentId=development&strategyId=7b233aae-cbc4-45ea-ace2-4c78c8e7e760',
},
},
],
},
});
const generateInput = (
featureCount: number,
environments: string[],
contextValues: { [key: string]: string[] }
): AdvancedPlaygroundFeatureSchema[] => {
const cartesianContext = cartesian(contextValues);
return Array.from(Array(featureCount)).map((_, i) => ({
name: `feature-${i}`,
projectId: 'default',
environments: Object.fromEntries(
environments.map(env => [
env,
cartesianContext.map(generateFeature),
])
),
}));
};
it('counts the correct number of combinations', () => {
const assertCount = (
numberOfFeatures: number,
envs: string[],
context: { [k: string]: string[] }
) => {
const totalCombinations =
numberOfFeatures *
envs.length *
Object.values(context)
.map(contextValues => contextValues.length)
.reduce((total, n) => total + n);
const input = generateInput(numberOfFeatures, envs, context);
expect(countCombinations(input)).toEqual(totalCombinations);
};
assertCount(1, ['development'], { x: ['2'] });
assertCount(10, ['development', 'production'], {
x: ['1', '2'],
y: ['x', 'abc'],
});
assertCount(5, ['development'], { x: ['1', '2'] });
});

View File

@ -0,0 +1,12 @@
import { AdvancedPlaygroundFeatureSchema } from 'openapi';
export const countCombinations = (
features: AdvancedPlaygroundFeatureSchema[]
) =>
features.reduce(
(total, feature) =>
total +
Object.values(feature.environments).flatMap(env => Object.keys(env))
.length,
0
);

View File

@ -40,7 +40,8 @@ export type CustomEvents =
| 'demo-open-demo-web'
| 'context-usage'
| 'segment-usage'
| 'strategy-add';
| 'strategy-add'
| 'playground';
export const usePlausibleTracker = () => {
const plausible = useContext(PlausibleContext);

View File

@ -3613,6 +3613,13 @@ caniuse-lite@^1.0.30001400:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001445.tgz#cf2d4eb93f2bcdf0310de9dd6d18be271bc0b447"
integrity sha512-8sdQIdMztYmzfTMO6KfLny878Ln9c2M0fc7EH60IjlP4Dc4PiCy7K2Vl3ITmWgOyPgVQKa5x+UP/KqFsxj4mBg==
cartesian@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cartesian/-/cartesian-1.0.1.tgz#ae3fc8a63e2ba7e2c4989ce696207457bcae65af"
integrity sha512-tR3qKRYpRJ6FXEGuoBwpuCYcwydrk1N2rduy7eWg1Msepi3i5fCxheryw4VBlCqjCbk3Vhjh3eg+IGHtl5H74A==
dependencies:
xtend "^4.0.1"
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@ -9587,6 +9594,11 @@ xregexp@2.0.0:
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943"
integrity sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==
xtend@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
y18n@^5.0.5:
version "5.0.8"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"