Repository: tensorflow
Issue: Duplicate Logs After tf.saved_model.save with Custom Logging Configurations
Labels: type:others,comp:apis,2.17

### Issue type

Feature Request

### Have you reproduced the bug with TensorFlow Nightly?

No

### Source

source

### TensorFlow version

2.17.0

### Custom code

Yes

### OS platform and distribution

Fedora Linux 40

### Mobile device

_No response_

### Python version

3.11

### Bazel version

_No response_

### GCC/compiler version

_No response_

### CUDA/cuDNN version

_No response_

### GPU model and memory

_No response_

### Current behavior?

When using tf.saved_model.save, log messages are duplicated in my application. This happens because TensorFlow adds its own handlers, which interfere with my custom logging setup.

TensorFlow should respect existing logging configurations and avoid adding unnecessary handlers. Some documentation to help align TensorFlow’s logging with user-defined settings would be great.

Setting logger.propagate = False works but requires extra setup.

My suggestion is to check for existing log handlers before adding new ones.

Thanks for looking into this.

### Standalone code to reproduce the issue

Here is the minimal code to reproduce the issue. You can check the code and results in this [colab notebook](https://colab.research.google.com/drive/1IB3IM81FCX9LJ0Ae8uW9p5OCvvJ986fm?usp=sharing) as well.

```python

import logging
import logging.config
import sys
from typing import Tuple
import tensorflow as tf
import numpy as np


def create_keras_sequential_model() -> tf.keras.Model:
    return tf.keras.Sequential(
        [
            tf.keras.layers.Input(shape=(10,)),
            tf.keras.layers.Dense(64, activation="relu"),
            tf.keras.layers.Dense(1),
        ]
    )


def generate_random_data(num_samples: int = 1000) -> Tuple[np.ndarray, np.ndarray]:
    x = np.random.random((num_samples, 10))
    y = np.random.random((num_samples, 1))
    return x, y


def compile_model(model: tf.keras.Model) -> None:
    model.compile(optimizer="sgd", loss="mean_absolute_error", metrics=["mae"])


def fit_model(
    model: tf.keras.Model, x: np.ndarray, y: np.ndarray, epochs: int = 10
) -> None:
    model.fit(x, y, epochs=epochs, verbose=0)


def create_compile_return_model() -> None:
    model = create_keras_sequential_model()
    compile_model(model)
    x, y = generate_random_data()
    fit_model(model, x, y)
    return model


def get_custom_formatter_logger() -> logging.Logger:
    log_format_with_time = "%(asctime)s - %(levelname)s %(message)s"
    logHandler = logging.StreamHandler(sys.stdout)
    formatter = logging.Formatter(log_format_with_time)
    logHandler.setFormatter(formatter)
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    logger.addHandler(logHandler)
    # logger.propagate = False #If you add this, then logs are not duplicated
    return logger


if __name__ == "__main__":

    logger = get_custom_formatter_logger()
    logger.info("TF version: %s", tf.__version__)
    logger.info("Started")
    keras_model = create_compile_return_model()
    logger.info("Model created, compiled and trained. Now saving the model!")
    tf.saved_model.save(keras_model, "my_fake_model")
    logger.info("Model saved!")
    logger.info("Logs are now duplicated!")
    logger.info("Finished")

```


### Relevant log output

```
2024-10-18 13:23:10,159 - INFO TF version: 2.17.0
2024-10-18 13:23:10,160 - INFO Started
2024-10-18 13:23:11,400 - INFO Model created, compiled and trained. Now saving the model!
2024-10-18 13:23:11,832 - INFO Model saved!
INFO:__main__:Model saved!
2024-10-18 13:23:11,832 - INFO Logs are now duplicated!
INFO:__main__:Logs are now duplicated!
2024-10-18 13:23:11,832 - INFO Finished
INFO:__main__:Finished
```