Skip to content
Merged
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
24 changes: 22 additions & 2 deletions api/doc/agg-query/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,29 @@
},
"operationTrack": {"$ref": "https://github.com/data-fair/metrics/daily-api-metric#/$defs/operationTrack"},
"statusClass": {"$ref": "https://github.com/data-fair/metrics/daily-api-metric#/$defs/statusClass"},
"userClass": {"$ref": "https://github.com/data-fair/metrics/daily-api-metric#/$defs/userClass"},
"userClass": {
"oneOf": [
{"$ref": "https://github.com/data-fair/metrics/daily-api-metric#/$defs/userClass"},
{
"type": "array",
"items": {"$ref": "https://github.com/data-fair/metrics/daily-api-metric#/$defs/userClass"},
"minItems": 1
}
]
},
"resourceType": {"type": "string"},
"resourceId": {"type": "string"},
"resourceId": {
"oneOf": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}, "minItems": 1}
]
},
"refererDomain": {
"oneOf": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}, "minItems": 1}
]
},
"topicId": {"type": "string"},
"processingId": {"type": "string"},
"split": {
Expand Down
69 changes: 49 additions & 20 deletions api/src/daily-api-metrics/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@ const setupWorksheets = (workbook: Excel.stream.xlsx.WorkbookWriter, query: { st
workbook.created = new Date()

const global = workbook.addWorksheet('Global')
global.columns = [
{ header: '', key: 'metric', width: 35 },
{ header: `Période du ${formatDate(query.start)} au ${formatDate(query.end)}`, key: 'current', width: 35 },
{ header: 'Période précédente', key: 'previous', width: 20 },
{ header: 'Variation', key: 'variation', width: 10 }
]
global.getColumn(1).width = 4
global.getColumn(2).width = 30
global.getColumn(3).width = 18
global.getColumn(4).width = 18
global.getColumn(5).width = 10
global.addRow([])
global.addRow(['', `Du ${formatDate(query.start)} au ${formatDate(query.end)}`, 'Période actuelle', 'Période précédente', 'Variation'])

const history = workbook.addWorksheet('Historique')
history.columns = [
Expand Down Expand Up @@ -111,6 +112,32 @@ const setupWorksheets = (workbook: Excel.stream.xlsx.WorkbookWriter, query: { st
return { global, history, dataset, topic, origin, app }
}

const applyGlobalBordersAndFill = (global: Excel.Worksheet) => {
const extBorder = { style: 'thin' as const }
const intBorder = { style: 'hair' as const }

for (let row = 2; row <= 5; row++) {
for (let col = 2; col <= 5; col++) {
const cell = global.getCell(row, col)

cell.border = {
top: row === 2 ? extBorder : intBorder,
bottom: (row === 2 || row === 5) ? extBorder : intBorder,
left: col === 2 ? extBorder : intBorder,
right: (col === 2 || col === 5) ? extBorder : intBorder
}

if (row === 2 || col === 2) {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'A6D0F4' }
}
}
}
}
}

// Update topic stats based on dataset metrics
const updateTopicStats = (topicsStats: Record<string, TopicStats>, dataset: Dataset, datasetMetrics: any) => {
if (!datasetMetrics || !dataset.topics) return
Expand Down Expand Up @@ -165,7 +192,7 @@ const generate = async (
return acc
}, {} as Record<string, TopicStats>)

// Fetch all data in parallel for better performance
// Fetch all data concurrently to improve performance
const [historyData, datasetResults, originResults, appResults, totalResults, userClassResults] = await Promise.all([
getHistory(account, query),
getDataset(account, query, datasetIds),
Expand Down Expand Up @@ -301,9 +328,9 @@ const generate = async (
}

// Add global stats
global.addRow(['Appels d\'API', totalResults.current.readDataAPI, totalResults.previous.readDataAPI])
global.addRow(['Fichiers téléchargés', totalResults.current.readDataFiles, totalResults.previous.readDataFiles])
global.addRow(['Affichages d\'applications', totalResults.current.openApplication, totalResults.previous.openApplication])
global.addRow(['', 'Appels d\'API', totalResults.current.readDataAPI, totalResults.previous.readDataAPI])
global.addRow(['', 'Fichiers téléchargés', totalResults.current.readDataFiles, totalResults.previous.readDataFiles])
global.addRow(['', 'Affichages d\'applications', totalResults.current.openApplication, totalResults.previous.openApplication])

const COLOR = {
POSITIVE: '4CAF50', // Green
Expand All @@ -312,16 +339,16 @@ const generate = async (
}

const metrics = [
{ row: 2, current: totalResults.current.readDataAPI, previous: totalResults.previous.readDataAPI },
{ row: 3, current: totalResults.current.readDataFiles, previous: totalResults.previous.readDataFiles },
{ row: 4, current: totalResults.current.openApplication, previous: totalResults.previous.openApplication }
{ row: 3, current: totalResults.current.readDataAPI, previous: totalResults.previous.readDataAPI },
{ row: 4, current: totalResults.current.readDataFiles, previous: totalResults.previous.readDataFiles },
{ row: 5, current: totalResults.current.openApplication, previous: totalResults.previous.openApplication }
]

metrics.forEach(({ row, current, previous }) => {
const cell = global.getCell(`D${row}`)
const cell = global.getCell(`E${row}`)
const diff = current - previous
cell.value = {
formula: `=(B${row}-C${row})/C${row}`,
formula: `=(C${row}-D${row})/D${row}`,
result: previous !== 0 ? diff / previous : diff === 0 ? 0 : 1
}

Expand All @@ -335,10 +362,11 @@ const generate = async (
}
})

applyGlobalBordersAndFill(global)
global.addRow([])

// Add user class stats
global.addRow(['Répartition par catégories d\'utilisateurs'])
global.addRow(['', 'Répartition par catégories d\'utilisateurs'])
const userClassMap = new Map()
userClassResults.current.forEach((item: { _id: string; nbRequests: any }) => {
if (userClasses[item._id as keyof typeof userClasses]) {
Expand All @@ -360,15 +388,16 @@ const generate = async (
})
}
})
let rowIndex = 7

let rowIndex = 8
userClassMap.forEach((data, id) => {
global.addRow([data.className, data.current, data.previous])
global.addRow(['', data.className, data.current, data.previous])

// Calculate and format percentage change
const cell = global.getCell(`D${rowIndex}`)
const cell = global.getCell(`E${rowIndex}`)
const diff = data.current - data.previous
cell.value = {
formula: `=(B${rowIndex}-C${rowIndex})/C${rowIndex}`,
formula: `=(C${rowIndex}-D${rowIndex})/D${rowIndex}`,
result: data.previous !== 0 ? diff / data.previous : diff === 0 ? 0 : 1
}

Expand Down
5 changes: 3 additions & 2 deletions api/src/daily-api-metrics/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ export const agg = async (account: Account, query: AggQuery) => {
if (query.start) $match.day = { $gte: query.start }
if (query.end) $match.day = { ...$match.day, $lte: query.end }
if (query.statusClass) $match.statusClass = query.statusClass
if (query.userClass) $match.userClass = query.userClass
if (query.userClass) $match.userClass = Array.isArray(query.userClass) ? { $in: query.userClass } : query.userClass
if (query.operationTrack) $match.operationTrack = query.operationTrack
if (query.resourceType) $match['resource.type'] = query.resourceType
if (query.resourceId) $match['resource.id'] = query.resourceId
if (query.resourceId) $match['resource.id'] = Array.isArray(query.resourceId) ? { $in: query.resourceId } : query.resourceId
if (query.refererDomain) $match.refererDomain = Array.isArray(query.refererDomain) ? { $in: query.refererDomain } : query.refererDomain
if (query.processingId) $match['processing._id'] = query.resourceId

const $group: Record<string, any> = {
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ services:
- PUBLIC_URL=http://localhost:5600/data-fair
- WS_PUBLIC_URL=ws://localhost:5600/data-fair
- OBSERVER_ACTIVE=false
- EXTRA_NAV_ITEMS=[{"id":"metrics","can":"admin","iframe":"https://staging-koumoul.com/metrics/embed/home","basePath":"/metrics","icon":"mdi-chart-bar","title":"Audience"}]
- EXTRA_NAV_ITEMS=[{"id":"metrics","iframe":"/metrics/embed/home","basePath":"/metrics","icon":"mdi-chart-bar","title":"Audience","subtitle":"Téléchargements, API"}]

#####
# db and search engine
Expand Down
Loading