@socialgouv/matomo-postgres 1.2.3 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,8 +4,12 @@
4
4
 
5
5
  Extract matomo data from [`Live.getLastVisitsDetails`](https://developer.matomo.org/api-reference/reporting-api) API and push events and visits informations to Postgres.
6
6
 
7
+ Use [pg_partman](https://github.com/pgpartman/pg_partman) to partition data by month.
8
+
7
9
  ## Usage
8
10
 
11
+ Create the [initial table](./initial.sql) database table then run the following job with correct environment variables.
12
+
9
13
  ```sh
10
14
  npx @socialgouv/matomo-postgres
11
15
  ```
@@ -30,9 +34,9 @@ docker-compose up
30
34
  export MATOMO_URL=
31
35
  export MATOMO_SITE=
32
36
  export MATOMO_KEY=
33
- export DESTINATION_TABLE=
34
- export STARTDATE=
35
- export OFFSET=
37
+ export DESTINATION_TABLE= # optional
38
+ export STARTDATE= # optional
39
+ export OFFSET= # optional
36
40
  export PGDATABASE=postgres://postgres:postgres@127.0.0.1:5455/postgres
37
41
  yarn start
38
42
  ```
@@ -0,0 +1,43 @@
1
+ FROM postgres:13-alpine
2
+
3
+ ENV PG_PARTMAN_VERSION v4.7.0
4
+
5
+ # Install pg_jobmon
6
+ RUN set -ex \
7
+ \
8
+ && apk add --no-cache --virtual .fetch-deps \
9
+ ca-certificates \
10
+ openssl \
11
+ tar \
12
+ \
13
+ && apk add --no-cache --virtual .build-deps \
14
+ autoconf \
15
+ automake \
16
+ g++ \
17
+ clang \
18
+ llvm \
19
+ libtool \
20
+ libxml2-dev \
21
+ make \
22
+ perl
23
+ # Install pg_partman
24
+ RUN set -ex \
25
+ && wget -O pg_partman.tar.gz "https://github.com/pgpartman/pg_partman/archive/$PG_PARTMAN_VERSION.tar.gz" \
26
+ && mkdir -p /usr/src/pg_partman \
27
+ && tar \
28
+ --extract \
29
+ --file pg_partman.tar.gz \
30
+ --directory /usr/src/pg_partman \
31
+ --strip-components 1 \
32
+ && rm pg_partman.tar.gz \
33
+ && cd /usr/src/pg_partman \
34
+ && make \
35
+ && make install \
36
+ && cd / \
37
+ && rm -rf /usr/src/pg_partman \
38
+ && apk del .fetch-deps .build-deps
39
+
40
+ # Copy the init script
41
+ # The Docker Postgres initd script will run anything
42
+ # in the directory /docker-entrypoint-initdb.d
43
+ COPY initdb.sh /docker-entrypoint-initdb.d/initdb.sh
@@ -0,0 +1,13 @@
1
+ #!/bin/bash -e
2
+
3
+ echo "Creating partman extension"
4
+ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
5
+ CREATE SCHEMA partman;
6
+ CREATE EXTENSION pg_partman SCHEMA partman;
7
+ EOSQL
8
+
9
+ echo "ADDING pg_partman_bgw TO postgresql.conf"
10
+ echo "shared_preload_libraries = 'pg_partman_bgw'" >> $PGDATA/postgresql.conf
11
+ echo "pg_partman_bgw.interval = 3600" >> $PGDATA/postgresql.conf
12
+ echo "pg_partman_bgw.role = '$POSTGRES_USER'" >> $PGDATA/postgresql.conf
13
+ echo "pg_partman_bgw.dbname = '$POSTGRES_DB'" >> $PGDATA/postgresql.conf
@@ -1,10 +1,18 @@
1
1
  version: "3.0"
2
2
  services:
3
3
  postgres:
4
- image: postgres:11
4
+ build:
5
+ context: ./docker
6
+ dockerfile: ./Dockerfile
7
+ volumes:
8
+ - postgres_data:/var/lib/postgresql/data
5
9
  environment:
6
10
  POSTGRES_PASSWORD: postgres
7
11
  POSTGRES_USERNAME: postgres
8
12
  TZ: "Europe/Paris"
9
13
  ports:
10
14
  - 5455:5432
15
+
16
+
17
+ volumes:
18
+ postgres_data:
package/initial.sql ADDED
@@ -0,0 +1,73 @@
1
+ -- converting existing matomo table to partitioned witg pg_partman
2
+ -- usage : ON_ERROR_STOP=1 psql < partition.sql
3
+
4
+ --- pg_partman setup
5
+
6
+ CREATE SCHEMA IF NOT EXISTS partman;
7
+ CREATE EXTENSION IF NOT EXISTS pg_partman SCHEMA partman;
8
+
9
+ --- backup and recreate a new partionned matomo table
10
+
11
+ CREATE TABLE IF NOT EXISTS matomo_tmp as (select * from matomo);
12
+
13
+ ALTER TABLE IF EXISTS matomo RENAME TO matomo_backup;
14
+
15
+ CREATE TABLE IF NOT EXISTS matomo
16
+ (
17
+ idsite text,
18
+ idvisit text,
19
+ actions text,
20
+ country text,
21
+ region text,
22
+ city text,
23
+ operatingsystemname text,
24
+ devicemodel text,
25
+ devicebrand text,
26
+ visitduration text,
27
+ dayssincefirstvisit text,
28
+ visitortype text,
29
+ sitename text,
30
+ userid text,
31
+ serverdateprettyfirstaction date,
32
+ action_id text,
33
+ action_type text,
34
+ action_eventcategory text,
35
+ action_eventaction text,
36
+ action_eventname text,
37
+ action_eventvalue decimal,
38
+ action_timespent text,
39
+ action_timestamp timestamp with time zone DEFAULT now(),
40
+ usercustomproperties json,
41
+ usercustomdimensions json,
42
+ dimension1 text,
43
+ dimension2 text,
44
+ dimension3 text,
45
+ dimension4 text,
46
+ dimension5 text,
47
+ dimension6 text,
48
+ dimension7 text,
49
+ dimension8 text,
50
+ dimension9 text,
51
+ dimension10 text,
52
+ action_url text,
53
+ sitesearchkeyword text,
54
+ action_title text
55
+ ) PARTITION BY RANGE (action_timestamp);
56
+
57
+ ALTER TABLE IF EXISTS matomo ADD CONSTRAINT unique_action_id UNIQUE (action_id, action_timestamp);
58
+ ALTER TABLE IF EXISTS matomo ALTER COLUMN action_eventvalue TYPE decimal USING action_eventvalue::decimal;
59
+ CREATE INDEX IF NOT EXISTS idx_action_timestamp_matomo ON matomo (action_timestamp);
60
+ CREATE INDEX IF NOT EXISTS idx_idvisit_matomo ON matomo(idvisit);
61
+ CREATE INDEX IF NOT EXISTS idx_action_eventcategory_matomo ON matomo(action_eventcategory);
62
+ CREATE INDEX IF NOT EXISTS idx_action_type_matomo ON matomo(action_type);
63
+ CREATE INDEX IF NOT EXISTS idx_action_eventaction_matomo ON matomo(action_eventaction);
64
+
65
+ SELECT partman.create_parent('public.matomo', 'action_timestamp', 'native', 'monthly');
66
+
67
+ -- Import des données depuis la table standard vers la table partitionnée
68
+ CALL partman.partition_data_proc('public.matomo', p_source_table := 'public.matomo_tmp', p_order:= 'DESC');
69
+
70
+ VACUUM ANALYZE public.matomo;
71
+
72
+ DROP TABLE if exists matomo_tmp;
73
+
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@socialgouv/matomo-postgres",
3
3
  "description": "Extract visitor events from Matomo API and push to Postgres",
4
- "version": "1.2.3",
4
+ "version": "1.4.0",
5
5
  "types": "types/index.d.ts",
6
6
  "license": "Apache-2.0",
7
7
  "main": "src/index.js",
@@ -21,8 +21,8 @@ Array [
21
21
  ],
22
22
  Array [
23
23
  "insert into matomo
24
- (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions)
25
- values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)
24
+ (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions, dimension1, dimension2, dimension3, dimension4, dimension5, dimension6, dimension7, dimension8, dimension9, dimension10)
25
+ values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38)
26
26
  ON CONFLICT DO NOTHING",
27
27
  Array [
28
28
  "42",
@@ -57,17 +57,32 @@ Array [
57
57
  },
58
58
  Object {
59
59
  "dimension1": "guest",
60
+ "dimension10": "36",
60
61
  "dimension2": "julien",
61
62
  "dimension3": "page",
62
63
  "dimension4": "indonesia",
63
64
  "dimension5": "diving",
65
+ "dimension6": "shop",
66
+ "dimension7": "v1.2.3",
67
+ "dimension8": "fr",
68
+ "dimension9": "light",
64
69
  },
70
+ "guest",
71
+ "julien",
72
+ "page",
73
+ "indonesia",
74
+ "diving",
75
+ "shop",
76
+ "v1.2.3",
77
+ "fr",
78
+ "light",
79
+ "36",
65
80
  ],
66
81
  ],
67
82
  Array [
68
83
  "insert into matomo
69
- (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions)
70
- values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)
84
+ (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions, dimension1, dimension2, dimension3, dimension4, dimension5, dimension6, dimension7, dimension8, dimension9, dimension10)
85
+ values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38)
71
86
  ON CONFLICT DO NOTHING",
72
87
  Array [
73
88
  "42",
@@ -99,17 +114,32 @@ Array [
99
114
  Object {},
100
115
  Object {
101
116
  "dimension1": "guest",
117
+ "dimension10": "36",
102
118
  "dimension2": "julien",
103
119
  "dimension3": "page",
104
120
  "dimension4": "indonesia",
105
121
  "dimension5": "diving",
122
+ "dimension6": "shop",
123
+ "dimension7": "v1.2.3",
124
+ "dimension8": "fr",
125
+ "dimension9": "light",
106
126
  },
127
+ "guest",
128
+ "julien",
129
+ "page",
130
+ "indonesia",
131
+ "diving",
132
+ "shop",
133
+ "v1.2.3",
134
+ "fr",
135
+ "light",
136
+ "36",
107
137
  ],
108
138
  ],
109
139
  Array [
110
140
  "insert into matomo
111
- (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions)
112
- values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)
141
+ (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions, dimension1, dimension2, dimension3, dimension4, dimension5, dimension6, dimension7, dimension8, dimension9, dimension10)
142
+ values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38)
113
143
  ON CONFLICT DO NOTHING",
114
144
  Array [
115
145
  "42",
@@ -141,17 +171,32 @@ Array [
141
171
  Object {},
142
172
  Object {
143
173
  "dimension1": "guest",
174
+ "dimension10": "36",
144
175
  "dimension2": "julien",
145
176
  "dimension3": "page",
146
177
  "dimension4": "indonesia",
147
178
  "dimension5": "diving",
179
+ "dimension6": "shop",
180
+ "dimension7": "v1.2.3",
181
+ "dimension8": "fr",
182
+ "dimension9": "light",
148
183
  },
184
+ "guest",
185
+ "julien",
186
+ "page",
187
+ "indonesia",
188
+ "diving",
189
+ "shop",
190
+ "v1.2.3",
191
+ "fr",
192
+ "light",
193
+ "36",
149
194
  ],
150
195
  ],
151
196
  Array [
152
197
  "insert into matomo
153
- (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions)
154
- values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)
198
+ (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions, dimension1, dimension2, dimension3, dimension4, dimension5, dimension6, dimension7, dimension8, dimension9, dimension10)
199
+ values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38)
155
200
  ON CONFLICT DO NOTHING",
156
201
  Array [
157
202
  "42",
@@ -186,17 +231,32 @@ Array [
186
231
  },
187
232
  Object {
188
233
  "dimension1": "guest",
234
+ "dimension10": "36",
189
235
  "dimension2": "julien",
190
236
  "dimension3": "page",
191
237
  "dimension4": "indonesia",
192
238
  "dimension5": "diving",
239
+ "dimension6": "shop",
240
+ "dimension7": "v1.2.3",
241
+ "dimension8": "fr",
242
+ "dimension9": "light",
193
243
  },
244
+ "guest",
245
+ "julien",
246
+ "page",
247
+ "indonesia",
248
+ "diving",
249
+ "shop",
250
+ "v1.2.3",
251
+ "fr",
252
+ "light",
253
+ "36",
194
254
  ],
195
255
  ],
196
256
  Array [
197
257
  "insert into matomo
198
- (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions)
199
- values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)
258
+ (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions, dimension1, dimension2, dimension3, dimension4, dimension5, dimension6, dimension7, dimension8, dimension9, dimension10)
259
+ values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38)
200
260
  ON CONFLICT DO NOTHING",
201
261
  Array [
202
262
  "42",
@@ -228,17 +288,32 @@ Array [
228
288
  Object {},
229
289
  Object {
230
290
  "dimension1": "guest",
291
+ "dimension10": "36",
231
292
  "dimension2": "julien",
232
293
  "dimension3": "page",
233
294
  "dimension4": "indonesia",
234
295
  "dimension5": "diving",
296
+ "dimension6": "shop",
297
+ "dimension7": "v1.2.3",
298
+ "dimension8": "fr",
299
+ "dimension9": "light",
235
300
  },
301
+ "guest",
302
+ "julien",
303
+ "page",
304
+ "indonesia",
305
+ "diving",
306
+ "shop",
307
+ "v1.2.3",
308
+ "fr",
309
+ "light",
310
+ "36",
236
311
  ],
237
312
  ],
238
313
  Array [
239
314
  "insert into matomo
240
- (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions)
241
- values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)
315
+ (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions, dimension1, dimension2, dimension3, dimension4, dimension5, dimension6, dimension7, dimension8, dimension9, dimension10)
316
+ values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38)
242
317
  ON CONFLICT DO NOTHING",
243
318
  Array [
244
319
  "42",
@@ -270,11 +345,26 @@ Array [
270
345
  Object {},
271
346
  Object {
272
347
  "dimension1": "guest",
348
+ "dimension10": "36",
273
349
  "dimension2": "julien",
274
350
  "dimension3": "page",
275
351
  "dimension4": "indonesia",
276
352
  "dimension5": "diving",
353
+ "dimension6": "shop",
354
+ "dimension7": "v1.2.3",
355
+ "dimension8": "fr",
356
+ "dimension9": "light",
277
357
  },
358
+ "guest",
359
+ "julien",
360
+ "page",
361
+ "indonesia",
362
+ "diving",
363
+ "shop",
364
+ "v1.2.3",
365
+ "fr",
366
+ "light",
367
+ "36",
278
368
  ],
279
369
  ],
280
370
  ]
@@ -19,6 +19,16 @@ Array [
19
19
  "dayssincefirstvisit": "23",
20
20
  "devicebrand": "Inconnu",
21
21
  "devicemodel": "Générique Bureau",
22
+ "dimension1": "guest",
23
+ "dimension10": "36",
24
+ "dimension2": "julien",
25
+ "dimension3": "page",
26
+ "dimension4": "indonesia",
27
+ "dimension5": "diving",
28
+ "dimension6": "shop",
29
+ "dimension7": "v1.2.3",
30
+ "dimension8": "fr",
31
+ "dimension9": "light",
22
32
  "idsite": "42",
23
33
  "idvisit": "124",
24
34
  "operatingsystemname": "Mac",
@@ -28,10 +38,15 @@ Array [
28
38
  "sitename": "tests",
29
39
  "usercustomdimensions": Object {
30
40
  "dimension1": "guest",
41
+ "dimension10": "36",
31
42
  "dimension2": "julien",
32
43
  "dimension3": "page",
33
44
  "dimension4": "indonesia",
34
45
  "dimension5": "diving",
46
+ "dimension6": "shop",
47
+ "dimension7": "v1.2.3",
48
+ "dimension8": "fr",
49
+ "dimension9": "light",
35
50
  },
36
51
  "usercustomproperties": Object {
37
52
  "page-author": "Julien",
@@ -58,6 +73,16 @@ Array [
58
73
  "dayssincefirstvisit": "23",
59
74
  "devicebrand": "Inconnu",
60
75
  "devicemodel": "Générique Bureau",
76
+ "dimension1": "guest",
77
+ "dimension10": "36",
78
+ "dimension2": "julien",
79
+ "dimension3": "page",
80
+ "dimension4": "indonesia",
81
+ "dimension5": "diving",
82
+ "dimension6": "shop",
83
+ "dimension7": "v1.2.3",
84
+ "dimension8": "fr",
85
+ "dimension9": "light",
61
86
  "idsite": "42",
62
87
  "idvisit": "124",
63
88
  "operatingsystemname": "Mac",
@@ -67,10 +92,15 @@ Array [
67
92
  "sitename": "tests",
68
93
  "usercustomdimensions": Object {
69
94
  "dimension1": "guest",
95
+ "dimension10": "36",
70
96
  "dimension2": "julien",
71
97
  "dimension3": "page",
72
98
  "dimension4": "indonesia",
73
99
  "dimension5": "diving",
100
+ "dimension6": "shop",
101
+ "dimension7": "v1.2.3",
102
+ "dimension8": "fr",
103
+ "dimension9": "light",
74
104
  },
75
105
  "usercustomproperties": Object {},
76
106
  "userid": "24",
@@ -94,6 +124,16 @@ Array [
94
124
  "dayssincefirstvisit": "23",
95
125
  "devicebrand": "Inconnu",
96
126
  "devicemodel": "Générique Bureau",
127
+ "dimension1": "guest",
128
+ "dimension10": "36",
129
+ "dimension2": "julien",
130
+ "dimension3": "page",
131
+ "dimension4": "indonesia",
132
+ "dimension5": "diving",
133
+ "dimension6": "shop",
134
+ "dimension7": "v1.2.3",
135
+ "dimension8": "fr",
136
+ "dimension9": "light",
97
137
  "idsite": "42",
98
138
  "idvisit": "124",
99
139
  "operatingsystemname": "Mac",
@@ -103,10 +143,15 @@ Array [
103
143
  "sitename": "tests",
104
144
  "usercustomdimensions": Object {
105
145
  "dimension1": "guest",
146
+ "dimension10": "36",
106
147
  "dimension2": "julien",
107
148
  "dimension3": "page",
108
149
  "dimension4": "indonesia",
109
150
  "dimension5": "diving",
151
+ "dimension6": "shop",
152
+ "dimension7": "v1.2.3",
153
+ "dimension8": "fr",
154
+ "dimension9": "light",
110
155
  },
111
156
  "usercustomproperties": Object {},
112
157
  "userid": "24",
@@ -120,8 +165,8 @@ exports[`importEvent: should extract events from matomo visit actionsDetails and
120
165
  Array [
121
166
  Array [
122
167
  "insert into matomo
123
- (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions)
124
- values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)
168
+ (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions, dimension1, dimension2, dimension3, dimension4, dimension5, dimension6, dimension7, dimension8, dimension9, dimension10)
169
+ values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38)
125
170
  ON CONFLICT DO NOTHING",
126
171
  Array [
127
172
  "42",
@@ -156,17 +201,32 @@ Array [
156
201
  },
157
202
  Object {
158
203
  "dimension1": "guest",
204
+ "dimension10": "36",
159
205
  "dimension2": "julien",
160
206
  "dimension3": "page",
161
207
  "dimension4": "indonesia",
162
208
  "dimension5": "diving",
209
+ "dimension6": "shop",
210
+ "dimension7": "v1.2.3",
211
+ "dimension8": "fr",
212
+ "dimension9": "light",
163
213
  },
214
+ "guest",
215
+ "julien",
216
+ "page",
217
+ "indonesia",
218
+ "diving",
219
+ "shop",
220
+ "v1.2.3",
221
+ "fr",
222
+ "light",
223
+ "36",
164
224
  ],
165
225
  ],
166
226
  Array [
167
227
  "insert into matomo
168
- (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions)
169
- values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)
228
+ (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions, dimension1, dimension2, dimension3, dimension4, dimension5, dimension6, dimension7, dimension8, dimension9, dimension10)
229
+ values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38)
170
230
  ON CONFLICT DO NOTHING",
171
231
  Array [
172
232
  "42",
@@ -198,17 +258,32 @@ Array [
198
258
  Object {},
199
259
  Object {
200
260
  "dimension1": "guest",
261
+ "dimension10": "36",
201
262
  "dimension2": "julien",
202
263
  "dimension3": "page",
203
264
  "dimension4": "indonesia",
204
265
  "dimension5": "diving",
266
+ "dimension6": "shop",
267
+ "dimension7": "v1.2.3",
268
+ "dimension8": "fr",
269
+ "dimension9": "light",
205
270
  },
271
+ "guest",
272
+ "julien",
273
+ "page",
274
+ "indonesia",
275
+ "diving",
276
+ "shop",
277
+ "v1.2.3",
278
+ "fr",
279
+ "light",
280
+ "36",
206
281
  ],
207
282
  ],
208
283
  Array [
209
284
  "insert into matomo
210
- (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions)
211
- values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)
285
+ (idsite, idvisit, actions, country, region, city, operatingsystemname, devicemodel, devicebrand, visitduration, dayssincefirstvisit, visitortype, sitename, userid, serverdateprettyfirstaction, action_id, action_type, action_title, action_eventcategory, action_eventaction, action_eventname, action_eventvalue, action_timespent, action_timestamp, action_url, siteSearchKeyword, usercustomproperties, usercustomdimensions, dimension1, dimension2, dimension3, dimension4, dimension5, dimension6, dimension7, dimension8, dimension9, dimension10)
286
+ values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38)
212
287
  ON CONFLICT DO NOTHING",
213
288
  Array [
214
289
  "42",
@@ -240,11 +315,26 @@ Array [
240
315
  Object {},
241
316
  Object {
242
317
  "dimension1": "guest",
318
+ "dimension10": "36",
243
319
  "dimension2": "julien",
244
320
  "dimension3": "page",
245
321
  "dimension4": "indonesia",
246
322
  "dimension5": "diving",
323
+ "dimension6": "shop",
324
+ "dimension7": "v1.2.3",
325
+ "dimension8": "fr",
326
+ "dimension9": "light",
247
327
  },
328
+ "guest",
329
+ "julien",
330
+ "page",
331
+ "indonesia",
332
+ "diving",
333
+ "shop",
334
+ "v1.2.3",
335
+ "fr",
336
+ "light",
337
+ "36",
248
338
  ],
249
339
  ],
250
340
  ]
@@ -2,8 +2,12 @@
2
2
 
3
3
  exports[`run: should create table 1`] = `
4
4
  Array [
5
- "CREATE TABLE IF NOT EXISTS matomo
6
- (
5
+ "
6
+
7
+ CREATE SCHEMA IF NOT EXISTS partman;
8
+ CREATE EXTENSION IF NOT EXISTS pg_partman SCHEMA partman;
9
+ CREATE TABLE IF NOT EXISTS matomo
10
+ (
7
11
  idsite text,
8
12
  idvisit text,
9
13
  actions text,
@@ -19,20 +23,31 @@ Array [
19
23
  sitename text,
20
24
  userid text,
21
25
  serverdateprettyfirstaction date,
22
- action_id text UNIQUE,
26
+ action_id text,
23
27
  action_type text,
24
28
  action_eventcategory text,
25
29
  action_eventaction text,
26
30
  action_eventname text,
27
31
  action_eventvalue decimal,
28
32
  action_timespent text,
29
- action_timestamp timestamp with time zone,
33
+ action_timestamp timestamp with time zone DEFAULT now(),
30
34
  usercustomproperties json,
31
35
  usercustomdimensions json,
36
+ dimension1 text,
37
+ dimension2 text,
38
+ dimension3 text,
39
+ dimension4 text,
40
+ dimension5 text,
41
+ dimension6 text,
42
+ dimension7 text,
43
+ dimension8 text,
44
+ dimension9 text,
45
+ dimension10 text,
32
46
  action_url text,
33
47
  sitesearchkeyword text,
34
48
  action_title text
35
- )",
49
+ ) PARTITION BY RANGE (action_timestamp);
50
+ ",
36
51
  Array [],
37
52
  ]
38
53
  `;
@@ -12,7 +12,7 @@ const matomoVisit = require("./visit.json");
12
12
 
13
13
  const run = require("../index");
14
14
 
15
- const NB_REQUEST_TO_INIT_DB = 10; // Number of query to init DB (createTable.js)
15
+ const NB_REQUEST_TO_INIT_DB = 1; // Number of query to init DB (createTable.js)
16
16
  const TEST_DATE = new Date();
17
17
 
18
18
  // @ts-ignore
@@ -86,11 +86,6 @@ test("run: should fetch the latest event date if no date provided", async () =>
86
86
 
87
87
  // check db queries
88
88
  expect(mock_pgQuery.mock.calls[NB_REQUEST_TO_INIT_DB][0]).toEqual(
89
- // call 0 is create table
90
- // call 1 is add column usercustomdimension
91
- // call 2 is add column action_url
92
- // ...
93
- //
94
89
  "select action_timestamp from matomo order by action_timestamp desc limit 1"
95
90
  );
96
91
  });
@@ -130,8 +125,6 @@ test("run: should resume using latest event date - offset if no date provided",
130
125
  expect(mock_matomoApi.mock.calls.length).toEqual(daysCount);
131
126
 
132
127
  // check db queries
133
- console.log("daysCount", daysCount);
134
- //console.log("mock_pgQuery.mock.calls", mock_pgQuery.mock.calls);
135
128
  expect(mock_pgQuery.mock.calls.length).toEqual(NB_REQUEST_TO_INIT_DB + 1 + daysCount * 7); // NB_REQUEST_TO_INIT_DB + select queries + days offset
136
129
  });
137
130
 
@@ -152,7 +145,6 @@ test("run: should use today date if nothing in DB", async () => {
152
145
 
153
146
  // check matomo requests
154
147
  expect(mock_matomoApi.mock.calls.length).toEqual(1);
155
- console.log(TEST_DATE, isoDate(TEST_DATE));
156
148
  expect(mock_matomoApi.mock.calls[0][0].date).toEqual(isoDate(TEST_DATE));
157
149
 
158
150
  // check the 4 events inserted
@@ -15,6 +15,11 @@
15
15
  "city": "Buenos Aires",
16
16
  "dimension1": "guest",
17
17
  "dimension3": "page",
18
+ "dimension6": "shop",
19
+ "dimension7": "v1.2.3",
20
+ "dimension8": "fr",
21
+ "dimension9": "light",
22
+ "dimension10": "36",
18
23
  "firstActionTimestamp": 1629496512,
19
24
  "actionDetails": [
20
25
  {
@@ -8,8 +8,12 @@ const { DESTINATION_TABLE } = require("./config");
8
8
  */
9
9
  async function createTable(client) {
10
10
  const table = client.escapeIdentifier(DESTINATION_TABLE);
11
- const text = `CREATE TABLE IF NOT EXISTS ${table}
12
- (
11
+ const text = `
12
+
13
+ CREATE SCHEMA IF NOT EXISTS partman;
14
+ CREATE EXTENSION IF NOT EXISTS pg_partman SCHEMA partman;
15
+ CREATE TABLE IF NOT EXISTS ${table}
16
+ (
13
17
  idsite text,
14
18
  idvisit text,
15
19
  actions text,
@@ -25,39 +29,35 @@ async function createTable(client) {
25
29
  sitename text,
26
30
  userid text,
27
31
  serverdateprettyfirstaction date,
28
- action_id text UNIQUE,
32
+ action_id text,
29
33
  action_type text,
30
34
  action_eventcategory text,
31
35
  action_eventaction text,
32
36
  action_eventname text,
33
37
  action_eventvalue decimal,
34
38
  action_timespent text,
35
- action_timestamp timestamp with time zone,
39
+ action_timestamp timestamp with time zone DEFAULT now(),
36
40
  usercustomproperties json,
37
41
  usercustomdimensions json,
42
+ dimension1 text,
43
+ dimension2 text,
44
+ dimension3 text,
45
+ dimension4 text,
46
+ dimension5 text,
47
+ dimension6 text,
48
+ dimension7 text,
49
+ dimension8 text,
50
+ dimension9 text,
51
+ dimension10 text,
38
52
  action_url text,
39
53
  sitesearchkeyword text,
40
54
  action_title text
41
- )`;
55
+ ) PARTITION BY RANGE (action_timestamp);
56
+ `;
42
57
 
43
58
  await client.query(text, []);
44
59
 
45
- const migrations = [
46
- `ALTER TABLE IF EXISTS ${table} ADD COLUMN IF NOT EXISTS "usercustomdimensions" json;`,
47
- `ALTER TABLE IF EXISTS ${table} ADD COLUMN IF NOT EXISTS "action_url" text;`,
48
- `ALTER TABLE IF EXISTS ${table} ADD COLUMN IF NOT EXISTS "sitesearchkeyword" text;`,
49
- `ALTER TABLE IF EXISTS ${table} ADD COLUMN IF NOT EXISTS "action_title" text;`,
50
- `ALTER TABLE IF EXISTS ${table} ALTER COLUMN action_eventvalue TYPE decimal USING action_eventvalue::decimal;`,
51
- `CREATE INDEX IF NOT EXISTS idx_action_timestamp ON ${table} (action_timestamp);`,
52
- `CREATE INDEX IF NOT EXISTS idx_idvisit ON ${table}(idvisit);`,
53
- `CREATE INDEX IF NOT EXISTS idx_action_eventcategory ON ${table}(action_eventcategory);`,
54
- `CREATE INDEX IF NOT EXISTS idx_action_type ON ${table}(action_type);`,
55
- ];
56
-
57
- // --------------------------------------------- //
58
- // If you add new query: Don't forget to update //
59
- // const `NB_REQUEST_TO_INIT_DB` (index.test.js) //
60
- // --------------------------------------------- //
60
+ const migrations = [];
61
61
 
62
62
  for (const query of migrations) {
63
63
  await client.query(query, []);
@@ -73,7 +73,7 @@ const getEventsFromMatomoVisit = (matomoVisit) => {
73
73
 
74
74
  /** @type {Record<string, string>} */
75
75
  const usercustomdimensions = {};
76
- for (let k = 1; k < 10; k++) {
76
+ for (let k = 1; k < 11; k++) {
77
77
  const dimension = `dimension${k}`;
78
78
  const value = actionDetail[dimension] || matomoVisit[dimension];
79
79
  if (!value) continue; // max 10 custom variables
@@ -92,7 +92,11 @@ const getEventsFromMatomoVisit = (matomoVisit) => {
92
92
  }),
93
93
  // custom variables
94
94
  usercustomproperties,
95
+ // custom dimensions
96
+ // We keep both for backwards compatibility.
97
+ // Current implementation is flat with one column for each dimension.
95
98
  usercustomdimensions,
99
+ ...usercustomdimensions,
96
100
  };
97
101
  return event;
98
102
  });
package/types/matomo.d.ts CHANGED
@@ -96,6 +96,11 @@ export type Visit = {
96
96
  dimension3?: string;
97
97
  dimension4?: string;
98
98
  dimension5?: string;
99
+ dimension6?: string;
100
+ dimension7?: string;
101
+ dimension8?: string;
102
+ dimension9?: string;
103
+ dimension10?: string;
99
104
  experiments: Experiment[];
100
105
  customVariables: any;
101
106
  formConversions: number;