Repository: dbt-labs/dbt-core

Issue:
[CT-3160] minimal snowplow tracker and snowplow python tracker are incompatible for the latest versions of the snowplow python tracker
_Originally posted by @akurdyukov in https://github.com/dbt-labs/dbt-core/issues/8409#issuecomment-1723683080_

I bumped into a issue with minimal showplow after installing `meltano` using this guide: https://dagster.io/blog/dagster-meltano-integration-tutorial

The guide is a little bit inaccurate because it does not say that you need to install `meltano` package into venv the dagster is running in. And after installing meltano (and doing nothing with the code) I ran into
```
Stack Trace:
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dagster/_grpc/server.py", line 295, in __init__
    self._loaded_repositories: Optional[LoadedRepositories] = LoadedRepositories(
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dagster/_grpc/server.py", line 139, in __init__
    loadable_targets = get_loadable_targets(
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dagster/_grpc/utils.py", line 47, in get_loadable_targets
    else loadable_targets_from_python_module(module_name, working_directory)
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dagster/_core/workspace/autodiscovery.py", line 35, in loadable_targets_from_python_module
    module = load_python_module(
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dagster/_core/code_pointer.py", line 135, in load_python_module
    return importlib.import_module(module_name)
  File "/opt/homebrew/Cellar/python@3.10/3.10.13/Frameworks/Python.framework/Versions/3.10/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/Users/alik/Development/dagster_analytics/dagster_analytics/definitions.py", line 4, in <module>
    from dagster_dbt import DbtCliResource
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dagster_dbt/__init__.py", line 2, in <module>
    from .asset_defs import (
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dagster_dbt/asset_defs.py", line 62, in <module>
    from dagster_dbt.core.resources import DbtCliClient
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dagster_dbt/core/__init__.py", line 5, in <module>
    from .resources_v2 import (
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dagster_dbt/core/resources_v2.py", line 35, in <module>
    from dbt.contracts.results import NodeStatus, TestStatus
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dbt/contracts/results.py", line 1, in <module>
    from dbt.contracts.graph.unparsed import FreshnessThreshold
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dbt/contracts/graph/unparsed.py", line 3, in <module>
    from dbt import deprecations
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dbt/deprecations.py", line 6, in <module>
    import dbt.tracking
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dbt/tracking.py", line 104, in <module>
    emitter = TimeoutEmitter()
  File "/Users/alik/Development/dagster-env-10/lib/python3.10/site-packages/dbt/tracking.py", line 54, in __init__
    super().__init__(
```

This happens because `meltano` depends on `snowplow-tracker [required: >=1.0.1,<2.0.0, installed: 1.0.1]`. And the contract for `snowplow_tracker.Emitter` does not match between `snowplow-tracker` and `minimal-snowplow-tracker`.


Discussion:

Resolving patch:
diff --git a/core/dbt/tracking.py b/core/dbt/tracking.py
--- a/core/dbt/tracking.py
+++ b/core/dbt/tracking.py
@@ -9,7 +9,9 @@
 import logbook
 import pytz
 import requests
+from packaging.version import Version
 from snowplow_tracker import Emitter, SelfDescribingJson, Subject, Tracker
+from snowplow_tracker import __version__ as snowplow_version  # type: ignore
 from snowplow_tracker import logger as sp_logger
 
 from dbt import version as dbt_version
@@ -49,17 +51,25 @@
 RUN_MODEL_SPEC = "iglu:com.dbt/run_model/jsonschema/1-0-3"
 PLUGIN_GET_NODES = "iglu:com.dbt/plugin_get_nodes/jsonschema/1-0-0"
 
+SNOWPLOW_TRACKER_VERSION = Version(snowplow_version)
+
+# workaround in case real snowplow tracker is in the env
+# the argument was renamed in https://github.com/snowplow/snowplow-python-tracker/commit/39fd50a3aff98a5efdd5c5c7fb5518fe4761305b
+INIT_KW_ARGS = (
+    {"buffer_size": 30} if SNOWPLOW_TRACKER_VERSION < Version("0.13.0") else {"batch_size": 30}
+)
+
 
 class TimeoutEmitter(Emitter):
     def __init__(self) -> None:
         super().__init__(
             COLLECTOR_URL,
             protocol=COLLECTOR_PROTOCOL,
-            buffer_size=30,
             on_failure=self.handle_failure,
             method="post",
             # don't set this.
             byte_limit=None,
+            **INIT_KW_ARGS,
         )
 
     @staticmethod
@@ -104,7 +114,7 @@ def http_get(self, payload):
 
 emitter = TimeoutEmitter()
 tracker = Tracker(
-    emitter,
+    emitters=emitter,
     namespace="cf",
     app_id="dbt",
 )


Test patch: