fix: stats on API rest

pull/2842/head
Johan Girod 2023-11-29 10:26:38 +01:00
parent 9ac81d5957
commit 759b7c4979
11 changed files with 182978 additions and 183572 deletions

View File

@ -52,7 +52,6 @@ jobs:
ZAMMAD_API_SECRET_KEY: ${{ secrets.ZAMMAD_API_SECRET_KEY }}
ATINTERNET_API_SECRET_KEY: ${{ secrets.ATINTERNET_API_SECRET_KEY }}
ATINTERNET_API_ACCESS_KEY: ${{ secrets.ATINTERNET_API_ACCESS_KEY }}
PLAUSIBLE_API_KEY: ${{ secrets.PLAUSIBLE_API_KEY }}
CRISP_API_IDENTIFIER: ${{ secrets.CRISP_API_IDENTIFIER }}
CRISP_API_KEY: ${{ secrets.CRISP_API_KEY }}
CRISP_WEBSITE_ID: ${{ secrets.CRISP_WEBSITE_ID }}
@ -108,7 +107,6 @@ jobs:
ZAMMAD_API_SECRET_KEY: ${{ secrets.ZAMMAD_API_SECRET_KEY }}
ATINTERNET_API_SECRET_KEY: ${{ secrets.ATINTERNET_API_SECRET_KEY }}
ATINTERNET_API_ACCESS_KEY: ${{ secrets.ATINTERNET_API_ACCESS_KEY }}
PLAUSIBLE_API_KEY: ${{ secrets.PLAUSIBLE_API_KEY }}
CRISP_API_IDENTIFIER: ${{ secrets.CRISP_API_IDENTIFIER }}
CRISP_API_KEY: ${{ secrets.CRISP_API_KEY }}
CRISP_WEBSITE_ID: ${{ secrets.CRISP_WEBSITE_ID }}

View File

@ -24,7 +24,6 @@ jobs:
ZAMMAD_API_SECRET_KEY: ${{ secrets.ZAMMAD_API_SECRET_KEY }}
ATINTERNET_API_SECRET_KEY: ${{ secrets.ATINTERNET_API_SECRET_KEY }}
ATINTERNET_API_ACCESS_KEY: ${{ secrets.ATINTERNET_API_ACCESS_KEY }}
PLAUSIBLE_API_KEY: ${{ secrets.PLAUSIBLE_API_KEY }}
CRISP_API_IDENTIFIER: ${{ secrets.CRISP_API_IDENTIFIER }}
CRISP_API_KEY: ${{ secrets.CRISP_API_KEY }}
CRISP_WEBSITE_ID: ${{ secrets.CRISP_WEBSITE_ID }}

View File

@ -20,7 +20,6 @@ jobs:
ZAMMAD_API_SECRET_KEY: ${{ secrets.ZAMMAD_API_SECRET_KEY }}
ATINTERNET_API_SECRET_KEY: ${{ secrets.ATINTERNET_API_SECRET_KEY }}
ATINTERNET_API_ACCESS_KEY: ${{ secrets.ATINTERNET_API_ACCESS_KEY }}
PLAUSIBLE_API_KEY: ${{ secrets.PLAUSIBLE_API_KEY }}
CRISP_API_IDENTIFIER: ${{ secrets.CRISP_API_IDENTIFIER }}
CRISP_API_KEY: ${{ secrets.CRISP_API_KEY }}
CRISP_WEBSITE_ID: ${{ secrets.CRISP_WEBSITE_ID }}

View File

@ -16,7 +16,6 @@ jobs:
ZAMMAD_API_SECRET_KEY: ${{ secrets.ZAMMAD_API_SECRET_KEY }}
ATINTERNET_API_SECRET_KEY: ${{ secrets.ATINTERNET_API_SECRET_KEY }}
ATINTERNET_API_ACCESS_KEY: ${{ secrets.ATINTERNET_API_ACCESS_KEY }}
PLAUSIBLE_API_KEY: ${{ secrets.PLAUSIBLE_API_KEY }}
CRISP_API_IDENTIFIER: ${{ secrets.CRISP_API_IDENTIFIER }}
CRISP_API_KEY: ${{ secrets.CRISP_API_KEY }}
CRISP_WEBSITE_ID: ${{ secrets.CRISP_WEBSITE_ID }}
@ -27,7 +26,6 @@ jobs:
ZAMMAD_API_SECRET_KEY: ${{ secrets.ZAMMAD_API_SECRET_KEY }}
ATINTERNET_API_SECRET_KEY: ${{ secrets.ATINTERNET_API_SECRET_KEY }}
ATINTERNET_API_ACCESS_KEY: ${{ secrets.ATINTERNET_API_ACCESS_KEY }}
PLAUSIBLE_API_KEY: ${{ secrets.PLAUSIBLE_API_KEY }}
CRISP_API_IDENTIFIER: ${{ secrets.CRISP_API_IDENTIFIER }}
CRISP_API_KEY: ${{ secrets.CRISP_API_KEY }}
CRISP_WEBSITE_ID: ${{ secrets.CRISP_WEBSITE_ID }}

View File

@ -5,7 +5,6 @@ ATINTERNET_API_ACCESS_KEY=
ATINTERNET_API_SECRET_KEY=
DEEPL_API_SECRET=
ZAMMAD_API_SECRET_KEY=
PLAUSIBLE_API_KEY=
SENTRY_AUTH_TOKEN=
# Utilisez votre propre token (voir issue en haut pour en créé un)

View File

@ -1,63 +0,0 @@
import dotenv from 'dotenv'
dotenv.config()
const fetchApiStats = async (page, start, end, interval) => {
if (!process.env.PLAUSIBLE_API_KEY) {
throw new Error(
"Variables d'environnement manquantes : PLAUSIBLE_API_KEY, nous ne récupérons pas les statistiques d'usage"
)
}
const url =
'https://plausible.io/api/v1/stats/timeseries?' +
Object.entries({
site_id: 'mon-entreprise.urssaf.fr/api',
period: 'custom',
date: start + ',' + end,
interval,
metrics: 'pageviews,visitors',
filters: 'event:page==' + page,
})
.map(([k, v]) => encodeURIComponent(k) + '=' + encodeURIComponent(v))
.join('&')
const result = await fetch(url, {
headers: new Headers({
Authorization: `Bearer ${process.env.PLAUSIBLE_API_KEY}`,
}),
})
return await result.json()
}
export const apiStats = async (start, end, interval) => {
const names = ['evaluate', 'rules', 'rule']
const data = Object.values(
(
await Promise.all([
fetchApiStats('/api/v1/evaluate', start, end, interval),
fetchApiStats('/api/v1/rules', start, end, interval),
fetchApiStats('/api/v1/rules/*', start, end, interval),
])
)
.filter((x) => !!x)
.flatMap(({ results }, i) =>
(results || []).map(({ date, pageviews }) => ({
date,
[names[i]]: pageviews,
}))
)
.reduce(
(acc, el) => (
acc[el.date]
? (acc[el.date] = { ...acc[el.date], ...el })
: (acc[el.date] = el),
acc
),
{}
)
)
return data
}

View File

@ -5,7 +5,6 @@ import { fileURLToPath } from 'url'
import dotenv from 'dotenv'
import { createDataDir, readInDataDir, writeInDataDir } from '../utils.js'
import { apiStats } from './fetch-api-stats.js'
dotenv.config()
@ -148,6 +147,45 @@ const buildSiteQuery =
},
})
const buildAPIQuery =
(period, granularity) =>
(page = 1) => ({
columns: ['page', 'm_page_loads'],
space: {
s: [617190, 617189],
},
period: {
p1: [period],
},
evo: {
granularity,
top: {
'page-num': page,
'max-results': 100,
sort: ['-m_page_loads'],
filter: {
property: {
$AND: [
{
page_chapter1: {
$eq: 'api',
},
},
{
page: {
$eq: 'evaluate',
},
},
],
},
},
},
},
options: {
ignore_null_properties: true,
},
})
const yesterday = new Date(new Date().setDate(new Date().getDate() - 1))
.toISOString()
.slice(0, 10)
@ -181,11 +219,25 @@ const last12Months = {
const uniformiseData = (data) =>
data
.map(({ d_evo_day, d_evo_month, m_visits, m_events, ...data }) => ({
date: d_evo_day != null ? d_evo_day : d_evo_month,
nombre: m_visits != null ? m_visits : m_events,
...data,
}))
.map(
({
d_evo_day,
d_evo_month,
m_visits,
m_events,
m_page_loads,
...data
}) => ({
date: d_evo_day != null ? d_evo_day : d_evo_month,
nombre:
m_visits != null
? m_visits
: m_page_loads != null
? m_page_loads
: m_events,
...data,
})
)
// For some reason, an artifact create ghost page with unlogical chapter metrics...
// It seems to only by one per month thought... This hacks resolves it
.filter(({ m_visits }) => m_visits === undefined || m_visits > 2)
@ -203,14 +255,14 @@ async function fetchDailyVisits() {
const site = uniformiseData(
(await fetchApi(buildSiteQuery(last60days, 'D')))[0].Rows
)
const { start, end } = last60days
const api = uniformiseData(
(await fetchApi(buildAPIQuery(last60days, 'D')))[0].Rows
)
return {
pages,
site,
api: await apiStats(start, end, 'date'),
api,
}
}
@ -228,13 +280,14 @@ async function fetchMonthlyVisits() {
(await fetchApi(buildSiteQuery(last12Months, 'M')))[0].Rows
),
]
const { start, end } = last12Months
const api = uniformiseData(
(await fetchApi(buildAPIQuery(last12Months, 'M')))[0].Rows
)
return {
pages,
site,
api: await apiStats(start, end, 'month'),
api,
}
}

View File

@ -70,23 +70,6 @@ export const StatsDetail = ({ stats, accessibleMode }: StatsDetailProps) => {
[visites]
)
type ApiData = {
date: string
nombre: { evaluate: number; rules: number; rule: number }
}
const apiCumul =
filter === 'api-rest' &&
slicedVisits.length > 0 &&
typeof slicedVisits[0]?.nombre === 'object' &&
(slicedVisits as ApiData[]).reduce(
(acc, { nombre }) => ({
evaluate: acc.evaluate + nombre.evaluate,
rules: acc.rules + nombre.rules,
rule: acc.rule + nombre.rule,
}),
{ evaluate: 0, rules: 0, rule: 0 }
)
return (
<>
<H2>Statistiques détaillées</H2>
@ -179,24 +162,6 @@ export const StatsDetail = ({ stats, accessibleMode }: StatsDetailProps) => {
)}
<Grid container spacing={2}>
{apiCumul ? (
<>
<BigIndicator
main={apiCumul.evaluate}
subTitle="Appel à /evaluate"
/>
<BigIndicator main={apiCumul.rules} subTitle="Appel à /rules" />
<BigIndicator main={apiCumul.rule} subTitle="Appel à /rule/*" />
</>
) : (
<BigIndicator
main={formatValue(
typeof totals === 'number' ? totals : totals.accueil
)}
subTitle="Visites"
/>
)}
{typeof totals !== 'number' && 'simulation_commencee' in totals && (
<>
{' '}
@ -222,6 +187,20 @@ export const StatsDetail = ({ stats, accessibleMode }: StatsDetailProps) => {
/>
</>
)}
{typeof totals === 'number' && (
<BigIndicator
main={formatValue(totals)}
subTitle={
filter === 'api-rest' ? (
<>
Nombre d'appels à <code>evaluate</code>
</>
) : (
<>Nombre total de visites </>
)
}
/>
)}
</Grid>
{period === 'mois' && !!satisfaction.length && (

View File

@ -43,7 +43,7 @@ interface Visites {
creer: Page[]
pages: Page[]
site: Site[]
api: API[]
api: Site[]
}
interface Site {
@ -51,13 +51,6 @@ interface Site {
nombre: number
}
interface API {
date: string
evaluate: number
rules: number
rule: number
}
export enum PageChapter2 {
AideDeclarationIndependant = 'aide_declaration_independant',
ArtisteAuteur = 'artiste_auteur',

View File

@ -1,7 +1,5 @@
import { useMemo } from 'react'
import { Trans } from 'react-i18next'
import { Body } from '@/design-system/typography/paragraphs'
import { groupBy } from '@/utils'
import { Page, PageChapter2, PageSatisfaction, StatsStruct } from './types'
@ -28,14 +26,7 @@ export function useStatistiques({
return rawData.site
}
if (filter === 'api-rest') {
return (rawData.api ?? []).map(({ date, ...nombre }) => ({
date,
nombre,
info:
(period === 'jours' ? '2023-06-16' : '2023-06-01') === date ? (
<ChangeJune2023 />
) : null,
}))
return rawData.api
}
if (
typeof filter !== 'string' &&
@ -74,15 +65,6 @@ export function useStatistiques({
}
}
const ChangeJune2023 = () => (
<Body style={{ maxWidth: '350px' }}>
<Trans i18nKey="stats.change_june_2023">
Ajout d'un cache sur l'API pour améliorer les performances et réduire le
nombre de requêtes.
</Trans>
</Body>
)
const isPAM = (name: string | undefined) =>
name &&
[

File diff suppressed because it is too large Load Diff