Repository: meltano/meltano

Issue:
[Feature]: Collect telemetry data about how `send_anonymous_usage_stats` was configured
The project context (and its schema) should be updated to include the key `send_anonymous_usage_stats_source` with the value `ProjectSettingService.get_with_metadata('send_anonymous_usage_stats')[1]['source'].value`, which can be one of the following strings:
- `auto`
- `config_override`
- `db`
- `default`
- `dotenv`
- `env`
- `inherited`
- `meltano_env`
- `meltano_yml`

CC @pnadolny13 @aaronsteers 


Discussion:
@WillDaSilva thanks for opening this. I agree that this would be useful to have.

For others reading this, the context is that we dont know where the setting comes from so sometimes we see projects toggling between opting out and opting in. We were chatting about how that could be due to different configurations in local vs production environments i.e. locally telemetry is on but in prod things are strict and its off.

From my view I dont think this is necessarily a high priority but it would be nice to know.

Resolving patch:
diff --git a/src/meltano/core/tracking/contexts/project.py b/src/meltano/core/tracking/contexts/project.py
--- a/src/meltano/core/tracking/contexts/project.py
+++ b/src/meltano/core/tracking/contexts/project.py
@@ -42,9 +42,10 @@ def __init__(self, project: Project, client_id: uuid.UUID):
         """
         self.project = project
         self.settings_service = ProjectSettingsService(project)
-        self.send_anonymous_usage_stats = self.settings_service.get(
-            "send_anonymous_usage_stats", True
-        )
+        (
+            send_anonymous_usage_stats,
+            send_anonymous_usage_stats_metadata,
+        ) = self.settings_service.get_with_metadata("send_anonymous_usage_stats")
 
         super().__init__(
             ProjectContextSchema.url,
@@ -58,6 +59,10 @@ def __init__(self, project: Project, client_id: uuid.UUID):
                     if self.project.active_environment
                     else None
                 ),
+                "send_anonymous_usage_stats": send_anonymous_usage_stats,
+                "send_anonymous_usage_stats_source": (
+                    send_anonymous_usage_stats_metadata["source"].value
+                ),
             },
         )
 
diff --git a/src/meltano/core/tracking/schemas.py b/src/meltano/core/tracking/schemas.py
--- a/src/meltano/core/tracking/schemas.py
+++ b/src/meltano/core/tracking/schemas.py
@@ -32,5 +32,5 @@ def url(self) -> str:
 ExceptionContextSchema = IgluSchema("exception_context", "1-0-0")
 ExitEventSchema = IgluSchema("exit_event", "1-0-0")
 PluginsContextSchema = IgluSchema("plugins_context", "1-0-0")
-ProjectContextSchema = IgluSchema("project_context", "1-0-0")
+ProjectContextSchema = IgluSchema("project_context", "1-1-0")
 TelemetryStateChangeEventSchema = IgluSchema("telemetry_state_change_event", "1-0-0")


Test patch:
diff --git a/tests/meltano/core/tracking/test_tracker.py b/tests/meltano/core/tracking/test_tracker.py
--- a/tests/meltano/core/tracking/test_tracker.py
+++ b/tests/meltano/core/tracking/test_tracker.py
@@ -402,3 +402,24 @@ def emitter_failure_callback(_, failure_events: list):
         server_thread.join()
 
         assert timeout_occured is timeout_should_occur
+
+    def test_project_context_send_anonymous_usage_stats_source(self, project: Project):
+        clear_telemetry_settings(project)
+
+        settings_service = ProjectSettingsService(project)
+
+        def get_source():
+            return ProjectContext(project, uuid.uuid4()).to_json()["data"][
+                "send_anonymous_usage_stats_source"
+            ]
+
+        assert get_source() == "default"
+
+        settings_service.set(
+            "send_anonymous_usage_stats",
+            not settings_service.get("send_anonymous_usage_stats"),
+        )
+        assert get_source() == "meltano_yml"
+
+        os.environ["MELTANO_SEND_ANONYMOUS_USAGE_STATS"] = "True"
+        assert get_source() == "env"