Repository: ydataai/ydata-profiling

Issue:
Feature Request | Telemetry
### Missing functionality

Better understanding how ydata-profiling is being used is key to prioritize and drive product innovation.
There are many questions we can answer now that could help a lot making the product better:
 - Which versions of ydata-profiling are people installing/using now (i.e. whether people have primarily made the jump from version X to version Y)
- Which Python version / environment is used, among other env specs?
- What features are the most used and wanted?
- Approximately how many people out there in the world are installing ydata-profiling?
- Is ydata-profiling being used for ad-hoc developments or part of CI/CD pipelines?
- and many more.

### Proposed feature

My proposal is to use Scarf.sh.
The following case studies are worth reading:

1. https://about.scarf.sh/post/scarf-case-study-apache-superset
2. https://about.scarf.sh/post/haskell-org-bridging-the-gap-between-language-innovation-and-community-understanding

Similar to them, this could help in various ways that come with using data for decision-making. With clear guidelines on "how to opt-out" & "what data is being collected", this can be beneficial to the entire community as we would be making more informed decisions.

### Alternatives considered

It's possible to find other tools for telemetry, but this one seems to check all the boxes.

### Additional context

The ASF already approves Scarf and is already used by other ASF projects, namely Superset, Dolphin Scheduler, Dubbo Kubernetes, DevLake, Skywalking as it follows GDPR and other regulations.


Discussion:

Resolving patch:
diff --git a/src/ydata_profiling/utils/common.py b/src/ydata_profiling/utils/common.py
--- a/src/ydata_profiling/utils/common.py
+++ b/src/ydata_profiling/utils/common.py
@@ -1,5 +1,8 @@
 """Common util functions (e.g. missing in Python)."""
 import collections.abc
+import os
+import platform
+import subprocess
 import zipfile
 from datetime import datetime, timedelta
 
@@ -8,6 +11,10 @@
 from pathlib import Path
 from typing import Mapping
 
+import requests
+
+from ydata_profiling.version import __version__
+
 
 def update(d: dict, u: Mapping) -> dict:
     """Recursively update a dict.
@@ -88,3 +95,32 @@ def convert_timestamp_to_datetime(timestamp: int) -> datetime:
         return datetime.fromtimestamp(timestamp)
     else:
         return datetime(1970, 1, 1) + timedelta(seconds=int(timestamp))
+
+
+def analytics_features(dataframe, datatype: bool, report_type: bool):
+    endpoint = "https://packages.ydata.ai/ydata-profiling?"
+
+    if os.getenv("YDATA_PROFILING_NO_ANALYTICS") != True:
+        package_version = __version__
+        try:
+            subprocess.check_output("nvidia-smi")
+            gpu_present = True
+        except Exception:
+            gpu_present = False
+
+        python_version = ".".join(platform.python_version().split(".")[:2])
+
+        try:
+            request_message = (
+                f"{endpoint}version={package_version}"
+                f"&python_version={python_version}"
+                f"&report_type={report_type}"
+                f"&dataframe={dataframe}"
+                f"&datatype={datatype}"
+                f"&os={platform.system()}"
+                f"&gpu={str(gpu_present)}"
+            )
+
+            requests.get(request_message)
+        except Exception:
+            pass
diff --git a/src/ydata_profiling/utils/logger.py b/src/ydata_profiling/utils/logger.py
new file mode 100644
--- /dev/null
+++ b/src/ydata_profiling/utils/logger.py
@@ -0,0 +1,42 @@
+"""
+    Logger function for ydata-profiling reports
+"""
+
+import logging
+
+import pandas as pd
+
+from ydata_profiling.utils.common import analytics_features
+
+
+class ProfilingLogger(logging.Logger):
+    def __init__(self, name, level=logging.INFO):
+        super().__init__(name, level)
+
+    def info(
+        self,
+        msg: object,
+    ) -> None:
+        super().info(f"[PROFILING] - {msg}.")
+
+    def info_def_report(self, dataframe, timeseries: bool):
+        if dataframe == pd.DataFrame:
+            dataframe = "pandas"
+            report_type = "regular"
+        elif dataframe == type(None):
+            dataframe = "pandas"
+            report_type = "compare"
+        else:
+            dataframe = "spark"
+            report_type = "regular"
+
+        datatype = "timeseries" if timeseries else "tabular"
+
+        analytics_features(
+            dataframe=dataframe, datatype=datatype, report_type=report_type
+        )
+
+        super().info(
+            f"[PROFILING] Calculating profile with the following characteristics "
+            f"- {dataframe} | {datatype} | {report_type}."
+        )


Test patch: