Skip to content

Commit

Permalink
Merge pull request #563 from SquirrelCorporation/feat-telemetry
Browse files Browse the repository at this point in the history
[FEAT] Add telemetry support for anonymized usage tracking
  • Loading branch information
SquirrelDeveloper authored Dec 12, 2024
2 parents 226ecbe + 31d3ea6 commit 087ac8a
Show file tree
Hide file tree
Showing 15 changed files with 132 additions and 15 deletions.
12 changes: 7 additions & 5 deletions .env
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#SECRETS
# SECRETS
SECRET=REPLACE_ME
SALT=1234567890123456
VAULT_PWD=REPLACE_ME
#MONGO
# MONGO
DB_HOST=mongo
DB_NAME=ssm
DB_PORT=27017
#REDIS
# REDIS
REDIS_HOST=redis
REDIS_PORT=6379
#SSM CONFIG
# SSM CONFIG
#SSM_INSTALL_PATH=/opt/squirrelserversmanager
#SSM_DATA_PATH=/data
#SSM_DATA_PATH=/data
# TELEMETRY
TELEMETRY_ENABLED=true
10 changes: 6 additions & 4 deletions .env.dev
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#SECRETS
# SECRETS
SECRET=REPLACE_ME
SALT=1234567890123456
VAULT_PWD=REPLACE_ME
#MONGO
# MONGO
DB_HOST=mongo
DB_NAME=ssm
DB_PORT=27017
#REDIS
REDIS_HOST=redis
REDIS_PORT=6379
#SSM CONFIG
# SSM CONFIG
#SSM_INSTALL_PATH=/opt/squirrelserversmanager
#SSM_DATA_PATH=/data
#SSM_DATA_PATH=/data
# TELEMETRY
TELEMETRY_ENABLED=true
10 changes: 10 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ See [Troubleshoot](https://squirrelserversmanager.io/docs/technical-guide/troubl
![Device Info](./site/public/home/device-info.png)
![New Device](./site/public/home/new-device.png)

---
## Disabling Anonymized Telemetry

By default, SSM automatically reports anonymized basic usage statistics. This helps us understand how SSM is used and track its overall usage and growth. This data does not include any sensitive information. To disable anonymized telemetry, follow these steps:

Set `TELEMETRY_ENABLED` to `false` in your `.env` file.

---

**Note:**
Expand Down
26 changes: 23 additions & 3 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@
"socket.io": "^4.8.1",
"multer": "^1.4.5-lts.1",
"js-yaml": "^4.1.0",
"passport-mock-strategy": "^2.0.0"
"passport-mock-strategy": "^2.0.0",
"posthog-node": "^4.3.2"
},
"overrides": {
"minimatch": "5.1.2",
Expand Down
1 change: 1 addition & 0 deletions server/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export const VAULT_PWD = process.env.VAULT_PWD || '';
export const SESSION_DURATION = parseInt(process.env.SESSION_DURATION || '86400000');
export const SSM_INSTALL_PATH = process.env.SSM_INSTALL_PATH || '/opt/squirrelserversmanager';
export const SSM_DATA_PATH = process.env.SSM_DATA_PATH || '/data';
export const TELEMETRY_ENABLED = process.env.TELEMETRY_ENABLED === 'true';
2 changes: 2 additions & 0 deletions server/src/controllers/rest/user/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { SECRET, SESSION_DURATION } from '../../../config';
import UserRepo from '../../../data/database/repository/UserRepo';
import { AuthFailureError } from '../../../middlewares/api/ApiError';
import { SuccessResponse } from '../../../middlewares/api/ApiResponse';
import Telemetry from '../../../modules/telemetry';

export const login = async (req, res, next) => {
const { password, username } = req.body;
Telemetry.capture('user login');
if (!password || !username) {
res.status(401).send({
data: {
Expand Down
2 changes: 2 additions & 0 deletions server/src/controllers/rest/user/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import logger from '../../../logger';
import { AuthFailureError } from '../../../middlewares/api/ApiError';
import { SuccessResponse } from '../../../middlewares/api/ApiResponse';
import { createADefaultLocalUserRepository } from '../../../modules/repository/default-playbooks-repositories';
import Telemetry from '../../../modules/telemetry';
import DashboardUseCase from '../../../services/DashboardUseCase';
import DeviceUseCases from '../../../services/DeviceUseCases';

Expand Down Expand Up @@ -99,6 +100,7 @@ export const getCurrentUser = async (req, res) => {

export const createFirstUser = async (req, res) => {
const { email, password, name, avatar } = req.body;
Telemetry.capture('user signed up');
const hasUser = (await UserRepo.count()) > 0;
if (hasUser) {
throw new AuthFailureError('Your instance already has a user, you must first connect');
Expand Down
12 changes: 12 additions & 0 deletions server/src/core/startup/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import ContainerCustomStacksRepositoryEngine from '../../modules/repository/Cont
import { createADefaultLocalUserRepository } from '../../modules/repository/default-playbooks-repositories';
import PlaybooksRepositoryEngine from '../../modules/repository/PlaybooksRepositoryEngine';
import sshPrivateKeyFileManager from '../../modules/shell/managers/SshPrivateKeyFileManager';
import Telemetry from '../../modules/telemetry';
import UpdateChecker from '../../modules/update/UpdateChecker';
import ContainerRegistryUseCases from '../../services/ContainerRegistryUseCases';
import { setAnsibleVersions } from '../system/ansible-versions';
Expand Down Expand Up @@ -51,10 +52,21 @@ class Startup {
void AutomationEngine.init();
void UpdateChecker.checkVersion();
void ContainerCustomStacksRepositoryEngine.init();
void Telemetry.init();
}

private async updateScheme() {
this.logger.warn('updateScheme - Scheme version differed, starting applying updates...');

try {
const installId = await getFromCache(SettingsKeys.GeneralSettingsKeys.INSTALL_ID);
if (!installId) {
await setToCache(SettingsKeys.GeneralSettingsKeys.INSTALL_ID, uuidv4());
}
} catch (error: any) {
this.logger.error(`Error settings installId: ${error.message}`);
}

try {
await PlaybookModel.syncIndexes();
this.logger.info('PlaybookModel indexes synchronized successfully.');
Expand Down
4 changes: 4 additions & 0 deletions server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Startup from './core/startup';
import './middlewares/Passport';
import Crons from './modules/crons';
import app from './App';
import Telemetry from './modules/telemetry';

const start = () => {
logger.info(`
Expand Down Expand Up @@ -34,6 +35,9 @@ export const restart = async () => {
app.stopServer(start);
};

process.on('SIGINT', Telemetry.shutdown);
process.on('SIGTERM', Telemetry.shutdown);

/*process.on('uncaughtException', (err, origin) => {
console.error('Unhandled exception. Please handle!', err.stack || err);
console.error(`Origin: ${JSON.stringify(origin)}`);
Expand Down
42 changes: 42 additions & 0 deletions server/src/modules/telemetry/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { PostHog } from 'posthog-node';
import { SettingsKeys } from 'ssm-shared-lib';
import { TELEMETRY_ENABLED } from '../../config';
import { getFromCache } from '../../data/cache';
import logger from '../../logger';

class Telemetry {
private client;
private _id!: string;

constructor() {
this.client = new PostHog('phc_wJKUU2ssGzXxFferOrilvhErmTxvx8jZCf77PCW24JG', {
host: 'https://us.i.posthog.com',
});
}

public capture(eventName: string) {
if (TELEMETRY_ENABLED) {
this.client?.capture({ distinctId: this._id, event: eventName });
}
}

public async init() {
const installId = await getFromCache(SettingsKeys.GeneralSettingsKeys.INSTALL_ID);
if (!installId) {
logger.error('Install ID not found');
}
if (installId) {
this._id = installId;
this.client?.identify({ distinctId: this._id });
}
if (!TELEMETRY_ENABLED) {
await this.client?.optOut();
}
}

public async shutdown() {
await this.client?.shutdown();
}
}

export default new Telemetry();
3 changes: 2 additions & 1 deletion shared-lib/src/enums/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ export enum GeneralSettingsKeys {
DEVICE_STATS_RETENTION_IN_DAYS = 'device-stats-retention-in-days',
CONTAINER_STATS_RETENTION_IN_DAYS = 'container-stats-retention-in-days',
UPDATE_AVAILABLE = 'update-available',
INSTALL_ID = 'install-id',
}

export enum DefaultValue {
SCHEME_VERSION = '17',
SCHEME_VERSION = '18',
SERVER_LOG_RETENTION_IN_DAYS = '30',
CONSIDER_DEVICE_OFFLINE_AFTER_IN_MINUTES = '3',
CONSIDER_PERFORMANCE_GOOD_MEM_IF_GREATER = '10',
Expand Down
2 changes: 2 additions & 0 deletions site/docs/install/dockerless.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ REDIS_PORT=6379
# SSM CONFIG
SSM_INSTALL_PATH=/opt/squirrelserversmanager
SSM_DATA_PATH=/opt/squirrelserversmanager/data
# TELEMETRY
TELEMETRY_ENABLED=true
EOF
```

Expand Down
11 changes: 10 additions & 1 deletion site/docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ DB_PORT=27017
#REDIS
REDIS_HOST=redis
REDIS_PORT=6379
#TELEMETRY
TELEMETRY_ENABLED=true
```
Replace the values of "SECRET", "SALT", and "VAULT_PWD"

Expand All @@ -125,4 +127,11 @@ docker compose up
---

### Other install methods:
To manually build the project your self, see this [section](/docs/technical-guide/manual-install-ssm)
To manually build the project your self, see this [section](/docs/technical-guide/manual-install-ssm)

---
### Disabling Anonymized Telemetry

By default, SSM automatically reports anonymized basic usage statistics. This helps us understand how SSM is used and track its overall usage and growth. This data does not include any sensitive information. To disable anonymized telemetry, follow these steps:

Set `TELEMETRY_ENABLED` to `false` in your `.env` file.

0 comments on commit 087ac8a

Please sign in to comment.