telemetry.ts file in Flyde codebase.
In this article, we will review telemetry.ts file in Flyde codebase. We will look at:
-
reportEvent().
-
sanitizeProperties().
-
isSafeProperty().
-
sanitizeValue().
reportEvent()
reportEvent function is exported in telemetry.ts file as shown below:
export function reportEvent(
distinctId: string,
event: string,
properties?: Record<string, any>
): void {
// Check if telemetry is disabled via environment variable
if (typeof process !== 'undefined' && process.env?.FLYDE_TELEMETRY_DISABLED === 'true') {
return;
}
// Disable in CI/CD and production environments
if (typeof process !== 'undefined' && process.env) {
const env = process.env;
// Disable in CI
if (env.CI === 'true') {
return;
}
// Disable in production
if (env.NODE_ENV === 'production') {
return;
}
}
// Fire and forget
(async () => {
try {
const sanitizedProperties = sanitizeProperties(properties);
const payload: TelemetryEvent = {
distinctId,
event,
properties: {
...sanitizedProperties,
flydeVersion: FLYDE_VERSION
}
};
fetch(TELEMETRY_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
} catch (error) {
// Silently fail - telemetry should not break the app
}
})();
}
This code snippet is self explanatory with helpful comments. What I find interesting is that “fire and forget” type of invocation. This is an IIFE.
Also notice that catch block is empty.
sanitizeProperties()
sanitizeProperties is defined as shown below:
function sanitizeProperties(properties?: Record<string, any>): Record<string, any> {
if (!properties) {
return {};
}
const sanitized: Record<string, any> = {};
for (const [key, value] of Object.entries(properties)) {
if (isSafeProperty(key, value)) {
sanitized[key] = sanitizeValue(value);
}
}
return sanitized;
}
This function iterates over the object keys and checks if it is a safe property and then sanitizes value.
Two questions come to mind.
-
What does safe here mean?
-
What does sanitize value here mean?
Continue reading.
isSafeProperty()
isSafeProperty function is defined as shown below:
function isSafeProperty(key: string, _value: any): boolean {
const sensitiveKeys = [
'token', 'password', 'secret', 'key', 'auth', 'credential',
'email', 'username', 'path', 'file', 'content', 'code'
];
const lowerKey = key.toLowerCase();
if (sensitiveKeys.some(sensitive => lowerKey.includes(sensitive))) {
return false;
}
return true;
}
Interesting usage of “some” here and this is based on sensitiveKeys array.
sanitizeValue()
sanitizeValue is defined as shown below:
function sanitizeValue(value: any): any {
if (typeof value === 'string' && value.length > 100) {
return '[Redacted]';
}
if (typeof value === 'object' && value !== null) {
return '[Object]';
}
return value;
}
sanitize here means sensitive info gets redacted and if the value is of type object, it returns [Object]
.
About me:
Hey, my name is Ramu Narasinga. I study codebase architecture in large open-source projects.
Email: ramu.narasinga@gmail.com
Want to learn from open-source? Solve challenges inspired by open-source projects.
References:
-
https://github.com/flydelabs/flyde/blob/main/core/src/telemetry.ts
-
https://github.com/search?q=repo%3Aflydelabs%2Fflyde+FLYDE_VERSION&type=code
-
https://github.com/search?q=repo%3Aflydelabs%2Fflyde+telemetry&type=code