Repository: apache/airflow

Issue:
Airflow logging secrets masker assumes dict_key is type `str`
**Apache Airflow version**: 2.1.0

**What happened**:
Airflow logging assume dict_key is type `str`
```
    logging.info("Dictionary where key is int type: %s", modified_table_mapping)
  File "/usr/lib64/python3.6/logging/__init__.py", line 1902, in info
    root.info(msg, *args, **kwargs)
  File "/usr/lib64/python3.6/logging/__init__.py", line 1308, in info
    self._log(INFO, msg, args, **kwargs)
  File "/usr/lib64/python3.6/logging/__init__.py", line 1444, in _log
    self.handle(record)
  File "/usr/lib64/python3.6/logging/__init__.py", line 1453, in handle
    if (not self.disabled) and self.filter(record):
  File "/usr/lib64/python3.6/logging/__init__.py", line 720, in filter
    result = f.filter(record)
  File "/bb/bin/airflow_env/lib/python3.6/site-packages/airflow/utils/log/secrets_masker.py", line 157, in filter
    record.__dict__[k] = self.redact(v)
  File "/bb/bin/airflow_env/lib/python3.6/site-packages/airflow/utils/log/secrets_masker.py", line 193, in redact
    return {dict_key: self.redact(subval, dict_key) for dict_key, subval in item.items()}
  File "/bb/bin/airflow_env/lib/python3.6/site-packages/airflow/utils/log/secrets_masker.py", line 193, in <dictcomp>
    return {dict_key: self.redact(subval, dict_key) for dict_key, subval in item.items()}
  File "/bb/bin/airflow_env/lib/python3.6/site-packages/airflow/utils/log/secrets_masker.py", line 189, in redact
    if name and should_hide_value_for_key(name):
  File "/bb/bin/airflow_env/lib/python3.6/site-packages/airflow/utils/log/secrets_masker.py", line 74, in should_hide_value_for_key
    name = name.strip().lower()
AttributeError: 'int' object has no attribute 'strip'
```

**How to reproduce it**:
Define a dictionary where the type of keys is `int` and print it in any Airflow tasks.



Discussion:
Thanks for opening your first issue here! Be sure to follow the issue template!

should be easy to fix by str() 

Resolving patch:
diff --git a/airflow/utils/log/secrets_masker.py b/airflow/utils/log/secrets_masker.py
--- a/airflow/utils/log/secrets_masker.py
+++ b/airflow/utils/log/secrets_masker.py
@@ -63,7 +63,7 @@ def should_hide_value_for_key(name):
     """Should the value for this given name (Variable name, or key in conn.extra_dejson) be hidden"""
     from airflow import settings
 
-    if name and settings.HIDE_SENSITIVE_VAR_CONN_FIELDS:
+    if isinstance(name, str) and settings.HIDE_SENSITIVE_VAR_CONN_FIELDS:
         name = name.strip().lower()
         return any(s in name for s in get_sensitive_variables_fields())
     return False


Test patch:
diff --git a/tests/utils/log/test_secrets_masker.py b/tests/utils/log/test_secrets_masker.py
--- a/tests/utils/log/test_secrets_masker.py
+++ b/tests/utils/log/test_secrets_masker.py
@@ -179,6 +179,8 @@ def test_mask_secret(self, name, value, expected_mask):
             ({"secret", "other"}, None, ["secret", "other"], ["***", "***"]),
             # We don't mask dict _keys_.
             ({"secret", "other"}, None, {"data": {"secret": "secret"}}, {"data": {"secret": "***"}}),
+            # Non string dict keys
+            ({"secret", "other"}, None, {1: {"secret": "secret"}}, {1: {"secret": "***"}}),
             (
                 # Since this is a sensitive name, all the values should be redacted!
                 {"secret"},
@@ -221,6 +223,7 @@ class TestShouldHideValueForKey:
             ("google_api_key", True),
             ("GOOGLE_API_KEY", True),
             ("GOOGLE_APIKEY", True),
+            (1, False),
         ],
     )
     def test_hiding_defaults(self, key, expected_result):