From c2f1a2dadb083453aa2424d9e9f7de5185df4ed6 Mon Sep 17 00:00:00 2001 From: Kanwar Ujjaval Singh <4216199+kanwarujjaval@users.noreply.github.com> Date: Sat, 19 Apr 2025 10:44:22 +0530 Subject: [PATCH 01/12] minor typos --- api/parts/data/changeStreamReader.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/parts/data/changeStreamReader.js b/api/parts/data/changeStreamReader.js index e4c3bacb191..c7cd169b9e1 100644 --- a/api/parts/data/changeStreamReader.js +++ b/api/parts/data/changeStreamReader.js @@ -9,7 +9,7 @@ class changeStreamReader { /** * @param {Object} db - Database object * @param {Object} options - Options object - * @param {function} onData - Finction to call when getting new data from stream + * @param {function} onData - Function to call when getting new data from stream */ constructor(db, options, onData,) { this.db = db; @@ -29,8 +29,8 @@ class changeStreamReader { this.fallback = options.fallback; //I give data - //Processor function processes. Sends last processed tken from time to time. - //Update last processed token to database + //Processor function processes. Sends last processed token from time to time. + //Update the last processed token to database //On startup - read token, resume from that token. this.setUp(onData, false); From 689adebb2e41701deaec314492aec3c351fb2f37 Mon Sep 17 00:00:00 2001 From: Kanwar Ujjaval Singh <4216199+kanwarujjaval@users.noreply.github.com> Date: Sat, 19 Apr 2025 10:45:23 +0530 Subject: [PATCH 02/12] dev logger improvement --- api/utils/log.js | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/api/utils/log.js b/api/utils/log.js index 205141a0570..3e9ccd5c0b9 100644 --- a/api/utils/log.js +++ b/api/utils/log.js @@ -16,6 +16,17 @@ catch (e) { // do nothing } +/** + * Fallback for performance.now() if not available + * @returns {number} Current timestamp in milliseconds + */ +const getNow = () => { + if (typeof performance !== 'undefined' && performance.now) { + return performance.now(); + } + return Date.now(); +}; + /** * Mapping of short level codes to full level names * @type {Object.} @@ -153,6 +164,25 @@ const logLevel = function(name) { } }; +/** + * Build a transport config: pretty in dev, JSON in prod. + * @returns {Object} Transport config + */ +function getTransport() { + if (process.env.NODE_ENV === 'development') { + return { + target: 'pino-pretty', + options: { + colorize: true, + translateTime: 'yyyy-mm-dd HH:MM:ss.l', + ignore: 'pid,hostname' + } + }; + } + return undefined; +} + + /** * Creates a Pino logger instance with the appropriate configuration * @param {string} name - The module name @@ -168,11 +198,14 @@ const createLogger = (name, level) => { level: (label) => { return { level: label.toUpperCase() }; }, - log: (object) => { + log: (obj) => { const traceContext = getTraceContext(); - return traceContext ? { ...object, ...traceContext } : object; + return traceContext ? { ...obj, ...traceContext } : obj; } - } + }, + sync: false, + browser: false, + transport: getTransport() }); }; @@ -187,7 +220,7 @@ const createLogFunction = (logger, name, level) => { return function(...args) { const currentLevel = levels[name] || deflt; if (ACCEPTABLE[level].indexOf(currentLevel) !== -1) { - const startTime = performance.now(); + const startTime = getNow(); const message = args[0]; // Create span for this logging operation @@ -207,7 +240,7 @@ const createLogFunction = (logger, name, level) => { // Record duration if (logDurationHistogram) { - const duration = (performance.now() - startTime) / 1000; // Convert to seconds + const duration = (getNow() - startTime) / 1000; // Convert to seconds logDurationHistogram.record(duration, { module: name, level: LEVELS[level] From e86ef06dad57dfcfb6be0eceebb6034119b666d3 Mon Sep 17 00:00:00 2001 From: Kanwar Ujjaval Singh <4216199+kanwarujjaval@users.noreply.github.com> Date: Sat, 19 Apr 2025 10:45:53 +0530 Subject: [PATCH 03/12] start ingestor with sane defaults without config --- api/ingestor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/ingestor.js b/api/ingestor.js index f0db837a209..984f53d7509 100644 --- a/api/ingestor.js +++ b/api/ingestor.js @@ -273,7 +273,7 @@ plugins.connectToAllDatabases(true).then(function() { else { common.returnMessage(params, 405, "Method not allowed"); } - }).listen(common.config.ingestor.port, common.config.ingestor.host || '').timeout = common.config.ingestor.timeout || 120000; + }).listen(common.config?.ingestor?.port || 3010, common.config?.ingestor?.host || '').timeout = common.config?.ingestor?.timeout || 120000; }); }); From 4c6c1c3d5342e1554afbd174e3d9b5ac7d26d00a Mon Sep 17 00:00:00 2001 From: Kanwar Ujjaval Singh <4216199+kanwarujjaval@users.noreply.github.com> Date: Sat, 19 Apr 2025 10:46:06 +0530 Subject: [PATCH 04/12] fix for separate connection pool --- plugins/pluginManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/pluginManager.js b/plugins/pluginManager.js index f58f18ba2c1..3fd8de7590f 100644 --- a/plugins/pluginManager.js +++ b/plugins/pluginManager.js @@ -1838,7 +1838,7 @@ var pluginManager = function pluginManager() { } else { console.log("using separate connection pool"); - databases = await Promise.all(dbs.map(this.dbConnection.bind(this, return_original))); + databases = await Promise.all(dbs.map((db) => this.dbConnection(db, return_original))); } const [dbCountly, dbOut, dbFs, dbDrill] = databases; From 283d1f5a098432de8187e45bd734f7c0326459b9 Mon Sep 17 00:00:00 2001 From: Kanwar Ujjaval Singh <4216199+kanwarujjaval@users.noreply.github.com> Date: Sat, 19 Apr 2025 12:13:07 +0530 Subject: [PATCH 05/12] remove subapp specific eslint config from global lint --- .eslintrc.json | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 41c7c2f28f1..e7829784d55 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -374,44 +374,6 @@ "es2023": true } }, - { - "files": [ - "plugins/content/frontend/content-blocks/**/*.js", - "plugins/journey_engine/frontend/builder/**/*.js", - "plugins/content/frontend/content-blocks/**/*.vue", - "plugins/journey_engine/frontend/builder/**/*.vue" - ], - "plugins": [ - "vue", - "@stylistic" - ], - "extends": [ - "eslint:recommended", - "plugin:vue/vue3-essential", - "plugin:vue/vue3-strongly-recommended", - "plugin:vue/vue3-recommended" - ], - "rules": { - // override these post initial content release, to make them fit with countly convention - "no-console": ["error"], - "@stylistic/quotes": ["error", "single"], - "@stylistic/quote-props": ["error", "as-needed"], - "no-unused-vars": "off", - "vue/no-unused-vars": ["error", { - "ignorePattern": "^_" - }] - }, - "parserOptions": { - "ecmaVersion": 2023, - "sourceType": "module", - "extraFileExtensions": [".vue"] - }, - "env": { - "node": true, - "es2023": true, - "es6": true - } - }, { "files": [ "frontend/express/public/javascripts/countly/*.js", From a219df9cc112f9f95d2a1d90d4ae53a9c55cc2f1 Mon Sep 17 00:00:00 2001 From: Kanwar Ujjaval Singh <4216199+kanwarujjaval@users.noreply.github.com> Date: Sat, 19 Apr 2025 14:36:41 +0530 Subject: [PATCH 06/12] [experimental] add clickhouse client --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index c5c6f7e5764..0145cc1755a 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ }, "dependencies": { "@breejs/later": "^4.2.0", + "@clickhouse/client": "^1.11.1", "@pulsecron/pulse": "1.6.7", "all-the-cities": "3.1.0", "argon2": "0.41.1", From 805101212f22cfdda89a191ae0664f6e0d4e81e1 Mon Sep 17 00:00:00 2001 From: Kanwar Ujjaval Singh <4216199+kanwarujjaval@users.noreply.github.com> Date: Mon, 21 Apr 2025 13:34:39 +0530 Subject: [PATCH 07/12] temporary fixes to make it work --- api/ingestor.js | 8 +++++++- api/parts/mgmt/app_users.js | 8 ++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/api/ingestor.js b/api/ingestor.js index 984f53d7509..d418373d0a6 100644 --- a/api/ingestor.js +++ b/api/ingestor.js @@ -18,7 +18,13 @@ console.log("Connecting to databases"); //Overriding function plugins.loadConfigs = plugins.loadConfigsIngestor; -plugins.connectToAllDatabases(true).then(function() { +/** + * TODO + * temporarily change this false since it fails at + * Cannot create uid TypeError: common.db.ObjectID is not a function + * at usersApi.getUid (api/parts/mgmt/app_users.js:434:90) + */ +plugins.connectToAllDatabases(false).then(function() { log.i("Db connections done"); // common.writeBatcher = new WriteBatcher(common.db); common.readBatcher = new Cacher(common.db); diff --git a/api/parts/mgmt/app_users.js b/api/parts/mgmt/app_users.js index e438db69ccb..50709b4c29f 100644 --- a/api/parts/mgmt/app_users.js +++ b/api/parts/mgmt/app_users.js @@ -435,9 +435,13 @@ usersApi.getUid = async function(app_id, callback) { returnDocument: 'after', upsert: true }); - if (result && result.seq) { + /** + * TODO + * temporarily use .value since thats what the findOneAndUpdate returns + */ + if (result && result.value.seq) { if (callback) { - callback(null, common.parseSequence(result.seq)); + callback(null, common.parseSequence(result.value.seq)); } } else if (callback) { From 20c4c2f1290787ee0dc113f946ce1ee28c45e52f Mon Sep 17 00:00:00 2001 From: Kanwar Ujjaval Singh <4216199+kanwarujjaval@users.noreply.github.com> Date: Mon, 21 Apr 2025 13:50:00 +0530 Subject: [PATCH 08/12] add configuration for ingestor process --- .../public/javascripts/countly/countly.config.sample.js | 7 +++++++ .../frontend/public/javascripts/countly.models.js | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/frontend/express/public/javascripts/countly/countly.config.sample.js b/frontend/express/public/javascripts/countly/countly.config.sample.js index c2216c9584c..2e7c49eb5f8 100644 --- a/frontend/express/public/javascripts/countly/countly.config.sample.js +++ b/frontend/express/public/javascripts/countly/countly.config.sample.js @@ -11,6 +11,13 @@ * @type {string} */ countlyCommon.API_URL = countlyGlobal.path || ""; + + /** + * Ingestor service URL. This is used for the ingestion of data for /i and /i/bulk endpoints. + * @type {string} + */ + countlyCommon.INGESTOR_URL = countlyGlobal.path || ""; + /** * Main api path to make all ajax requests to. This value is configured in countly.config.js or over written through theme. * @property {object} data - contains default read and write endpoints diff --git a/plugins/populator/frontend/public/javascripts/countly.models.js b/plugins/populator/frontend/public/javascripts/countly.models.js index 5cd7f389675..25cd6e996d6 100644 --- a/plugins/populator/frontend/public/javascripts/countly.models.js +++ b/plugins/populator/frontend/public/javascripts/countly.models.js @@ -1178,7 +1178,7 @@ this.reportConversion = function(uid, campaingId, deviceId) { $.ajax({ type: "GET", - url: countlyCommon.API_URL + "/i", + url: countlyCommon.INGESTOR_URL + "/i", data: { campaign_id: uid, campaign_user: campaingId, @@ -1365,7 +1365,7 @@ if (generating) { $.ajax({ type: "POST", - url: countlyCommon.API_URL + "/i/bulk", + url: countlyCommon.INGESTOR_URL + "/i/bulk", data: { app_key: countlyCommon.ACTIVE_APP_KEY, requests: JSON.stringify(req), From 0706c1c5861f2279a351d7c94608ff585c48f40c Mon Sep 17 00:00:00 2001 From: Kanwar Ujjaval Singh <4216199+kanwarujjaval@users.noreply.github.com> Date: Mon, 21 Apr 2025 15:46:55 +0530 Subject: [PATCH 09/12] remove deprecated dont-enclose from requires --- api/aggregator.js | 2 +- api/api.js | 2 +- api/ingestor.js | 2 +- api/parts/jobs/index.js | 2 +- api/tcp_example.js | 2 +- api/utils/common.js | 2 +- api/utils/log.js | 2 +- api/utils/render.js | 2 +- api/utils/utils.js | 2 +- frontend/express/app.js | 2 +- frontend/express/libs/members.js | 2 +- plugins/crashes/frontend/app.js | 2 +- plugins/dashboards/frontend/app.js | 2 +- plugins/enterpriseinfo/frontend/app.js | 2 +- plugins/locale/frontend/app.js | 2 +- plugins/pluginManager.js | 10 +++++----- plugins/recaptcha/frontend/app.js | 2 +- plugins/reports/api/reports.js | 2 +- 18 files changed, 22 insertions(+), 22 deletions(-) diff --git a/api/aggregator.js b/api/aggregator.js index 67c820329b2..19adb75e645 100644 --- a/api/aggregator.js +++ b/api/aggregator.js @@ -1,4 +1,4 @@ -const countlyConfig = require('./config', 'dont-enclose'); +const countlyConfig = require('./config'); const plugins = require('../plugins/pluginManager.js'); const log = require('./utils/log.js')('aggregator-core:api'); const common = require('./utils/common.js'); diff --git a/api/api.js b/api/api.js index bb7bb8c4f8f..cb0f2f20a18 100644 --- a/api/api.js +++ b/api/api.js @@ -1,6 +1,6 @@ const http = require('http'); const formidable = require('formidable'); -const countlyConfig = require('./config', 'dont-enclose'); +const countlyConfig = require('./config'); const plugins = require('../plugins/pluginManager.js'); const log = require('./utils/log.js')('core:api'); const common = require('./utils/common.js'); diff --git a/api/ingestor.js b/api/ingestor.js index d418373d0a6..aac4b1ad1ab 100644 --- a/api/ingestor.js +++ b/api/ingestor.js @@ -1,6 +1,6 @@ const http = require('http'); const formidable = require('formidable'); -const countlyConfig = require('./config', 'dont-enclose'); +const countlyConfig = require('./config'); const plugins = require('../plugins/pluginManager.js'); const log = require('./utils/log.js')('ingestor-core:api'); const {processRequest} = require('./ingestor/requestProcessor'); diff --git a/api/parts/jobs/index.js b/api/parts/jobs/index.js index 231d30e2d89..d7316ba9200 100644 --- a/api/parts/jobs/index.js +++ b/api/parts/jobs/index.js @@ -1,6 +1,6 @@ 'use strict'; -const countlyConfig = require('./../../config', 'dont-enclose'); +const countlyConfig = require('./../../config'); if (require('cluster').isMaster && process.argv[1].endsWith('api/api.js') && !(countlyConfig && countlyConfig.preventJobs)) { module.exports = require('./manager.js'); diff --git a/api/tcp_example.js b/api/tcp_example.js index 387ff224850..5d53fa48d37 100644 --- a/api/tcp_example.js +++ b/api/tcp_example.js @@ -1,5 +1,5 @@ const net = require('net'); -const countlyConfig = require('./config', 'dont-enclose'); +const countlyConfig = require('./config'); const plugins = require('../plugins/pluginManager.js'); const log = require('./utils/log.js')('core:tcp'); const common = require('./utils/common.js'); diff --git a/api/utils/common.js b/api/utils/common.js index d0704d17cb2..0ef31ee1157 100644 --- a/api/utils/common.js +++ b/api/utils/common.js @@ -10,7 +10,7 @@ var common = {}, logger = require('./log.js'), mcc_mnc_list = require('mcc-mnc-list'), plugins = require('../../plugins/pluginManager.js'), - countlyConfig = require('./../config', 'dont-enclose'), + countlyConfig = require('./../config'), argon2 = require('argon2'), mongodb = require('mongodb'), getRandomValues = require('get-random-values'), diff --git a/api/utils/log.js b/api/utils/log.js index 3e9ccd5c0b9..ee2d89862ab 100644 --- a/api/utils/log.js +++ b/api/utils/log.js @@ -51,7 +51,7 @@ const ACCEPTABLE = { // Initialize configuration with defaults -let prefs = require('../config.js', 'dont-enclose').logging || {}; +let prefs = require('../config.js').logging || {}; prefs.default = prefs.default || "warn"; let deflt = (prefs && prefs.default) ? prefs.default : 'error'; diff --git a/api/utils/render.js b/api/utils/render.js index ee01d946878..c8f538428e2 100644 --- a/api/utils/render.js +++ b/api/utils/render.js @@ -24,7 +24,7 @@ var alternateChrome = true; var chromePath = ""; var countlyFs = require('./countlyFs'); var log = require('./log.js')('core:render'); -var countlyConfig = require('./../config', 'dont-enclose'); +var countlyConfig = require('./../config'); /** diff --git a/api/utils/utils.js b/api/utils/utils.js index b1c7925c81c..82e8ebdea8f 100644 --- a/api/utils/utils.js +++ b/api/utils/utils.js @@ -3,7 +3,7 @@ * @module api/utils/utils */ var crypto = require('crypto'), - countlyConfig = require('./../config', 'dont-enclose'); + countlyConfig = require('./../config'); if (!countlyConfig.encryption) { countlyConfig.encryption = {}; diff --git a/frontend/express/app.js b/frontend/express/app.js index 77eaa3d0fed..c46444323a4 100644 --- a/frontend/express/app.js +++ b/frontend/express/app.js @@ -61,7 +61,7 @@ var versionInfo = require('./version.info'), preventBruteforce = require('./libs/preventBruteforce.js'), plugins = require('../../plugins/pluginManager.js'), request = require('countly-request')(plugins.getConfig("security")), - countlyConfig = require('./config', 'dont-enclose'), + countlyConfig = require('./config'), log = require('../../api/utils/log.js')('core:app'), url = require('url'), authorize = require('../../api/utils/authorizer.js'), //for token validations diff --git a/frontend/express/libs/members.js b/frontend/express/libs/members.js index a9c42ad2f83..e47b33c4cfd 100755 --- a/frontend/express/libs/members.js +++ b/frontend/express/libs/members.js @@ -13,7 +13,7 @@ var authorize = require('./../../../api/utils/authorizer.js'); //for token valid var common = require('./../../../api/utils/common.js'); var plugins = require('./../../../plugins/pluginManager.js'); var { getUserApps } = require('./../../../api/utils/rights.js'); -var configs = require('./../config', 'dont-enclose'); +var configs = require('./../config'); var countlyMail = require('./../../../api/parts/mgmt/mail.js'); var countlyStats = require('./../../../api/parts/data/stats.js'); var request = require('countly-request')(plugins.getConfig("security")); diff --git a/plugins/crashes/frontend/app.js b/plugins/crashes/frontend/app.js index c8514a58155..5c5d8506b6a 100644 --- a/plugins/crashes/frontend/app.js +++ b/plugins/crashes/frontend/app.js @@ -1,5 +1,5 @@ var exportedPlugin = {}, - countlyConfig = require('../../../frontend/express/config', 'dont-enclose'); + countlyConfig = require('../../../frontend/express/config'); var config; try { diff --git a/plugins/dashboards/frontend/app.js b/plugins/dashboards/frontend/app.js index c623758c11c..6bd1af51672 100644 --- a/plugins/dashboards/frontend/app.js +++ b/plugins/dashboards/frontend/app.js @@ -1,6 +1,6 @@ var plugins = require('../../pluginManager.js'); var exported = {}; -var countlyConfig = require('../../../frontend/express/config', 'dont-enclose'); +var countlyConfig = require('../../../frontend/express/config'); var countlyFs = require('../../../api/utils/countlyFs.js'); (function(plugin) { diff --git a/plugins/enterpriseinfo/frontend/app.js b/plugins/enterpriseinfo/frontend/app.js index d6dd1f48626..171757204df 100644 --- a/plugins/enterpriseinfo/frontend/app.js +++ b/plugins/enterpriseinfo/frontend/app.js @@ -1,5 +1,5 @@ var exported = {}, - countlyConfig = require('../../../frontend/express/config', 'dont-enclose'), + countlyConfig = require('../../../frontend/express/config'), versionInfo = require('../../../frontend/express/version.info'), async = require('async'); diff --git a/plugins/locale/frontend/app.js b/plugins/locale/frontend/app.js index d75e59a2860..98cce808468 100644 --- a/plugins/locale/frontend/app.js +++ b/plugins/locale/frontend/app.js @@ -1,5 +1,5 @@ var exported = {}, - countlyConfig = require('../../../frontend/express/config', 'dont-enclose'), + countlyConfig = require('../../../frontend/express/config'), langs = require('../api/utils/langs.js'); (function(plugin) { diff --git a/plugins/pluginManager.js b/plugins/pluginManager.js index 3fd8de7590f..fd2aec96c77 100644 --- a/plugins/pluginManager.js +++ b/plugins/pluginManager.js @@ -1,13 +1,13 @@ var pluginDependencies = require('./pluginDependencies.js'), path = require('path'), - plugins = pluginDependencies.getFixedPluginList(require('./plugins.json', 'dont-enclose'), { + plugins = pluginDependencies.getFixedPluginList(require('./plugins.json'), { "discoveryStrategy": "disableChildren", "overwrite": path.resolve(__dirname, './plugins.json') }), pluginsApis = {}, mongodb = require('mongodb'), - countlyConfig = require('../frontend/express/config', 'dont-enclose'), - apiCountlyConfig = require('../api/config', 'dont-enclose'), + countlyConfig = require('../frontend/express/config'), + apiCountlyConfig = require('../api/config'), utils = require('../api/utils/utils.js'), fs = require('fs'), url = require('url'), @@ -1194,8 +1194,8 @@ var pluginManager = function pluginManager() { * Try to reload cached plugins json file **/ this.reloadPlugins = function() { - delete require.cache[require.resolve('./plugins.json', 'dont-enclose')]; - plugins = pluginDependencies.getFixedPluginList(require('./plugins.json', 'dont-enclose'), { + delete require.cache[require.resolve('./plugins.json')]; + plugins = pluginDependencies.getFixedPluginList(require('./plugins.json'), { "discoveryStrategy": "disableChildren", "overwrite": path.resolve(__dirname, './plugins.json') }); diff --git a/plugins/recaptcha/frontend/app.js b/plugins/recaptcha/frontend/app.js index 7041378d3bb..bde7588b985 100644 --- a/plugins/recaptcha/frontend/app.js +++ b/plugins/recaptcha/frontend/app.js @@ -1,5 +1,5 @@ var exportedPlugin = {}, - countlyConfig = require('../../../frontend/express/config', 'dont-enclose'), + countlyConfig = require('../../../frontend/express/config'), recaptcha = require('express-recaptcha'); var plugins = require("../../pluginManager.js"); diff --git a/plugins/reports/api/reports.js b/plugins/reports/api/reports.js index 7dd1890eb79..c8b7405fff5 100644 --- a/plugins/reports/api/reports.js +++ b/plugins/reports/api/reports.js @@ -15,7 +15,7 @@ var reportsInstance = {}, log = require('../../../api/utils/log')('reports:reports'), versionInfo = require('../../../frontend/express/version.info'), countlyConfig = require('../../../frontend/express/config.js'), - countlyApiConfig = require('./../../../api/config', 'dont-enclose'), + countlyApiConfig = require('./../../../api/config'), pdf = require('../../../api/utils/pdf'); countlyConfig.passwordSecret || ""; From 636db2e120898e0aa08aa6e342fa7134c89e0573 Mon Sep 17 00:00:00 2001 From: Kanwar Ujjaval Singh <4216199+kanwarujjaval@users.noreply.github.com> Date: Wed, 23 Apr 2025 19:12:15 +0530 Subject: [PATCH 10/12] temporary way of attaching clickhouse client --- plugins/pluginManager.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/pluginManager.js b/plugins/pluginManager.js index fd2aec96c77..60bca9b4a69 100644 --- a/plugins/pluginManager.js +++ b/plugins/pluginManager.js @@ -1843,6 +1843,11 @@ var pluginManager = function pluginManager() { const [dbCountly, dbOut, dbFs, dbDrill] = databases; let common = require('../api/utils/common'); + try { + // TODO: TEMPORARY, should be refactored once in its own lib + common.clickhouseClient = require('./drill/api/clickhouse-client'); + } + catch (e) { /*suppress*/ } common.db = dbCountly; common.outDb = dbOut; require('../api/utils/countlyFs').setHandler(dbFs); From 848939b56c02e06c2252b7eeab736ebe3e1db1a2 Mon Sep 17 00:00:00 2001 From: Kanwar Ujjaval Singh <4216199+kanwarujjaval@users.noreply.github.com> Date: Thu, 24 Apr 2025 20:08:51 +0530 Subject: [PATCH 11/12] minor change --- api/utils/common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/utils/common.js b/api/utils/common.js index ae8e0f91bfc..aade9f4626f 100644 --- a/api/utils/common.js +++ b/api/utils/common.js @@ -19,7 +19,7 @@ const crypto = require('crypto'); const logger = require('./log.js'); const mcc_mnc_list = require('mcc-mnc-list'); const plugins = require('../../plugins/pluginManager.js'); -const countlyConfig = require('./../config', 'dont-enclose'); +const countlyConfig = require('./../config'); const argon2 = require('argon2'); const mongodb = require('mongodb'); const getRandomValues = require('get-random-values'); From f1e7a1c98a9e5df33724c540f146116ae272cb7a Mon Sep 17 00:00:00 2001 From: Kanwar Ujjaval Singh <4216199+kanwarujjaval@users.noreply.github.com> Date: Thu, 29 May 2025 19:21:58 +0530 Subject: [PATCH 12/12] add clikchouse config --- api/config.sample.js | 59 +++++++++++++++++++++++++++++++++++++++++-- api/configextender.js | 7 +++++ api/utils/log.js | 28 ++++++++++---------- 3 files changed, 78 insertions(+), 16 deletions(-) diff --git a/api/config.sample.js b/api/config.sample.js index e881e72c607..0d7ef4e9d1a 100644 --- a/api/config.sample.js +++ b/api/config.sample.js @@ -5,6 +5,14 @@ /** @lends module:api/config */ var countlyConfig = { + /** + * Drill events database driver configuration + * @type {string} + * @property {string} [drill_events_driver=mongodb] - database driver to use for drill events storage + * Possible values are: "mongodb", "clickhouse" + */ + drill_events_driver: "clickhouse", + /** * MongoDB connection definition and options * @type {object} @@ -51,9 +59,56 @@ var countlyConfig = { }, */ /* or define as a url - //mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] - mongodb: "mongodb://localhost:27017/countly", + //mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] + mongodb: "mongodb://localhost:27017/countly", + */ + /** + * ClickHouse connection definition and options + * @type {object|string} + * @property {string} [url=http://localhost:8123] - ClickHouse server URL + * @property {string} [username=default] - username for authenticating user + * @property {string} [password=] - password for authenticating user + * @property {string} [database=countly_drill] - ClickHouse database name + * @property {object} [compression] - compression settings + * @property {string} [application] - application name for connection + * @property {number} [request_timeout=1200000] - request timeout in milliseconds + * @property {object} [keep_alive] - keep alive settings + * @property {number} [max_open_connections=10] - maximum number of open connections + * @property {object} [clickhouse_settings] - ClickHouse specific settings + */ + clickhouse: { + url: "http://localhost:8123", + username: "default", + password: "", + database: "countly_drill", + compression: { + request: false, + response: false, + }, + application: "", + request_timeout: 1200_000, + keep_alive: { + enabled: true, + idle_socket_ttl: 10000, + }, + max_open_connections: 10, + clickhouse_settings: { + idle_connection_timeout: 11000 + '', + async_insert: 1, + wait_for_async_insert: 1, + wait_end_of_query: 1, + optimize_on_insert: 1, + allow_suspicious_types_in_group_by: 1, + allow_suspicious_types_in_order_by: 1, + optimize_move_to_prewhere: 1, + query_plan_optimize_lazy_materialization: 1 + } + }, + /* or define as a url + //http://[username:password@]host[:port][/database] + clickhouse: "http://localhost:8123/countly_drill", */ + /** * Default API configuration * @type {object} diff --git a/api/configextender.js b/api/configextender.js index 670c736c24d..d5175c31438 100644 --- a/api/configextender.js +++ b/api/configextender.js @@ -30,6 +30,13 @@ const OVERRIDES = { SERVEROPTIONS: 'serverOptions' }, + CLICKHOUSE: { + REQUEST_TIMEOUT: 'request_timeout', + MAX_OPEN_CONNECTIONS: 'max_open_connections', + CLICKHOUSE_SETTINGS: 'clickhouse_settings', + KEEP_ALIVE: 'keep_alive' + }, + API: { MAX_SOCKETS: 'max_sockets', MAX_UPLOAD_FILE_SIZE: 'maxUploadFileSize' diff --git a/api/utils/log.js b/api/utils/log.js index ee2d89862ab..bbd6ca9f033 100644 --- a/api/utils/log.js +++ b/api/utils/log.js @@ -168,19 +168,19 @@ const logLevel = function(name) { * Build a transport config: pretty in dev, JSON in prod. * @returns {Object} Transport config */ -function getTransport() { - if (process.env.NODE_ENV === 'development') { - return { - target: 'pino-pretty', - options: { - colorize: true, - translateTime: 'yyyy-mm-dd HH:MM:ss.l', - ignore: 'pid,hostname' - } - }; - } - return undefined; -} +// function getTransport() { +// if (process.env.NODE_ENV === 'development') { +// return { +// target: 'pino-pretty', +// options: { +// colorize: true, +// translateTime: 'yyyy-mm-dd HH:MM:ss.l', +// ignore: 'pid,hostname' +// } +// }; +// } +// return undefined; +// } /** @@ -205,7 +205,7 @@ const createLogger = (name, level) => { }, sync: false, browser: false, - transport: getTransport() + // transport: getTransport() }); };