We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
dbt sometimes writes a `.user.yml` and ignores configs
## Issue
If you pass dbt a relative path to `--profiles-dir` or the `DBT_PROFILES_DIR` environment variable and execute from a subdirectory, dbt will look for the user cookie and profiles.yml in different places (the latter correct, the former incorrect).

### Results
What happened? What did you expect to happen?
I got a `./profiles/.user.yml` and my settings were ignored. I expected my settings to be respected or to receive an error, and to not have a new file.

Suggested fixes:
My preference: don't allow users to run dbt from subdirectories.
Other option: defer loading of the user config until after we've found `dbt_project.yml`.

### System information
The output of `dbt --version`:
```
0.14.0
```

The operating system you're running on:
Any

The python version you're using (probably the output of `python --version`)
Any

### Steps to reproduce
In as much detail as possible, please provide steps to reproduce the issue. Sample data that triggers the issue, example models, etc are all very helpful here.

1) Make a dbt project in `${project_root}`
2) put your profiles.yml in  `${project_root}/profiles`
3) Make a subdirectory (`${project_root}/models`) and cd into it
4) Run dbt with the relative path to the profiles directory as an argument to `--profiles-dir`: `dbt run --profiles-dir profiles`
5) You will now have a `${project_root}/models/profiles/.user.yml` with cookie information. Also, any settings in your `profiles.yml` won't be respected.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `core/dbt/tracking.py`
Content:
```
1 from dbt.logger import GLOBAL_LOGGER as logger
2 from dbt import version as dbt_version
3 from snowplow_tracker import Subject, Tracker, Emitter, logger as sp_logger
4 from snowplow_tracker import SelfDescribingJson
5 from datetime import datetime
6 
7 from dbt.adapters.factory import get_adapter
8 
9 import pytz
10 import platform
11 import uuid
12 import requests
13 import yaml
14 import os
15 
16 import dbt.clients.system
17 
18 sp_logger.setLevel(100)
19 
20 COLLECTOR_URL = "fishtownanalytics.sinter-collect.com"
21 COLLECTOR_PROTOCOL = "https"
22 
23 INVOCATION_SPEC = 'iglu:com.dbt/invocation/jsonschema/1-0-1'
24 PLATFORM_SPEC = 'iglu:com.dbt/platform/jsonschema/1-0-0'
25 RUN_MODEL_SPEC = 'iglu:com.dbt/run_model/jsonschema/1-0-1'
26 INVOCATION_ENV_SPEC = 'iglu:com.dbt/invocation_env/jsonschema/1-0-0'
27 PACKAGE_INSTALL_SPEC = 'iglu:com.dbt/package_install/jsonschema/1-0-0'
28 RPC_REQUEST_SPEC = 'iglu:com.dbt/rpc_request/jsonschema/1-0-1'
29 
30 DBT_INVOCATION_ENV = 'DBT_INVOCATION_ENV'
31 
32 
33 class TimeoutEmitter(Emitter):
34     def __init__(self):
35         super(TimeoutEmitter, self).__init__(COLLECTOR_URL,
36                                              protocol=COLLECTOR_PROTOCOL,
37                                              buffer_size=1,
38                                              on_failure=self.handle_failure)
39 
40     @staticmethod
41     def handle_failure(num_ok, unsent):
42         # num_ok will always be 0, unsent will always be 1 entry long, because
43         # the buffer is length 1, so not much to talk about
44         logger.warning('Error sending message, disabling tracking')
45         do_not_track()
46 
47     def http_get(self, payload):
48         sp_logger.info("Sending GET request to %s..." % self.endpoint)
49         sp_logger.debug("Payload: %s" % payload)
50         r = requests.get(self.endpoint, params=payload, timeout=5.0)
51 
52         msg = "GET request finished with status code: " + str(r.status_code)
53         if self.is_good_status_code(r.status_code):
54             sp_logger.info(msg)
55         else:
56             sp_logger.warn(msg)
57         return r
58 
59 
60 emitter = TimeoutEmitter()
61 tracker = Tracker(emitter, namespace="cf", app_id="dbt")
62 
63 active_user = None
64 
65 
66 class User(object):
67 
68     def __init__(self, cookie_dir):
69         self.do_not_track = True
70         self.cookie_dir = cookie_dir
71 
72         self.id = None
73         self.invocation_id = str(uuid.uuid4())
74         self.run_started_at = datetime.now(tz=pytz.utc)
75 
76     def state(self):
77         return "do not track" if self.do_not_track else "tracking"
78 
79     @property
80     def cookie_path(self):
81         return os.path.join(self.cookie_dir, '.user.yml')
82 
83     def initialize(self):
84         self.do_not_track = False
85 
86         cookie = self.get_cookie()
87         self.id = cookie.get('id')
88 
89         subject = Subject()
90         subject.set_user_id(self.id)
91         tracker.set_subject(subject)
92 
93     def set_cookie(self):
94         user = {"id": str(uuid.uuid4())}
95 
96         dbt.clients.system.make_directory(self.cookie_dir)
97 
98         with open(self.cookie_path, "w") as fh:
99             yaml.dump(user, fh)
100 
101         return user
102 
103     def get_cookie(self):
104         if not os.path.isfile(self.cookie_path):
105             user = self.set_cookie()
106         else:
107             with open(self.cookie_path, "r") as fh:
108                 try:
109                     user = yaml.safe_load(fh)
110                     if user is None:
111                         user = self.set_cookie()
112                 except yaml.reader.ReaderError:
113                     user = self.set_cookie()
114         return user
115 
116 
117 def get_run_type(args):
118     return 'regular'
119 
120 
121 def get_invocation_context(user, config, args):
122     try:
123         adapter_type = get_adapter(config).type()
124     except Exception:
125         adapter_type = None
126 
127     return {
128         "project_id": None if config is None else config.hashed_name(),
129         "user_id": user.id,
130         "invocation_id": user.invocation_id,
131 
132         "command": args.which,
133         "options": None,
134         "version": str(dbt_version.installed),
135 
136         "run_type": get_run_type(args),
137         "adapter_type": adapter_type,
138     }
139 
140 
141 def get_invocation_start_context(user, config, args):
142     data = get_invocation_context(user, config, args)
143 
144     start_data = {
145         "progress": "start",
146         "result_type": None,
147         "result": None
148     }
149 
150     data.update(start_data)
151     return SelfDescribingJson(INVOCATION_SPEC, data)
152 
153 
154 def get_invocation_end_context(user, config, args, result_type):
155     data = get_invocation_context(user, config, args)
156 
157     start_data = {
158         "progress": "end",
159         "result_type": result_type,
160         "result": None
161     }
162 
163     data.update(start_data)
164     return SelfDescribingJson(INVOCATION_SPEC, data)
165 
166 
167 def get_invocation_invalid_context(user, config, args, result_type):
168     data = get_invocation_context(user, config, args)
169 
170     start_data = {
171         "progress": "invalid",
172         "result_type": result_type,
173         "result": None
174     }
175 
176     data.update(start_data)
177     return SelfDescribingJson(INVOCATION_SPEC, data)
178 
179 
180 def get_platform_context():
181     data = {
182         "platform": platform.platform(),
183         "python": platform.python_version(),
184         "python_version": platform.python_implementation(),
185     }
186 
187     return SelfDescribingJson(PLATFORM_SPEC, data)
188 
189 
190 def get_dbt_env_context():
191     default = 'manual'
192 
193     dbt_invocation_env = os.getenv(DBT_INVOCATION_ENV, default)
194     if dbt_invocation_env == '':
195         dbt_invocation_env = default
196 
197     data = {
198         "environment": dbt_invocation_env,
199     }
200 
201     return SelfDescribingJson(INVOCATION_ENV_SPEC, data)
202 
203 
204 def track(user, *args, **kwargs):
205     if user.do_not_track:
206         return
207     else:
208         logger.debug("Sending event: {}".format(kwargs))
209         try:
210             tracker.track_struct_event(*args, **kwargs)
211         except Exception:
212             logger.debug(
213                 "An error was encountered while trying to send an event"
214             )
215 
216 
217 def track_invocation_start(config=None, args=None):
218     context = [
219         get_invocation_start_context(active_user, config, args),
220         get_platform_context(),
221         get_dbt_env_context()
222     ]
223 
224     track(
225         active_user,
226         category="dbt",
227         action='invocation',
228         label='start',
229         context=context
230     )
231 
232 
233 def track_model_run(options):
234     context = [SelfDescribingJson(RUN_MODEL_SPEC, options)]
235 
236     track(
237         active_user,
238         category="dbt",
239         action='run_model',
240         label=active_user.invocation_id,
241         context=context
242     )
243 
244 
245 def track_rpc_request(options):
246     context = [SelfDescribingJson(RPC_REQUEST_SPEC, options)]
247 
248     track(
249         active_user,
250         category="dbt",
251         action='rpc_request',
252         label=active_user.invocation_id,
253         context=context
254     )
255 
256 
257 def track_package_install(options):
258     context = [SelfDescribingJson(PACKAGE_INSTALL_SPEC, options)]
259     track(
260         active_user,
261         category="dbt",
262         action='package',
263         label=active_user.invocation_id,
264         property_='install',
265         context=context
266     )
267 
268 
269 def track_invocation_end(
270         config=None, args=None, result_type=None
271 ):
272     user = active_user
273     context = [
274         get_invocation_end_context(user, config, args, result_type),
275         get_platform_context(),
276         get_dbt_env_context()
277     ]
278     track(
279         active_user,
280         category="dbt",
281         action='invocation',
282         label='end',
283         context=context
284     )
285 
286 
287 def track_invalid_invocation(
288         config=None, args=None, result_type=None
289 ):
290 
291     user = active_user
292     invocation_context = get_invocation_invalid_context(
293         user,
294         config,
295         args,
296         result_type
297     )
298 
299     context = [
300         invocation_context,
301         get_platform_context(),
302         get_dbt_env_context()
303     ]
304 
305     track(
306         active_user,
307         category="dbt",
308         action='invocation',
309         label='invalid',
310         context=context
311     )
312 
313 
314 def flush():
315     logger.debug("Flushing usage events")
316     tracker.flush()
317 
318 
319 def do_not_track():
320     global active_user
321     active_user = User(None)
322 
323 
324 def initialize_tracking(cookie_dir):
325     global active_user
326     active_user = User(cookie_dir)
327     try:
328         active_user.initialize()
329     except Exception:
330         logger.debug('Got an exception trying to initialize tracking',
331                      exc_info=True)
332         active_user = User(None)
333
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/core/dbt/tracking.py b/core/dbt/tracking.py
--- a/core/dbt/tracking.py
+++ b/core/dbt/tracking.py
@@ -13,8 +13,6 @@
 import yaml
 import os
 
-import dbt.clients.system
-
 sp_logger.setLevel(100)
 
 COLLECTOR_URL = "fishtownanalytics.sinter-collect.com"
@@ -91,12 +89,22 @@
         tracker.set_subject(subject)
 
     def set_cookie(self):
-        user = {"id": str(uuid.uuid4())}
+        # If the user points dbt to a profile directory which exists AND
+        # contains a profiles.yml file, then we can set a cookie. If the
+        # specified folder does not exist, or if there is not a profiles.yml
+        # file in this folder, then an inconsistent cookie can be used. This
+        # will change in every dbt invocation until the user points to a
+        # profile dir file which contains a valid profiles.yml file.
+        #
+        # See: https://github.com/fishtown-analytics/dbt/issues/1645
 
-        dbt.clients.system.make_directory(self.cookie_dir)
+        user = {"id": str(uuid.uuid4())}
 
-        with open(self.cookie_path, "w") as fh:
-            yaml.dump(user, fh)
+        cookie_path = os.path.abspath(self.cookie_dir)
+        profiles_file = os.path.join(cookie_path, 'profiles.yml')
+        if os.path.exists(cookie_path) and os.path.exists(profiles_file):
+            with open(self.cookie_path, "w") as fh:
+                yaml.dump(user, fh)
 
         return user

{"golden_diff": "diff --git a/core/dbt/tracking.py b/core/dbt/tracking.py\n--- a/core/dbt/tracking.py\n+++ b/core/dbt/tracking.py\n@@ -13,8 +13,6 @@\n import yaml\n import os\n \n-import dbt.clients.system\n-\n sp_logger.setLevel(100)\n \n COLLECTOR_URL = \"fishtownanalytics.sinter-collect.com\"\n@@ -91,12 +89,22 @@\n         tracker.set_subject(subject)\n \n     def set_cookie(self):\n-        user = {\"id\": str(uuid.uuid4())}\n+        # If the user points dbt to a profile directory which exists AND\n+        # contains a profiles.yml file, then we can set a cookie. If the\n+        # specified folder does not exist, or if there is not a profiles.yml\n+        # file in this folder, then an inconsistent cookie can be used. This\n+        # will change in every dbt invocation until the user points to a\n+        # profile dir file which contains a valid profiles.yml file.\n+        #\n+        # See: https://github.com/fishtown-analytics/dbt/issues/1645\n \n-        dbt.clients.system.make_directory(self.cookie_dir)\n+        user = {\"id\": str(uuid.uuid4())}\n \n-        with open(self.cookie_path, \"w\") as fh:\n-            yaml.dump(user, fh)\n+        cookie_path = os.path.abspath(self.cookie_dir)\n+        profiles_file = os.path.join(cookie_path, 'profiles.yml')\n+        if os.path.exists(cookie_path) and os.path.exists(profiles_file):\n+            with open(self.cookie_path, \"w\") as fh:\n+                yaml.dump(user, fh)\n \n         return user\n", "issue": "dbt sometimes writes a `.user.yml` and ignores configs\n## Issue\r\nIf you pass dbt a relative path to `--profiles-dir` or the `DBT_PROFILES_DIR` environment variable and execute from a subdirectory, dbt will look for the user cookie and profiles.yml in different places (the latter correct, the former incorrect).\r\n\r\n### Results\r\nWhat happened? What did you expect to happen?\r\nI got a `./profiles/.user.yml` and my settings were ignored. I expected my settings to be respected or to receive an error, and to not have a new file.\r\n\r\nSuggested fixes:\r\nMy preference: don't allow users to run dbt from subdirectories.\r\nOther option: defer loading of the user config until after we've found `dbt_project.yml`.\r\n\r\n### System information\r\nThe output of `dbt --version`:\r\n```\r\n0.14.0\r\n```\r\n\r\nThe operating system you're running on:\r\nAny\r\n\r\nThe python version you're using (probably the output of `python --version`)\r\nAny\r\n\r\n### Steps to reproduce\r\nIn as much detail as possible, please provide steps to reproduce the issue. Sample data that triggers the issue, example models, etc are all very helpful here.\r\n\r\n1) Make a dbt project in `${project_root}`\r\n2) put your profiles.yml in  `${project_root}/profiles`\r\n3) Make a subdirectory (`${project_root}/models`) and cd into it\r\n4) Run dbt with the relative path to the profiles directory as an argument to `--profiles-dir`: `dbt run --profiles-dir profiles`\r\n5) You will now have a `${project_root}/models/profiles/.user.yml` with cookie information. Also, any settings in your `profiles.yml` won't be respected.\r\n\n", "before_files": [{"content": "from dbt.logger import GLOBAL_LOGGER as logger\nfrom dbt import version as dbt_version\nfrom snowplow_tracker import Subject, Tracker, Emitter, logger as sp_logger\nfrom snowplow_tracker import SelfDescribingJson\nfrom datetime import datetime\n\nfrom dbt.adapters.factory import get_adapter\n\nimport pytz\nimport platform\nimport uuid\nimport requests\nimport yaml\nimport os\n\nimport dbt.clients.system\n\nsp_logger.setLevel(100)\n\nCOLLECTOR_URL = \"fishtownanalytics.sinter-collect.com\"\nCOLLECTOR_PROTOCOL = \"https\"\n\nINVOCATION_SPEC = 'iglu:com.dbt/invocation/jsonschema/1-0-1'\nPLATFORM_SPEC = 'iglu:com.dbt/platform/jsonschema/1-0-0'\nRUN_MODEL_SPEC = 'iglu:com.dbt/run_model/jsonschema/1-0-1'\nINVOCATION_ENV_SPEC = 'iglu:com.dbt/invocation_env/jsonschema/1-0-0'\nPACKAGE_INSTALL_SPEC = 'iglu:com.dbt/package_install/jsonschema/1-0-0'\nRPC_REQUEST_SPEC = 'iglu:com.dbt/rpc_request/jsonschema/1-0-1'\n\nDBT_INVOCATION_ENV = 'DBT_INVOCATION_ENV'\n\n\nclass TimeoutEmitter(Emitter):\n    def __init__(self):\n        super(TimeoutEmitter, self).__init__(COLLECTOR_URL,\n                                             protocol=COLLECTOR_PROTOCOL,\n                                             buffer_size=1,\n                                             on_failure=self.handle_failure)\n\n    @staticmethod\n    def handle_failure(num_ok, unsent):\n        # num_ok will always be 0, unsent will always be 1 entry long, because\n        # the buffer is length 1, so not much to talk about\n        logger.warning('Error sending message, disabling tracking')\n        do_not_track()\n\n    def http_get(self, payload):\n        sp_logger.info(\"Sending GET request to %s...\" % self.endpoint)\n        sp_logger.debug(\"Payload: %s\" % payload)\n        r = requests.get(self.endpoint, params=payload, timeout=5.0)\n\n        msg = \"GET request finished with status code: \" + str(r.status_code)\n        if self.is_good_status_code(r.status_code):\n            sp_logger.info(msg)\n        else:\n            sp_logger.warn(msg)\n        return r\n\n\nemitter = TimeoutEmitter()\ntracker = Tracker(emitter, namespace=\"cf\", app_id=\"dbt\")\n\nactive_user = None\n\n\nclass User(object):\n\n    def __init__(self, cookie_dir):\n        self.do_not_track = True\n        self.cookie_dir = cookie_dir\n\n        self.id = None\n        self.invocation_id = str(uuid.uuid4())\n        self.run_started_at = datetime.now(tz=pytz.utc)\n\n    def state(self):\n        return \"do not track\" if self.do_not_track else \"tracking\"\n\n    @property\n    def cookie_path(self):\n        return os.path.join(self.cookie_dir, '.user.yml')\n\n    def initialize(self):\n        self.do_not_track = False\n\n        cookie = self.get_cookie()\n        self.id = cookie.get('id')\n\n        subject = Subject()\n        subject.set_user_id(self.id)\n        tracker.set_subject(subject)\n\n    def set_cookie(self):\n        user = {\"id\": str(uuid.uuid4())}\n\n        dbt.clients.system.make_directory(self.cookie_dir)\n\n        with open(self.cookie_path, \"w\") as fh:\n            yaml.dump(user, fh)\n\n        return user\n\n    def get_cookie(self):\n        if not os.path.isfile(self.cookie_path):\n            user = self.set_cookie()\n        else:\n            with open(self.cookie_path, \"r\") as fh:\n                try:\n                    user = yaml.safe_load(fh)\n                    if user is None:\n                        user = self.set_cookie()\n                except yaml.reader.ReaderError:\n                    user = self.set_cookie()\n        return user\n\n\ndef get_run_type(args):\n    return 'regular'\n\n\ndef get_invocation_context(user, config, args):\n    try:\n        adapter_type = get_adapter(config).type()\n    except Exception:\n        adapter_type = None\n\n    return {\n        \"project_id\": None if config is None else config.hashed_name(),\n        \"user_id\": user.id,\n        \"invocation_id\": user.invocation_id,\n\n        \"command\": args.which,\n        \"options\": None,\n        \"version\": str(dbt_version.installed),\n\n        \"run_type\": get_run_type(args),\n        \"adapter_type\": adapter_type,\n    }\n\n\ndef get_invocation_start_context(user, config, args):\n    data = get_invocation_context(user, config, args)\n\n    start_data = {\n        \"progress\": \"start\",\n        \"result_type\": None,\n        \"result\": None\n    }\n\n    data.update(start_data)\n    return SelfDescribingJson(INVOCATION_SPEC, data)\n\n\ndef get_invocation_end_context(user, config, args, result_type):\n    data = get_invocation_context(user, config, args)\n\n    start_data = {\n        \"progress\": \"end\",\n        \"result_type\": result_type,\n        \"result\": None\n    }\n\n    data.update(start_data)\n    return SelfDescribingJson(INVOCATION_SPEC, data)\n\n\ndef get_invocation_invalid_context(user, config, args, result_type):\n    data = get_invocation_context(user, config, args)\n\n    start_data = {\n        \"progress\": \"invalid\",\n        \"result_type\": result_type,\n        \"result\": None\n    }\n\n    data.update(start_data)\n    return SelfDescribingJson(INVOCATION_SPEC, data)\n\n\ndef get_platform_context():\n    data = {\n        \"platform\": platform.platform(),\n        \"python\": platform.python_version(),\n        \"python_version\": platform.python_implementation(),\n    }\n\n    return SelfDescribingJson(PLATFORM_SPEC, data)\n\n\ndef get_dbt_env_context():\n    default = 'manual'\n\n    dbt_invocation_env = os.getenv(DBT_INVOCATION_ENV, default)\n    if dbt_invocation_env == '':\n        dbt_invocation_env = default\n\n    data = {\n        \"environment\": dbt_invocation_env,\n    }\n\n    return SelfDescribingJson(INVOCATION_ENV_SPEC, data)\n\n\ndef track(user, *args, **kwargs):\n    if user.do_not_track:\n        return\n    else:\n        logger.debug(\"Sending event: {}\".format(kwargs))\n        try:\n            tracker.track_struct_event(*args, **kwargs)\n        except Exception:\n            logger.debug(\n                \"An error was encountered while trying to send an event\"\n            )\n\n\ndef track_invocation_start(config=None, args=None):\n    context = [\n        get_invocation_start_context(active_user, config, args),\n        get_platform_context(),\n        get_dbt_env_context()\n    ]\n\n    track(\n        active_user,\n        category=\"dbt\",\n        action='invocation',\n        label='start',\n        context=context\n    )\n\n\ndef track_model_run(options):\n    context = [SelfDescribingJson(RUN_MODEL_SPEC, options)]\n\n    track(\n        active_user,\n        category=\"dbt\",\n        action='run_model',\n        label=active_user.invocation_id,\n        context=context\n    )\n\n\ndef track_rpc_request(options):\n    context = [SelfDescribingJson(RPC_REQUEST_SPEC, options)]\n\n    track(\n        active_user,\n        category=\"dbt\",\n        action='rpc_request',\n        label=active_user.invocation_id,\n        context=context\n    )\n\n\ndef track_package_install(options):\n    context = [SelfDescribingJson(PACKAGE_INSTALL_SPEC, options)]\n    track(\n        active_user,\n        category=\"dbt\",\n        action='package',\n        label=active_user.invocation_id,\n        property_='install',\n        context=context\n    )\n\n\ndef track_invocation_end(\n        config=None, args=None, result_type=None\n):\n    user = active_user\n    context = [\n        get_invocation_end_context(user, config, args, result_type),\n        get_platform_context(),\n        get_dbt_env_context()\n    ]\n    track(\n        active_user,\n        category=\"dbt\",\n        action='invocation',\n        label='end',\n        context=context\n    )\n\n\ndef track_invalid_invocation(\n        config=None, args=None, result_type=None\n):\n\n    user = active_user\n    invocation_context = get_invocation_invalid_context(\n        user,\n        config,\n        args,\n        result_type\n    )\n\n    context = [\n        invocation_context,\n        get_platform_context(),\n        get_dbt_env_context()\n    ]\n\n    track(\n        active_user,\n        category=\"dbt\",\n        action='invocation',\n        label='invalid',\n        context=context\n    )\n\n\ndef flush():\n    logger.debug(\"Flushing usage events\")\n    tracker.flush()\n\n\ndef do_not_track():\n    global active_user\n    active_user = User(None)\n\n\ndef initialize_tracking(cookie_dir):\n    global active_user\n    active_user = User(cookie_dir)\n    try:\n        active_user.initialize()\n    except Exception:\n        logger.debug('Got an exception trying to initialize tracking',\n                     exc_info=True)\n        active_user = User(None)\n", "path": "core/dbt/tracking.py"}], "after_files": [{"content": "from dbt.logger import GLOBAL_LOGGER as logger\nfrom dbt import version as dbt_version\nfrom snowplow_tracker import Subject, Tracker, Emitter, logger as sp_logger\nfrom snowplow_tracker import SelfDescribingJson\nfrom datetime import datetime\n\nfrom dbt.adapters.factory import get_adapter\n\nimport pytz\nimport platform\nimport uuid\nimport requests\nimport yaml\nimport os\n\nsp_logger.setLevel(100)\n\nCOLLECTOR_URL = \"fishtownanalytics.sinter-collect.com\"\nCOLLECTOR_PROTOCOL = \"https\"\n\nINVOCATION_SPEC = 'iglu:com.dbt/invocation/jsonschema/1-0-1'\nPLATFORM_SPEC = 'iglu:com.dbt/platform/jsonschema/1-0-0'\nRUN_MODEL_SPEC = 'iglu:com.dbt/run_model/jsonschema/1-0-1'\nINVOCATION_ENV_SPEC = 'iglu:com.dbt/invocation_env/jsonschema/1-0-0'\nPACKAGE_INSTALL_SPEC = 'iglu:com.dbt/package_install/jsonschema/1-0-0'\nRPC_REQUEST_SPEC = 'iglu:com.dbt/rpc_request/jsonschema/1-0-1'\n\nDBT_INVOCATION_ENV = 'DBT_INVOCATION_ENV'\n\n\nclass TimeoutEmitter(Emitter):\n    def __init__(self):\n        super(TimeoutEmitter, self).__init__(COLLECTOR_URL,\n                                             protocol=COLLECTOR_PROTOCOL,\n                                             buffer_size=1,\n                                             on_failure=self.handle_failure)\n\n    @staticmethod\n    def handle_failure(num_ok, unsent):\n        # num_ok will always be 0, unsent will always be 1 entry long, because\n        # the buffer is length 1, so not much to talk about\n        logger.warning('Error sending message, disabling tracking')\n        do_not_track()\n\n    def http_get(self, payload):\n        sp_logger.info(\"Sending GET request to %s...\" % self.endpoint)\n        sp_logger.debug(\"Payload: %s\" % payload)\n        r = requests.get(self.endpoint, params=payload, timeout=5.0)\n\n        msg = \"GET request finished with status code: \" + str(r.status_code)\n        if self.is_good_status_code(r.status_code):\n            sp_logger.info(msg)\n        else:\n            sp_logger.warn(msg)\n        return r\n\n\nemitter = TimeoutEmitter()\ntracker = Tracker(emitter, namespace=\"cf\", app_id=\"dbt\")\n\nactive_user = None\n\n\nclass User(object):\n\n    def __init__(self, cookie_dir):\n        self.do_not_track = True\n        self.cookie_dir = cookie_dir\n\n        self.id = None\n        self.invocation_id = str(uuid.uuid4())\n        self.run_started_at = datetime.now(tz=pytz.utc)\n\n    def state(self):\n        return \"do not track\" if self.do_not_track else \"tracking\"\n\n    @property\n    def cookie_path(self):\n        return os.path.join(self.cookie_dir, '.user.yml')\n\n    def initialize(self):\n        self.do_not_track = False\n\n        cookie = self.get_cookie()\n        self.id = cookie.get('id')\n\n        subject = Subject()\n        subject.set_user_id(self.id)\n        tracker.set_subject(subject)\n\n    def set_cookie(self):\n        # If the user points dbt to a profile directory which exists AND\n        # contains a profiles.yml file, then we can set a cookie. If the\n        # specified folder does not exist, or if there is not a profiles.yml\n        # file in this folder, then an inconsistent cookie can be used. This\n        # will change in every dbt invocation until the user points to a\n        # profile dir file which contains a valid profiles.yml file.\n        #\n        # See: https://github.com/fishtown-analytics/dbt/issues/1645\n\n        user = {\"id\": str(uuid.uuid4())}\n\n        cookie_path = os.path.abspath(self.cookie_dir)\n        profiles_file = os.path.join(cookie_path, 'profiles.yml')\n        if os.path.exists(cookie_path) and os.path.exists(profiles_file):\n            with open(self.cookie_path, \"w\") as fh:\n                yaml.dump(user, fh)\n\n        return user\n\n    def get_cookie(self):\n        if not os.path.isfile(self.cookie_path):\n            user = self.set_cookie()\n        else:\n            with open(self.cookie_path, \"r\") as fh:\n                try:\n                    user = yaml.safe_load(fh)\n                    if user is None:\n                        user = self.set_cookie()\n                except yaml.reader.ReaderError:\n                    user = self.set_cookie()\n        return user\n\n\ndef get_run_type(args):\n    return 'regular'\n\n\ndef get_invocation_context(user, config, args):\n    try:\n        adapter_type = get_adapter(config).type()\n    except Exception:\n        adapter_type = None\n\n    return {\n        \"project_id\": None if config is None else config.hashed_name(),\n        \"user_id\": user.id,\n        \"invocation_id\": user.invocation_id,\n\n        \"command\": args.which,\n        \"options\": None,\n        \"version\": str(dbt_version.installed),\n\n        \"run_type\": get_run_type(args),\n        \"adapter_type\": adapter_type,\n    }\n\n\ndef get_invocation_start_context(user, config, args):\n    data = get_invocation_context(user, config, args)\n\n    start_data = {\n        \"progress\": \"start\",\n        \"result_type\": None,\n        \"result\": None\n    }\n\n    data.update(start_data)\n    return SelfDescribingJson(INVOCATION_SPEC, data)\n\n\ndef get_invocation_end_context(user, config, args, result_type):\n    data = get_invocation_context(user, config, args)\n\n    start_data = {\n        \"progress\": \"end\",\n        \"result_type\": result_type,\n        \"result\": None\n    }\n\n    data.update(start_data)\n    return SelfDescribingJson(INVOCATION_SPEC, data)\n\n\ndef get_invocation_invalid_context(user, config, args, result_type):\n    data = get_invocation_context(user, config, args)\n\n    start_data = {\n        \"progress\": \"invalid\",\n        \"result_type\": result_type,\n        \"result\": None\n    }\n\n    data.update(start_data)\n    return SelfDescribingJson(INVOCATION_SPEC, data)\n\n\ndef get_platform_context():\n    data = {\n        \"platform\": platform.platform(),\n        \"python\": platform.python_version(),\n        \"python_version\": platform.python_implementation(),\n    }\n\n    return SelfDescribingJson(PLATFORM_SPEC, data)\n\n\ndef get_dbt_env_context():\n    default = 'manual'\n\n    dbt_invocation_env = os.getenv(DBT_INVOCATION_ENV, default)\n    if dbt_invocation_env == '':\n        dbt_invocation_env = default\n\n    data = {\n        \"environment\": dbt_invocation_env,\n    }\n\n    return SelfDescribingJson(INVOCATION_ENV_SPEC, data)\n\n\ndef track(user, *args, **kwargs):\n    if user.do_not_track:\n        return\n    else:\n        logger.debug(\"Sending event: {}\".format(kwargs))\n        try:\n            tracker.track_struct_event(*args, **kwargs)\n        except Exception:\n            logger.debug(\n                \"An error was encountered while trying to send an event\"\n            )\n\n\ndef track_invocation_start(config=None, args=None):\n    context = [\n        get_invocation_start_context(active_user, config, args),\n        get_platform_context(),\n        get_dbt_env_context()\n    ]\n\n    track(\n        active_user,\n        category=\"dbt\",\n        action='invocation',\n        label='start',\n        context=context\n    )\n\n\ndef track_model_run(options):\n    context = [SelfDescribingJson(RUN_MODEL_SPEC, options)]\n\n    track(\n        active_user,\n        category=\"dbt\",\n        action='run_model',\n        label=active_user.invocation_id,\n        context=context\n    )\n\n\ndef track_rpc_request(options):\n    context = [SelfDescribingJson(RPC_REQUEST_SPEC, options)]\n\n    track(\n        active_user,\n        category=\"dbt\",\n        action='rpc_request',\n        label=active_user.invocation_id,\n        context=context\n    )\n\n\ndef track_package_install(options):\n    context = [SelfDescribingJson(PACKAGE_INSTALL_SPEC, options)]\n    track(\n        active_user,\n        category=\"dbt\",\n        action='package',\n        label=active_user.invocation_id,\n        property_='install',\n        context=context\n    )\n\n\ndef track_invocation_end(\n        config=None, args=None, result_type=None\n):\n    user = active_user\n    context = [\n        get_invocation_end_context(user, config, args, result_type),\n        get_platform_context(),\n        get_dbt_env_context()\n    ]\n    track(\n        active_user,\n        category=\"dbt\",\n        action='invocation',\n        label='end',\n        context=context\n    )\n\n\ndef track_invalid_invocation(\n        config=None, args=None, result_type=None\n):\n\n    user = active_user\n    invocation_context = get_invocation_invalid_context(\n        user,\n        config,\n        args,\n        result_type\n    )\n\n    context = [\n        invocation_context,\n        get_platform_context(),\n        get_dbt_env_context()\n    ]\n\n    track(\n        active_user,\n        category=\"dbt\",\n        action='invocation',\n        label='invalid',\n        context=context\n    )\n\n\ndef flush():\n    logger.debug(\"Flushing usage events\")\n    tracker.flush()\n\n\ndef do_not_track():\n    global active_user\n    active_user = User(None)\n\n\ndef initialize_tracking(cookie_dir):\n    global active_user\n    active_user = User(cookie_dir)\n    try:\n        active_user.initialize()\n    except Exception:\n        logger.debug('Got an exception trying to initialize tracking',\n                     exc_info=True)\n        active_user = User(None)\n", "path": "core/dbt/tracking.py"}]}