Repository: conan-io/conan
Pull request: add CONAN_LOG_LEVEL env-var
Changelog: Feature: Define ``CONAN_LOG_LEVEL`` env-var to be able to change verbosity at a global level.
Docs: https://github.com/conan-io/docs/pull/3490

Close https://github.com/conan-io/conan/issues/14693


Problem statement:
[feature] Support command line verbosity via env-var or global.conf
Instead of requiring always to ``-vvv`` to all commands, it could be convenient to:
- Allow log level to be defined via env-var, for CI systems
- Or allow log level to be defined via ``global.conf`` configuration (this will be a bit more difficult to implement)

Hints from issue discussion:

Commit message: add CONAN_LOG_LEVEL env-var

Patch to review:
diff --git a/conan/cli/command.py b/conan/cli/command.py
index 85c90e936fe..292303d8537 100644
--- a/conan/cli/command.py
+++ b/conan/cli/command.py
@@ -1,4 +1,5 @@
 import argparse
+import os
 import textwrap
 
 from conan.api.output import ConanOutput
@@ -101,7 +102,7 @@ def __init__(self, *args, **kwargs):
 
     def parse_args(self, args=None, namespace=None):
         args = super().parse_args(args)
-        ConanOutput.define_log_level(args.v)
+        ConanOutput.define_log_level(os.getenv("CONAN_LOG_LEVEL") or args.v)
         return args
 
 
diff --git a/conans/test/integration/command_v2/test_output_level.py b/conans/test/integration/command_v2/test_output_level.py
index f485424924e..68d4f45e3ba 100644
--- a/conans/test/integration/command_v2/test_output_level.py
+++ b/conans/test/integration/command_v2/test_output_level.py
@@ -1,7 +1,6 @@
-import json
-
 from conans.test.assets.genconanfile import GenConanfile
 from conans.test.utils.tools import TestClient
+from conans.util.env import environment_update
 
 
 def test_invalid_output_level():
@@ -142,3 +141,43 @@ def test_output_level():
     assert "This is a success" not in t.out
     assert "This is a warning" not in t.out
     assert "This is a error" in t.out
+
+
+def test_output_level_envvar():
+
+    lines = ("self.output.trace('This is a trace')",
+             "self.output.debug('This is a debug')",
+             "self.output.verbose('This is a verbose')",
+             "self.output.info('This is a info')",
+             "self.output.highlight('This is a highlight')",
+             "self.output.success('This is a success')",
+             "self.output.warning('This is a warning')",
+             "self.output.error('This is a error')",
+             )
+
+    t = TestClient()
+    t.save({"conanfile.py": GenConanfile().with_package(*lines)})
+
+    # Check if -v argument is equal to VERBOSE level
+    with environment_update({"CONAN_LOG_LEVEL": "verbose"}):
+        t.run("create . --name foo --version 1.0")
+        assert "This is a trace" not in t.out
+        assert "This is a debug" not in t.out
+        assert "This is a verbose" in t.out
+        assert "This is a info" in t.out
+        assert "This is a highlight" in t.out
+        assert "This is a success" in t.out
+        assert "This is a warning" in t.out
+        assert "This is a error" in t.out
+
+        # Check if -v argument is equal to VERBOSE level
+    with environment_update({"CONAN_LOG_LEVEL": "error"}):
+        t.run("create . --name foo --version 1.0")
+        assert "This is a trace" not in t.out
+        assert "This is a debug" not in t.out
+        assert "This is a verbose" not in t.out
+        assert "This is a info" not in t.out
+        assert "This is a highlight" not in t.out
+        assert "This is a success" not in t.out
+        assert "This is a warning" not in t.out
+        assert "This is a error" in t.out


Code review comments:
diff_hunk: @@ -101,7 +102,7 @@ def __init__(self, *args, **kwargs):
 
     def parse_args(self, args=None, namespace=None):
         args = super().parse_args(args)
-        ConanOutput.define_log_level(args.v)
+        ConanOutput.define_log_level(os.getenv("CONAN_LOG_LEVEL") or args.v)
path: conan/cli/command.py
text: @user1:
```suggestion
        ConanOutput.define_log_level(os.getenv("CONAN_LOG_LEVEL", args.v))
```