Repository: conan-io/conan

Issue:
[feature] Log User for Remote in Verbose Mode
<!-- What is your suggestion? Please be as specific as possible! -->
When trying to download a package from a repo which hides existence of unauthorized resources (like Artifactory) trying to download a package results in an error that the package could not be found on the repo. Even when enabling the most verbose logging mode its nowhere written which user is used to get the package.

```
package/1.0.2@repo/stable: Trying with 'gitlab'...
DEBUG :rest_client_common.py[160]: REST: ping: https://gitlab.com/api/v4/packages/conan/v1/ping [2021-04-22 22:52:03,502]
DEBUG :rest_client.py [58]: REST: Cached capabilities for the remote: [] [2021-04-22 22:52:03,644]
DEBUG :rest_client_common.py[188]: REST: get: https://gitlab.com/api/v4/packages/conan/v1/conans/package/1.0.2/repo/stable/download_urls [2021-04-22 22:52:03,645]
DEBUG :rest_client_common.py[30]: REST ERROR: <class 'conans.errors.NotFoundException'> [2021-04-22 22:52:03,703]
ERROR: Unable to find 'package/1.0.2@repo/stable' in remotes
```

It would be a massive help if the user used for the remote could be found in those log lines!

It would may be even more helpful if the user used for the remote is logged in the general output not only in verbose mode. It could be something like 

```
package/1.0.2@repo/stable: Trying with 'anonymus' @ 'gitlab'...
```

- [x] I've read the [CONTRIBUTING guide](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md).



Discussion:
Hi @p0fi,
Thanks a lot for the suggestion, we'll try to add that information somewhere in the logs for the next release.
I have added a look trying to implement this, but it seems way harder than it looks at first sight. It happens that the user is not available at that point in time at all (at ``package/1.0.2@repo/stable: Trying with 'gitlab'``), it is read much later at the "Rest" layer, so it would require either reading it again from the DB just for displaying, or quite a few changes to the architecture of the app. 

Furthermore, it is also not straightforward to add it at the Rest layer (for the ``DEBUG :`` messages), because that level only gets the token used, but not the username. I have tried to do it, but it was too many changes:

```
(conan36) λ git diff --stat
 conans/client/rest/auth_manager.py       |  5 +----
 conans/client/rest/rest_client.py        | 19 ++++++++++---------
 conans/client/rest/rest_client_common.py |  7 ++++---
 conans/client/rest/rest_client_v2.py     | 10 ++++++----
 4 files changed, 21 insertions(+), 20 deletions(-)
```
And not counting tests that could need to be fixed.
So it seems a lot of change, with some non-negligible risk to break something, for something that only shows in the log in debug mode, and for an information that can be displayed very easily with a ``conan user`` command.

So I think it is better not to implement this feature now. While we refactor the internals of the Rest layers for Conan 2.0, we will try to display the user if possible.



Well this sometimes happens in software, something looks trivial but turns out its a major thing 🤓 

Thanks for letting me know! 

I know that this information can easily be obtained by the `conan user` command. I ran in some problems that took me over an hour to even think that something with the user could be wrong. To read which user is used for a given remote would have saved me a lot of trouble I think. 

It would be cool if this makes it into Conan 2.0 🎉 
I have tried to do a quick implementation of this for 2.0, but it turned out too dirty. As it is getting very close and this doesn't seem a high priority, I am moving this to 2.X.

I have been checking this, and the necessary refactors for this are:
- A central point ``RemotesRegistry`` access that hides the user login access and update, and that can be used by everyone without knowing about ``LocalDB`` and ``Remotes`` separately. ``LocalDB`` becomes an internal implementation detail initially (then it could be replaced for a text file if we wanted to, for simplicity, instead of using a full DB)
- AuthApiManager uses the new ``RemotesRegistry`` 
- The RemotesAPI uses the new ``RemotesRegistry``
- The ``Remote`` model can be extended to carry the ``user`` information.
- Finally, the ``ConanProxy`` will be able to display the ``user`` information while downloading.



Patch:
diff --git a/conan/api/output.py b/conan/api/output.py
index cce692af638..4d110270c56 100644
--- a/conan/api/output.py
+++ b/conan/api/output.py
@@ -212,12 +212,12 @@ def _write_message(self, msg, fg=None, bg=None):
 
     def trace(self, msg):
         if self._conan_output_level <= LEVEL_TRACE:
-            self._write_message(msg, fg=Color.BRIGHT_WHITE)
+            self._write_message(msg, fg=Color.BLUE)
         return self
 
     def debug(self, msg):
         if self._conan_output_level <= LEVEL_DEBUG:
-            self._write_message(msg)
+            self._write_message(msg, fg=Color.MAGENTA)
         return self
 
     def verbose(self, msg, fg=None, bg=None):
diff --git a/conans/client/rest/auth_manager.py b/conans/client/rest/auth_manager.py
index 525de701af7..e79fd404070 100644
--- a/conans/client/rest/auth_manager.py
+++ b/conans/client/rest/auth_manager.py
@@ -19,7 +19,7 @@
 LOGIN_RETRIES = 3
 
 
-class RemoteCreds:
+class _RemoteCreds:
     def __init__(self, localdb):
         self._localdb = localdb
 
@@ -28,11 +28,14 @@ def get(self, remote):
         if creds is None:
             user, token, _ = self._localdb.get_login(remote.url)
             creds = user, token
+            usermsg = f"with user '{user}'" if user else "anonymously"
+            ConanOutput().info(f"Connecting to remote '{remote.name}' {usermsg}")
             setattr(remote, "_creds", creds)
         return creds
 
     def set(self, remote, user, token):
         setattr(remote, "_creds", (user, token))
+        ConanOutput().success(f"Authenticated in remote '{remote.name}' with user '{user}'")
         self._localdb.store(user, token, None, remote.url)
 
 
@@ -40,7 +43,7 @@ class ConanApiAuthManager:
 
     def __init__(self, requester, cache_folder, localdb, global_conf):
         self._requester = requester
-        self._creds = RemoteCreds(localdb)
+        self._creds = _RemoteCreds(localdb)
         self._global_conf = global_conf
         self._cache_folder = cache_folder
 
diff --git a/conans/client/rest/conan_requester.py b/conans/client/rest/conan_requester.py
index edb2ce98926..b6700c9f510 100644
--- a/conans/client/rest/conan_requester.py
+++ b/conans/client/rest/conan_requester.py
@@ -9,6 +9,7 @@
 from jinja2 import Template
 from requests.adapters import HTTPAdapter
 
+from conan.api.output import ConanOutput
 from conan.internal.cache.home_paths import HomePaths
 
 from conan import __version__
@@ -198,6 +199,7 @@ def _call_method(self, method, url, **kwargs):
             for var_name in ("http_proxy", "https_proxy", "ftp_proxy", "all_proxy", "no_proxy"):
                 popped = True if os.environ.pop(var_name, None) else popped
                 popped = True if os.environ.pop(var_name.upper(), None) else popped
+        ConanOutput(scope="HttpRequest").trace(f"{method}: {url}")
         try:
             all_kwargs = self._add_kwargs(url, kwargs)
             tmp = getattr(self._http_requester, method)(url, **all_kwargs)


Test patch:
diff --git a/test/integration/command_v2/list_test.py b/test/integration/command_v2/list_test.py
index b8bcbed18d5..32fd9876030 100644
--- a/test/integration/command_v2/list_test.py
+++ b/test/integration/command_v2/list_test.py
@@ -724,6 +724,8 @@ class TestListRemotes:
 
     def test_search_no_matching_recipes(self, client):
         expected_output = textwrap.dedent("""\
+        Connecting to remote 'default' with user 'admin'
+        Connecting to remote 'other' with user 'admin'
         Local Cache
           ERROR: Recipe 'whatever/0.1' not found
         default
diff --git a/test/integration/command_v2/search_test.py b/test/integration/command_v2/search_test.py
index 6d6ae26b300..7262f6d814c 100644
--- a/test/integration/command_v2/search_test.py
+++ b/test/integration/command_v2/search_test.py
@@ -30,7 +30,9 @@ def test_search_no_params(self):
         assert "error: the following arguments are required: reference" in self.client.out
 
     def test_search_no_matching_recipes(self, remotes):
-        expected_output = ("remote1\n"
+        expected_output = ("Connecting to remote 'remote1' anonymously\n"
+                           "Connecting to remote 'remote2' anonymously\n"
+                           "remote1\n"
                            "  ERROR: Recipe 'whatever' not found\n"
                            "remote2\n"
                            "  ERROR: Recipe 'whatever' not found\n")