Skip to content

Commit 382dfda

Browse files
authored
Merge branch 'master' into ar2rsawseen/master2
2 parents 0e444e7 + 777a4f3 commit 382dfda

File tree

27 files changed

+981
-1050
lines changed

27 files changed

+981
-1050
lines changed

.github/workflows/codeql-analysis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141

4242
# Initializes the CodeQL tools for scanning.
4343
- name: Initialize CodeQL
44-
uses: github/codeql-action/init@v3
44+
uses: github/codeql-action/init@v4
4545
with:
4646
languages: ${{ matrix.language }}
4747
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -52,7 +52,7 @@ jobs:
5252
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
5353
# If this step fails, then you should remove it and run the build manually (see below)
5454
- name: Autobuild
55-
uses: github/codeql-action/autobuild@v3
55+
uses: github/codeql-action/autobuild@v4
5656

5757
# ℹ️ Command-line programs to run using the OS shell.
5858
# 📚 https://git.io/JvXDl
@@ -66,4 +66,4 @@ jobs:
6666
# make release
6767

6868
- name: Perform CodeQL Analysis
69-
uses: github/codeql-action/analyze@v3
69+
uses: github/codeql-action/analyze@v4

CHANGELOG.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
1-
## Version 25.03.xx
1+
## Version 25.03.XX
2+
Enterprise Fixes:
3+
- [data-manager] Fixed segment data deletion
4+
- [data-manager] Fixed bug preventing transformation of events ending in a dot
5+
- [users] Fix add/remove user to profile group
6+
- [users] Remove link to profile group page after removing user from group
7+
8+
Dependencies
9+
- Bump lint-staged from 16.2.3 to 16.2.4
10+
- Bump @faker-js/faker from 10.0.0 to 10.1.0 in /ui-tests
11+
- Bump puppeteer from 24.23.0 to 24.24.1
12+
- Bump countly-sdk-nodejs from 24.10.2 to 24.10.3
13+
14+
## Version 25.03.23
215
Fixes:
16+
- [events] Entries in the event list are now sorted alphabetically
317
- [mail] Add smtp debug option for mail module
418

519
Enterprise Fixes:
6-
- [users] Fixed uploading user profile pictures
7-
- [funnels] Show notification if funnel results are from cache/task manager
820
- [block] Fixed filter for consent events
921
- [drill] [survey] Fix survey answer in drill
22+
- [funnels] Show notification if funnel results are from cache/task manager
23+
- [revenue] Card in revenue page are now correctly indentified
1024
- [users] Add survey section to user feedback page
25+
- [users] Fixed uploading user profile pictures
1126

1227

1328
## Version 25.03.22

api/api.js

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const {WriteBatcher, ReadBatcher, InsertBatcher} = require('./parts/data/batcher
1616
const pack = require('../package.json');
1717
const versionInfo = require('../frontend/express/version.info.js');
1818
const moment = require("moment");
19+
const tracker = require('./parts/mgmt/tracker.js');
1920

2021
var t = ["countly:", "api"];
2122
common.processRequest = processRequest;
@@ -38,6 +39,9 @@ else {
3839
process.title = t.join(' ');
3940

4041
plugins.connectToAllDatabases().then(function() {
42+
plugins.loadConfigs(common.db, function() {
43+
tracker.enable();
44+
});
4145
common.writeBatcher = new WriteBatcher(common.db);
4246
common.readBatcher = new ReadBatcher(common.db);
4347
common.insertBatcher = new InsertBatcher(common.db);
@@ -142,6 +146,41 @@ plugins.connectToAllDatabases().then(function() {
142146
require('./utils/log.js').ipcHandler(msg);
143147
});
144148

149+
/**
150+
* Set tracking config
151+
*/
152+
plugins.setConfigs("tracking", {
153+
self_tracking_app: "",
154+
self_tracking_url: "",
155+
self_tracking_app_key: "",
156+
self_tracking_id_policy: "_id",
157+
self_tracking_sessions: true,
158+
self_tracking_events: true,
159+
self_tracking_views: true,
160+
self_tracking_feedback: true,
161+
self_tracking_user_details: true,
162+
server_sessions: true,
163+
server_events: true,
164+
server_crashes: true,
165+
server_views: true,
166+
server_feedback: true,
167+
server_user_details: true,
168+
/*user_sessions: true,
169+
user_events: true,
170+
user_crashes: true,
171+
user_views: true,
172+
user_feedback: true,
173+
user_details: true*/
174+
});
175+
176+
/*plugins.setUserConfigs("tracking", {
177+
user_sessions: false,
178+
user_events: false,
179+
user_crashes: false,
180+
user_views: false,
181+
user_feedback: false
182+
});*/
183+
145184
/**
146185
* Initialize Plugins
147186
*/
@@ -309,7 +348,7 @@ plugins.connectToAllDatabases().then(function() {
309348
// Allow configs to load & scanner to find all jobs classes
310349
setTimeout(() => {
311350
jobs.job('api:topEvents').replace().schedule('at 00:01 am ' + 'every 1 day');
312-
jobs.job('api:ping').replace().schedule('every 1 day');
351+
jobs.job('api:ping').replace().schedule('at 00:01 am ' + 'every 1 day');
313352
jobs.job('api:clear').replace().schedule('every 1 day');
314353
jobs.job('api:clearTokens').replace().schedule('every 1 day');
315354
jobs.job('api:clearAutoTasks').replace().schedule('every 1 day');

api/jobs/ping.js

Lines changed: 99 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
'use strict';
22

33
const job = require('../parts/jobs/job.js'),
4-
log = require('../utils/log.js')('job:ping'),
5-
countlyConfig = require("../../frontend/express/config.js"),
6-
versionInfo = require('../../frontend/express/version.info'),
74
plugins = require('../../plugins/pluginManager.js'),
8-
request = require('countly-request')(plugins.getConfig("security"));
9-
5+
tracker = require('../parts/mgmt/tracker.js');
106

117
/** Class for the job of pinging servers **/
128
class PingJob extends job.Job {
@@ -16,86 +12,114 @@ class PingJob extends job.Job {
1612
* @param {done} done callback
1713
*/
1814
run(db, done) {
19-
request({strictSSL: false, uri: (process.env.COUNTLY_CONFIG_PROTOCOL || "http") + "://" + (process.env.COUNTLY_CONFIG_HOSTNAME || "localhost") + (countlyConfig.path || "") + "/configs"}, function() {});
20-
var countlyConfigOrig = JSON.parse(JSON.stringify(countlyConfig));
21-
var url = "https://count.ly/configurations/ce/tracking";
22-
if (versionInfo.type !== "777a2bf527a18e0fffe22fb5b3e322e68d9c07a6") {
23-
url = "https://count.ly/configurations/ee/tracking";
24-
}
25-
plugins.loadConfigs(db, function() {
15+
plugins.loadConfigs(db, async function() {
2616
const offlineMode = plugins.getConfig("api").offline_mode;
27-
const { countly_tracking } = plugins.getConfig('frontend');
2817
if (!offlineMode) {
29-
request(url, function(err, response, body) {
30-
if (typeof body === "string") {
31-
try {
32-
body = JSON.parse(body);
33-
}
34-
catch (ex) {
35-
body = null;
36-
}
18+
var server = tracker.getBulkServer();
19+
var user = tracker.getBulkUser(server);
20+
if (!user) {
21+
return done();
22+
}
23+
24+
try {
25+
var custom = await tracker.getAllData();
26+
if (Object.keys(custom).length) {
27+
user.user_details({"custom": custom });
3728
}
38-
if (body) {
39-
if (countlyConfigOrig.web.use_intercom && typeof body.intercom !== "undefined") {
40-
countlyConfig.web.use_intercom = body.intercom;
41-
}
42-
if (typeof countlyConfigOrig.web.track === "undefined" && typeof body.stats !== "undefined") {
43-
if (body.stats) {
44-
countlyConfig.web.track = null;
45-
}
46-
else {
47-
countlyConfig.web.track = "none";
48-
}
49-
}
29+
}
30+
catch (ex) {
31+
console.log("Error collecting server data:", ex);
32+
}
33+
var days = 90;
34+
var current_sync = Date.now();
35+
36+
// Atomically retrieve old last_sync value and set new one
37+
var syncResult = await db.collection("plugins").findOneAndUpdate(
38+
{_id: "version"},
39+
{$set: {last_sync: current_sync}},
40+
{
41+
upsert: true,
42+
returnDocument: 'before',
43+
projection: {last_sync: 1}
5044
}
51-
log.d(err, body, countlyConfigOrig, countlyConfig);
52-
if (countly_tracking) {
53-
db.collection("members").findOne({global_admin: true}, function(err2, member) {
54-
if (!err2 && member) {
55-
var date = new Date();
56-
let domain = plugins.getConfig('api').domain;
45+
);
5746

58-
try {
59-
// try to extract hostname from full domain url
60-
const urlObj = new URL(domain);
61-
domain = urlObj.hostname;
62-
}
63-
catch (_) {
64-
// do nothing, domain from config will be used as is
65-
}
47+
var last_sync = syncResult.value ? syncResult.value.last_sync : null;
48+
if (last_sync) {
49+
days = Math.floor((new Date().getTime() - last_sync) / (1000 * 60 * 60 * 24));
50+
}
6651

67-
request({
68-
uri: "https://stats.count.ly/i",
69-
method: "GET",
70-
timeout: 4E3,
71-
qs: {
72-
device_id: domain,
73-
app_key: "e70ec21cbe19e799472dfaee0adb9223516d238f",
74-
timestamp: Math.floor(date.getTime() / 1000),
75-
hour: date.getHours(),
76-
dow: date.getDay(),
77-
no_meta: true,
78-
events: JSON.stringify([
79-
{
80-
key: "PING",
81-
count: 1
82-
}
83-
])
52+
if (days > 0) {
53+
//calculate seconds timestamp of days before today
54+
var startTs = Math.round((new Date().getTime() - (30 * 24 * 60 * 60 * 1000)) / 1000);
55+
56+
//sync server events - use aggregation pipeline to group by day and action on MongoDB side
57+
var aggregationPipeline = [
58+
// Match documents with timestamp greater than startTs and valid action
59+
{
60+
$match: {
61+
ts: { $gt: startTs }
62+
}
63+
},
64+
// Add calculated fields for day grouping
65+
{
66+
$addFields: {
67+
// Convert timestamp to date and set to noon (12:00:00)
68+
dayDate: {
69+
$dateFromParts: {
70+
year: { $year: { $toDate: { $multiply: ["$ts", 1000] } } },
71+
month: { $month: { $toDate: { $multiply: ["$ts", 1000] } } },
72+
day: { $dayOfMonth: { $toDate: { $multiply: ["$ts", 1000] } } },
73+
hour: 12,
74+
minute: 0,
75+
second: 0
8476
}
85-
}, function(a/*, c, b*/) {
86-
log.d('Done running ping job: %j', a);
87-
done();
88-
});
77+
}
78+
}
79+
},
80+
// Convert back to timestamp in seconds
81+
{
82+
$addFields: {
83+
noonTimestamp: {
84+
$divide: [{ $toLong: "$dayDate" }, 1000]
85+
}
8986
}
90-
else {
91-
done();
87+
},
88+
// Group by day and action
89+
{
90+
$group: {
91+
_id: {
92+
day: "$noonTimestamp",
93+
action: "$a"
94+
},
95+
count: { $sum: 1 }
9296
}
93-
});
97+
},
98+
// Project to final format
99+
{
100+
$project: {
101+
_id: 0,
102+
action: "$_id.action",
103+
timestamp: "$_id.day",
104+
count: 1
105+
}
106+
}
107+
];
108+
109+
var cursor = db.collection("systemlogs").aggregate(aggregationPipeline);
110+
111+
while (cursor && await cursor.hasNext()) {
112+
let eventData = await cursor.next();
113+
user.add_event({key: eventData.action, count: eventData.count, timestamp: eventData.timestamp});
94114
}
95-
else {
115+
server.start(function() {
116+
server.stop();
96117
done();
97-
}
98-
});
118+
});
119+
}
120+
else {
121+
done();
122+
}
99123
}
100124
else {
101125
done();
@@ -104,4 +128,4 @@ class PingJob extends job.Job {
104128
}
105129
}
106130

107-
module.exports = PingJob;
131+
module.exports = PingJob;

api/parts/data/usage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ plugins.register("/sdk/user_properties", async function(ob) {
11251125
userProps.av_major = null;
11261126
userProps.av_minor = null;
11271127
userProps.av_patch = null;
1128-
userProps.av_rel = null;
1128+
userProps.av_prerel = null;
11291129
userProps.av_build = null;
11301130
}
11311131
}

0 commit comments

Comments
 (0)