Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/update tracking #317

Merged
merged 2 commits into from
Nov 3, 2023
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
1 change: 1 addition & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ PROXY_URL= # To use only if you are behind a proxy
DISTRICT_TO_SNAPSHOT= # Comma separated list of district to snapshot (used only for dev toolbox)
MATOMO_URL=
MATOMO_SITE_ID=
MATOMO_TOKEN_AUTH=
7 changes: 4 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ services:
volumes:
- db-mongo:/data/db
db-postgres:
build:
build:
dockerfile: docker-resources/postgres/Dockerfile.dev
ports:
- "${POSTGRES_PORT:-5432}:5432"
Expand All @@ -23,7 +23,7 @@ services:
ports:
- "${REDIS_PORT:-6379}:6379"
api:
build:
build:
dockerfile: docker-resources/api/Dockerfile.dev
depends_on:
- db-mongo
Expand Down Expand Up @@ -53,6 +53,7 @@ services:
- JOB_STATUS_LIMIT_DURATION=${JOB_STATUS_LIMIT_DURATION}
- MATOMO_URL=${MATOMO_URL}
- MATOMO_SITE_ID=${MATOMO_SITE_ID}
- MATOMO_TOKEN_AUTH=${MATOMO_TOKEN_AUTH}
- FORCE_DOWNLOAD_CONTOUR=
- FORCE_DOWNLOAD_DATASETS=
ports:
Expand All @@ -69,4 +70,4 @@ volumes:
data:
dist:
db-mongo:
db-postgres:
db-postgres:
69 changes: 46 additions & 23 deletions lib/api/legacy-routes.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const {
ADMIN_TOKEN = '',
API_IDFIX_URL = 'https://plateforme.adresse.data.gouv.fr/api-idfix',
API_IDFIX_TOKEN = '',
BAN_API_URL = '',
} = process.env

const prepareMethode = {
Expand All @@ -56,10 +57,25 @@ const getLegacyTypeFromId = id => {
}
}

let sendToTracker = () => console.warn('Legacy-routes: sendToTracker not yet implemented')
import('../util/analytics-tracker.js').then(s => {
sendToTracker = s.sendToTracker
})
const sendToTracker = async ({url: paramUrl, download: paramDownload, ...params} = {}, ...args) => {
const module = await import('../util/analytics-tracker.js')
if (!module.sendToTracker) {
console.warn('Legacy-routes: sendToTracker not found')
return
}

const url = paramUrl && `${BAN_API_URL}${paramUrl}`
const download = paramDownload && `${BAN_API_URL}${paramDownload}`

return module.sendToTracker(
{
...(url ? {url} : {}),
...(download ? {download} : {}),
...params
},
...args)
}

const trackEventDefault = {
category: 'API Legacy',
value: 1,
Expand Down Expand Up @@ -133,12 +149,13 @@ const analyticsMiddleware = {
next?.()
},
downloadCommuneData(req, res, next) {
const {url} = req
const {url, commune = {}} = req
const {codeCommune, downloadFormat, downloadType} = req.params
const nomCommune = commune?.nomCommune
const trackEvent = {
category: 'Download Commune DATA API (From Legacy)',
action: `Download ${downloadType} (Format ${downloadFormat})`,
name: codeCommune,
category: 'Download',
action: `Download Commune ${downloadType} (Format ${downloadFormat})`,
name: `${codeCommune}${nomCommune ? ` - ${nomCommune}` : ''}`,
value: 1,
}
sendToTracker({url, download: url, trackEvent})
Expand Down Expand Up @@ -186,6 +203,7 @@ app.param(
})
)

// API Download Commune Data
app.get(
'/ban/communes/:codeCommune/download/:downloadFormat/:downloadType',
analyticsMiddleware.downloadCommuneData,
Expand Down Expand Up @@ -213,6 +231,7 @@ app.get(
})
)

// API-Legacy
app.post(
'/ban/communes/:codeCommune/compose',
ensureIsAdmin,
Expand Down Expand Up @@ -367,6 +386,7 @@ app.get(
})
)

// BAN Stats
app.get(
'/ban/stats',
w(async (req, res) => {
Expand All @@ -375,23 +395,26 @@ app.get(
})
)

app.post('/ban/stats', w(async (req, res) => {
const {codesCommune} = req.body
if (!codesCommune || codesCommune.length === 0) {
return res
.status(404)
.send({code: 404, message: 'Paramètre codesCommune manquant ou invalide'})
}
app.post(
'/ban/stats',
w(async (req, res) => {
const {codesCommune} = req.body
if (!codesCommune || codesCommune.length === 0) {
return res
.status(404)
.send({code: 404, message: 'Paramètre codesCommune manquant ou invalide'})
}

try {
const stats = await computeFilteredStats(codesCommune)
res.send(stats)
} catch (error) {
console.error(error)
res.status(500).send({code: 500, message: 'Une erreur est survenu lors du calcul des statistiques'})
}
}))
try {
const stats = await computeFilteredStats(codesCommune)
res.send(stats)
} catch (error) {
console.error(error)
res.status(500).send({code: 500, message: 'Une erreur est survenu lors du calcul des statistiques'})
}
}))

// BAN Carto Tiles
app.get(
'/tiles/ban/:z/:x/:y.pbf',
w(async (req, res) => {
Expand Down
85 changes: 50 additions & 35 deletions lib/util/analytics-tracker.js
Original file line number Diff line number Diff line change
@@ -1,51 +1,66 @@
/* eslint-disable camelcase */

import os from 'node:os'
import MatomoTracker from 'matomo-tracker'

const {MATOMO_URL, MATOMO_SITE_ID, NODE_ENV} = process.env

let MATOMO_ERROR = false
// CF. Tracking HTTP API documentation :
// https://developer.matomo.org/api-reference/tracking-api

let matomo
import os from 'node:os'
import fetch from '../util/fetch.cjs'

const isDevMode = () => NODE_ENV !== 'production'
const {
MATOMO_URL,
MATOMO_SITE_ID,
MATOMO_TOKEN_AUTH,
nkokla marked this conversation as resolved.
Show resolved Hide resolved
NODE_ENV
} = process.env
const isDevMode = NODE_ENV !== 'production'
const matomoUrl = `${MATOMO_URL}/matomo.php`

const logMatomoError = err => {
MATOMO_ERROR = true
console.warn('[WARNING] tracking request:', err)
console.log('error tracking request:', err)
}

const matomoUrl = `${MATOMO_URL}/matomo.php`
const encodeParams = params => Object.fromEntries(
Object
.entries(params || {})
.map(([key, value]) => [key, typeof value === 'string' ? encodeURIComponent(value) : value]),
)

try {
const matomo = new MatomoTracker(MATOMO_SITE_ID, matomoUrl)
matomo.on('error', logMatomoError)
} catch (error) {
logMatomoError(error)
}
export const getTrackEvent = ({category, action, name, value = 1}) => ({
e_c: encodeURIComponent(`${isDevMode ? 'DEVMODE - ' : ''}${category}`), // Category name
e_a: encodeURIComponent(action), // Action name
e_n: encodeURIComponent(name), // Name
e_v: value, // Value
})

export const getTrackEvent = ({category, action, name, value}) => {
const DEVMODE = isDevMode()
export const sendToTracker = async (params = {}) => {
const {url, ua, download, trackEvent, ...otherParams} = params
const safeOtherParams = encodeParams(otherParams)
const requiredParams = {
idsite: MATOMO_SITE_ID,
rec: 1,
ua: ua || encodeURIComponent(`${os.hostname()} / Node.JS ${process.version} / ${os.version()}`),
...(MATOMO_TOKEN_AUTH ? {token_auth: MATOMO_TOKEN_AUTH} : {}),
}
const urlSearchParams = new URLSearchParams({
...requiredParams,
...safeOtherParams,
...(url ? {url: encodeURIComponent(url)} : {}),
...(download ? {download: encodeURIComponent(download)} : {}),
...(trackEvent ? getTrackEvent(trackEvent) : {}),
})

// CF. Tracking HTTP API documentation :
// https://developer.matomo.org/api-reference/tracking-api
try {
const sentToMatomoWithHTTP = await fetch(matomoUrl, {
method: 'POST',
body: urlSearchParams,
})

return {
e_c: `${DEVMODE ? 'DEVMODE - ' : ''}${category}`, // Category name
e_a: action, // Action name
e_n: name, // Name
...(value ? {e_v: value} : {}), // Value
if (sentToMatomoWithHTTP.status !== 200) {
throw new Error(`Matomo HTTP API returned ${sentToMatomoWithHTTP.status}`)
}
} catch (error) {
logMatomoError(error)
}
}

export const sendToTracker = ({url, download, trackEvent}) =>
!MATOMO_ERROR
&& matomo?.track({
ua: `${os.hostname()} / Node.JS ${process.version} / ${os.version()}`,
...(url ? {url} : {}),
...(download ? {download} : {}),
...(trackEvent ? getTrackEvent(trackEvent) : {})
})

export default sendToTracker
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
"leven": "^3.1.0",
"lodash": "^4.17.21",
"lru-cache": "^6.0.0",
"matomo-tracker": "^2.2.4",
"mongodb": "^4.7.0",
"morgan": "^1.10.0",
"ms": "^2.1.3",
Expand Down
5 changes: 0 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6303,11 +6303,6 @@ map-obj@^4.1.0:
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a"
integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==

matomo-tracker@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/matomo-tracker/-/matomo-tracker-2.2.4.tgz#ee397d915d7b2e7964996ca28a0a03f4f0692453"
integrity sha512-7fDy4wRhDQ1dnSxVqmnVqmmos9ACKag0fCBtBD3/Qeoqks7MFqXcO35nfS6S8xU/IXNf7534q/4Gx8fuWKYW6A==

[email protected]:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
Expand Down
Loading