code: def tracer_provider(
      tracer_type: str = Provide[tracing.exporter_type],
      sample_rate: float | None = Provide[tracing.sample_rate],
      timeout: int | None = Provide[tracing.timeout],
      max_tag_value_length: int
      | None = Provide[tracing.max_tag_value_length],
      zipkin: dict[str, t.Any] = Provide[tracing.zipkin],
      jaeger: dict[str, t.Any] = Provide[tracing.jaeger],
      otlp: dict[str, t.Any] = Provide[tracing.otlp],
  ):
      from opentelemetry.sdk.resources import SERVICE_INSTANCE_ID
      from opentelemetry.sdk.resources import SERVICE_NAME
      from opentelemetry.sdk.resources import SERVICE_NAMESPACE
      from opentelemetry.sdk.resources import SERVICE_VERSION
      from opentelemetry.sdk.resources import OTELResourceDetector
      from opentelemetry.sdk.resources import Resource
      from opentelemetry.sdk.trace import TracerProvider
      from opentelemetry.sdk.trace.export import BatchSpanProcessor
  
      from ...exceptions import InvalidArgument
      from ..utils.telemetry import ParentBasedTraceIdRatio
  
      if sample_rate is None:
          sample_rate = 0.0
      if sample_rate == 0.0:
          logger.debug(
              "'tracing.sample_rate' is set to zero. No traces will be collected. Please refer to https://docs.bentoml.com/en/latest/guides/tracing.html for more details."
          )
  
      # User can optionally configure the resource with the following environment variables. Only
      # configure resource if user has not explicitly configured it.
      system_otel_resources: Resource = OTELResourceDetector().detect()
  
      _resource = {}
      if component_context.component_name:
          _resource[SERVICE_NAME] = component_context.component_name
      if component_context.component_index:
          _resource[
              SERVICE_INSTANCE_ID
          ] = component_context.component_index
      if component_context.bento_name:
          _resource[SERVICE_NAMESPACE] = component_context.bento_name
      if component_context.bento_version:
          _resource[SERVICE_VERSION] = component_context.bento_version
  
      bentoml_resource = Resource.create(_resource)
  
      resources = bentoml_resource.merge(system_otel_resources)
      trace_context.service_name = resources.attributes.get(
          SERVICE_NAME
      )
  
      # create tracer provider
      provider = TracerProvider(
          sampler=ParentBasedTraceIdRatio(sample_rate),
          resource=resources,
      )
      if tracer_type == "zipkin" and any(zipkin.values()):
          from opentelemetry.exporter.zipkin.json import ZipkinExporter
  
          exporter = ZipkinExporter(
              endpoint=zipkin.get("endpoint"),
              local_node_ipv4=zipkin.get("local_node_ipv4"),
              local_node_ipv6=zipkin.get("local_node_ipv6"),
              local_node_port=zipkin.get("local_node_port"),
              max_tag_value_length=max_tag_value_length,
              timeout=timeout,
          )
      elif tracer_type == "jaeger" and any(jaeger.values()):
          protocol = jaeger.get("protocol")
          if protocol == "thrift":
              from opentelemetry.exporter.jaeger.thrift import (
                  JaegerExporter,
              )
          elif protocol == "grpc":
              from opentelemetry.exporter.jaeger.proto.grpc import (
                  JaegerExporter,
              )
          else:
              raise InvalidArgument(
                  f"Invalid 'api_server.tracing.jaeger.protocol' value: {protocol}"
              ) from None
          exporter = JaegerExporter(
              collector_endpoint=jaeger.get("collector_endpoint"),
              max_tag_value_length=max_tag_value_length,
              timeout=timeout,
              **jaeger[protocol],
          )
      elif tracer_type == "otlp" and any(otlp.values()):
          protocol = otlp.get("protocol")
          if protocol == "grpc":
              from opentelemetry.exporter.otlp.proto.grpc import (
                  trace_exporter,
              )
          elif protocol == "http":
              from opentelemetry.exporter.otlp.proto.http import (
                  trace_exporter,
              )
          else:
              raise InvalidArgument(
                  f"Invalid 'api_server.tracing.jaeger.protocol' value: {protocol}"
              ) from None
          exporter = trace_exporter.OTLPSpanExporter(
              endpoint=otlp.get("endpoint", None),
              compression=otlp.get("compression", None),
              timeout=timeout,
              **otlp[protocol],
          )
      elif tracer_type == "in_memory":
          # This will be used during testing, user shouldn't use this otherwise.
          # We won't document this in documentation.
          from opentelemetry.sdk.trace.export import (
              in_memory_span_exporter,
          )
  
          exporter = in_memory_span_exporter.InMemorySpanExporter()
      else:
          return provider
      # When exporter is set
      provider.add_span_processor(BatchSpanProcessor(exporter))
      return provider
  
imports: from __future__ import annotations
  import logging
  import math
  import os
  import typing
  import uuid
  from copy import deepcopy
  from dataclasses import dataclass
  from pathlib import Path
  from typing import TYPE_CHECKING
  import schema
  import yaml
  from deepmerge.merger import Merger
  from simple_di import Provide
  from simple_di import providers
  from ...exceptions import BentoMLConfigException
  from ..context import component_context
  from ..context import trace_context
  from ..resource import CpuResource
  from ..resource import system_resources
  from ..utils import split_with_quotes
  from ..utils import validate_or_create_dir
  from ..utils.unflatten import unflatten
  from .None import expand_env_var
  from .helpers import expand_env_var_in_values
  from .helpers import flatten_dict
  from .helpers import get_default_config
  from .helpers import import_configuration_spec
  from .helpers import load_config_file
label_desc: Use image node_id 17 for calling the _BentoMLContainerClass obj's underlying member method code with example usage: obj.tracer_provider(tracer_type, sample_rate, timeout, max_tag_value_length, zipkin, jaeger, otlp) and returns: provider, provider