Skip to content

Commit

Permalink
Merge pull request #456 from flask-dashboard/fmd-telemetry-gh-pages-u…
Browse files Browse the repository at this point in the history
…pdate

Fmd telemetry gh pages update
  • Loading branch information
JohannesLC authored Apr 26, 2024
2 parents 4b016d2 + a1021e2 commit ee8fb59
Show file tree
Hide file tree
Showing 18 changed files with 122 additions and 175 deletions.
8 changes: 8 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
This project adheres to `Semantic Versioning <http://semver.org/>`_.
Please note that the changes before version 1.10.0 have not been documented.

v3.3.1
----------
Changed

- Telemetry now uses dynamic server-ip
- Removed survey
- FollowUp questions refactored

v3.3.0
----------
Changed
Expand Down
40 changes: 26 additions & 14 deletions docs/functionality.rst
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ Telemetry
The Dashboard is setup to be able to collect telemetric-data.
This data-collection can be toggled on and off under the "Configuration" route.

The collected data is released weekly at https://flask-dashboard.github.io/fmd-telemetry.

You can find detailed information about what and how data is collected below.

What:
Expand All @@ -356,7 +358,7 @@ What:

3. **Aggregated monitoring levels:** To determine the most frequently utilized monitoring level, we aggregate the levels set from each endpoint.

4. **Table size:** In order to determine how fast the data accumulates, we collect the size of the database and its tables.
4. **Version number:** In order to determine how often people update their dashboards, we collect the build number.

5. **Route visits:** Which routes you use in the dashboard.

Expand All @@ -368,19 +370,29 @@ This is most of the logic behind the telemetry:
.. code-block:: python
def post_to_back_if_telemetry_enabled(class_name='Endpoints', **kwargs):
"""
Function to send telemetry data to remote database
"""
if telemetry_config.telemetry_consent:
back4app_endpoint = f'https://parseapi.back4app.com/classes/{class_name}'
headers = telemetry_config.telemetry_headers
data = {'fmd_id': telemetry_config.fmd_user, 'session': telemetry_config.telemetry_session} # fmd_id is the random uuid of the user, session is amount of times app was initialized
for key, value in kwargs.items():
data[key] = value
requests.post(back4app_endpoint, json=data, headers=headers)
"""
Function to send data to server, with dynamic IP fetching.
If the IP cannot be fetched, the function will silently exit without sending data.
"""
if telemetry_config.telemetry_consent or class_name == 'FollowUp':
github_file_url = 'https://raw.githubusercontent.com/flask-dashboard/fmd-telemetry/master/ip_address'
parse_server_ip = fetch_ip_from_github(github_file_url)
if parse_server_ip is None:
return # Exit silently if no IP is fetched
parse_server_endpoint = f'http://{parse_server_ip}/parse/classes/{class_name}'
headers = telemetry_config.telemetry_headers
data = {'fmd_id': telemetry_config.fmd_user, 'session': telemetry_config.telemetry_session}
for key, value in kwargs.items():
data[key] = value
try:
response = requests.post(parse_server_endpoint, json=data, headers=headers, timeout=1)
return response
except requests.exceptions.ConnectionError as e:
return None
Need more information?
Expand Down
4 changes: 2 additions & 2 deletions flask_monitoringdashboard/constants.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "3.3.0",
"author": "Krzysztof Wielicki, Johannes Lind Christiansen",
"version": "3.3.1",
"author": "Johannes Lind Christiansen",
"email": "flask.monitoringdashboard@gmail.com"
}
5 changes: 2 additions & 3 deletions flask_monitoringdashboard/core/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def init_from(self, file=None, envvar=None, log_verbose=False):

class TelemetryConfig(object):
"""Configuration for the telemetry feature"""
# constants for defining survey and telemetry answers
# constants for defining telemetry answers
NOT_ANSWERED = 1
REJECTED = 2
ACCEPTED = 3
Expand All @@ -210,7 +210,6 @@ def __init__(self):
self.telemetry_consent = False
self.telemetry_session = 0
self.telemetry_headers = {
'X-Parse-Application-Id': '4nHPABwkHqOZzNrFduzNyKH8q7wmPFdOWvajfWU2',
'X-Parse-REST-API-Key': 'zjv0WLI2K3UvpfzrfG4sPA6EykYyzZM4KxQk07Hs',
'X-Parse-Application-Id': 'fmd-md',
'Content-Type': 'application/json'
}
53 changes: 43 additions & 10 deletions flask_monitoringdashboard/core/telemetry.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import datetime
import requests
import functools

from sqlalchemy import func
from sqlalchemy.exc import NoResultFound, MultipleResultsFound, SQLAlchemyError

from flask_monitoringdashboard import telemetry_config
from flask_monitoringdashboard.core.config import TelemetryConfig
from flask_monitoringdashboard.core.blueprints import get_blueprint
from flask_monitoringdashboard.core.utils import get_details
from flask_monitoringdashboard.database import TelemetryUser, Endpoint


Expand Down Expand Up @@ -49,13 +51,18 @@ def collect_general_telemetry_data(session, telemetry_user):
level_twos_count = counts_dict.get(2, 0)
level_threes_count = counts_dict.get(3, 0)

# Get details including the dashboard version
details = get_details(session)
dashboard_version = details['dashboard-version']

data = {'endpoints': no_of_endpoints,
'blueprints': no_of_blueprints,
'time_initialized': telemetry_user.last_initialized.strftime('%Y-%m-%d %H:%M:%S'),
'monitoring_0': level_zeros_count,
'monitoring_1': level_ones_count,
'monitoring_2': level_twos_count,
'monitoring_3': level_threes_count,
'dashboard_version': dashboard_version,
}

# post user data
Expand All @@ -78,13 +85,10 @@ def initialize_telemetry_session(session):
telemetry_user.last_initialized = datetime.datetime.utcnow()
session.commit()

# reset telemetry and survey prompt if declined in previous session
# reset telemetry if declined in previous session
if telemetry_user.monitoring_consent == TelemetryConfig.REJECTED:
telemetry_user.monitoring_consent = TelemetryConfig.NOT_ANSWERED
session.commit()
if telemetry_user.survey_filled == TelemetryConfig.REJECTED:
telemetry_user.survey_filled = TelemetryConfig.NOT_ANSWERED
session.commit()

# check if telemetry's been agreed on
telemetry_config.telemetry_consent = True if telemetry_user.monitoring_consent == TelemetryConfig.ACCEPTED else False
Expand All @@ -107,17 +111,46 @@ def initialize_telemetry_session(session):
session.rollback()


def post_to_back_if_telemetry_enabled(class_name='Endpoints', **kwargs):
@functools.cache
def fetch_ip_from_github(file_url):
"""
Function to send telemetry data to remote database
Fetches the IP address from a text file hosted on GitHub and caches the result.
Args:
file_url (str): URL to the raw version of the GitHub hosted text file containing the IP address.
Returns:
str: IP address and port as a string, or None if unable to fetch.
"""
if telemetry_config.telemetry_consent:
back4app_endpoint = f'https://parseapi.back4app.com/classes/{class_name}'
try:
response = requests.get(file_url)
response.raise_for_status() # Raises an HTTPError for bad responses
return response.text.strip() # Assuming the file contains the IP address and port in the format "IP:PORT"
except requests.RequestException:
return None


def post_to_back_if_telemetry_enabled(class_name='Endpoints', **kwargs):
"""
Function to send data to server, with dynamic IP fetching.
If the IP cannot be fetched, the function will silently exit without sending data.
"""
if telemetry_config.telemetry_consent or class_name == 'FollowUp':
github_file_url = 'https://raw.githubusercontent.com/flask-dashboard/fmd-telemetry/master/ip_address'
parse_server_ip = fetch_ip_from_github(github_file_url)
if parse_server_ip is None:
return # Exit silently if no IP is fetched

parse_server_endpoint = f'http://{parse_server_ip}/parse/classes/{class_name}'
headers = telemetry_config.telemetry_headers
data = {'fmd_id': telemetry_config.fmd_user, 'session': telemetry_config.telemetry_session}

for key, value in kwargs.items():
data[key] = value

requests.post(back4app_endpoint, json=data, headers=headers)
try:
response = requests.post(parse_server_endpoint, json=data, headers=headers, timeout=1)
return response
except requests.exceptions.ConnectionError as e:
return None


2 changes: 2 additions & 0 deletions flask_monitoringdashboard/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
get_date_of_first_request,
get_date_of_first_request_version,
)
from flask_monitoringdashboard import telemetry_config


def get_endpoint_details(session, endpoint_id):
Expand Down Expand Up @@ -57,6 +58,7 @@ def get_details(session):
'first-request': get_date_of_first_request(session),
'first-request-version': get_date_of_first_request_version(session, config.version),
'total-requests': count_total_requests(session),
'fmd-id': telemetry_config.fmd_user,
}


Expand Down
3 changes: 0 additions & 3 deletions flask_monitoringdashboard/database/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ class TelemetryUser(Base):
last_initialized = Column(DateTime, default=datetime.datetime.utcnow)
"""Check when was the last time user accessed FMD"""

survey_filled = Column(Integer, default=1)
"""If user filled the survey 1 - not responded 2 - declined 3 - filled"""

monitoring_consent = Column(Integer, default=1)
"""If user agrees to share data 1 - not responded 2 - declined 3 - accepted"""

Expand Down
5 changes: 0 additions & 5 deletions flask_monitoringdashboard/frontend/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import { DatabaseManagementController } from './controllers/databaseManagementCo
import { EndpointVersionIPController } from './controllers/endpointVersionIP';
import { EndpointVersionController } from "./controllers/endpointVersion";
import { MonitorLevelController } from "./controllers/monitorLevel";
import { SurveyController } from "./controllers/surveyController";
import { TelemetryController } from "./controllers/telemetryController";


Expand Down Expand Up @@ -85,10 +84,6 @@ app.controller('EndpointController', ['$scope', 'endpointService', EndpointContr
app.controller('PaginationController', ['$scope', 'paginationService', PaginationController]);
app.controller('ModalController', ['$scope', '$window', '$browser', 'modalService', ModalController]);

app.component('surveyComponent', {
templateUrl: 'static/pages/survey.html',
controller: SurveyController
});
app.component('telemetryComponent', {
templateUrl: 'static/pages/telemetry.html',
controller: TelemetryController
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -41,34 +41,22 @@ export function TelemetryController($scope, $http, $window) {
};
$scope.customReason = '';

// Configuration for HTTP requests to Back4App
var config = {
headers: {
'X-Parse-Application-Id': '4nHPABwkHqOZzNrFduzNyKH8q7wmPFdOWvajfWU2',
'X-Parse-REST-API-Key': 'zjv0WLI2K3UvpfzrfG4sPA6EykYyzZM4KxQk07Hs',
'Content-Type': 'application/json'
}
};

// Function to submit follow-up feedback
$scope.submitFollowUp = function () {
$scope.followUpShow = false;

var feedback = [];
for (var key in $scope.reasons) {
if ($scope.reasons[key]) {
if (key === 'other') {
feedback.push(key);
if ($scope.customReason.trim() !== '') {
feedback.push({ other: $scope.customReason });
}
if (key === 'other' && $scope.customReason.trim() !== '') {
feedback.push({ key: 'other', other_reason: $scope.customReason });
} else {
feedback.push(key);
feedback.push({ key: key });
}
}
}

$http.post('https://parseapi.back4app.com/classes/FollowUp', { reasons: feedback }, config)
$http.post('/dashboard/telemetry/submit_follow_up', { feedback: feedback })
.then(function (response) {
}, function (error) {
console.error('Error sending feedback:', error);
Expand Down
14 changes: 0 additions & 14 deletions flask_monitoringdashboard/static/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -1360,7 +1360,6 @@ progress {
margin-top: calc(-1 * var(--bs-gutter-y));
margin-right: calc(-0.5 * var(--bs-gutter-x));
margin-left: calc(-0.5 * var(--bs-gutter-x));
overflow: auto;
}
.row > * {
flex-shrink: 0;
Expand Down Expand Up @@ -4315,13 +4314,6 @@ textarea.form-control-lg {
list-style: none;
}

.navbar-btn {
display: none;
position: absolute;
right: 11px;
top: 13px;
}

.nav-link {
display: block;
padding: var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);
Expand Down Expand Up @@ -6193,12 +6185,6 @@ textarea.form-control-lg {
}
}
@media (max-width: 991.98px) {


.navbar-btn {
display: block !important;
}

.modal-fullscreen-lg-down {
width: 100vw;
max-width: none;
Expand Down
15 changes: 2 additions & 13 deletions flask_monitoringdashboard/static/js/app.js

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions flask_monitoringdashboard/static/pages/configuration.html
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@ <h4>Deployment details</h4>
<td><b>Total amount of monitored requests</b></td>
<td>{{ details['total-requests'] | number }}</td>
</tr>

<tr>
<td><b>fmd_id</b></td>
<td>{{ details['fmd-id'] }}</td>
</tr>
</table>
</div>
</div>
Expand Down
Loading

0 comments on commit ee8fb59

Please sign in to comment.