diff --git a/pdm.lock b/pdm.lock index 5f5f900bb4c..911458afc43 100644 --- a/pdm.lock +++ b/pdm.lock @@ -2,10 +2,10 @@ # It is not intended for manual editing. [metadata] -groups = ["default", "all", "testing", "io", "grpc-channelz", "tracing-otlp", "monitor-otlp", "io-image", "aws", "docs", "tracing-zipkin", "grpc-reflection", "grpc", "tracing", "tooling", "tracing-jaeger", "io-pandas", "triton"] +groups = ["default", "all", "testing", "io", "grpc-channelz", "tracing-otlp", "monitor-otlp", "io-image", "aws", "docs", "tracing-zipkin", "grpc-reflection", "grpc", "tracing", "tooling", "tracing-jaeger", "io-pandas", "triton", "opentelemetry-exporter-otlp-proto-grpc==1.20.0"] strategy = ["cross_platform", "inherit_metadata"] lock_version = "4.4.1" -content_hash = "sha256:094ecc034f5068cd96766a5f5c6397d7de93b148a520a8278ab6edea661ab2a2" +content_hash = "sha256:b24e49033b37d472b6ccee324e811bb67172d2a9f756a12f81e6963e9bfe1646" [[package]] name = "aiohttp" @@ -1391,7 +1391,7 @@ name = "grpcio" version = "1.59.0" requires_python = ">=3.7" summary = "HTTP/2-based RPC framework" -groups = ["all", "docs", "grpc", "grpc-channelz", "grpc-reflection", "tracing", "tracing-jaeger", "tracing-otlp", "triton"] +groups = ["all", "docs", "grpc", "grpc-channelz", "grpc-reflection", "monitor-otlp", "tracing", "tracing-jaeger", "tracing-otlp", "triton"] files = [ {file = "grpcio-1.59.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:225e5fa61c35eeaebb4e7491cd2d768cd8eb6ed00f2664fa83a58f29418b39fd"}, {file = "grpcio-1.59.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:b95ec8ecc4f703f5caaa8d96e93e40c7f589bad299a2617bdb8becbcce525539"}, @@ -2298,7 +2298,7 @@ name = "opentelemetry-exporter-otlp-proto-grpc" version = "1.20.0" requires_python = ">=3.7" summary = "OpenTelemetry Collector Protobuf over gRPC Exporter" -groups = ["all", "tracing", "tracing-otlp"] +groups = ["all", "monitor-otlp", "tracing", "tracing-otlp"] dependencies = [ "backoff<3.0.0,>=1.10.0; python_version >= \"3.7\"", "deprecated>=1.2.6", diff --git a/pyproject.toml b/pyproject.toml index 37eafdc5b54..7cf556fde84 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -108,7 +108,10 @@ tracing = [ tracing-jaeger = ["opentelemetry-exporter-jaeger==1.20.0"] tracing-zipkin = ["opentelemetry-exporter-zipkin==1.20.0"] tracing-otlp = ["opentelemetry-exporter-otlp==1.20.0"] -monitor-otlp = ["opentelemetry-exporter-otlp-proto-http==1.20.0"] +monitor-otlp = [ + "opentelemetry-exporter-otlp-proto-http==1.20.0", + "opentelemetry-exporter-otlp-proto-grpc==1.20.0", +] [build-system] requires = ['hatchling', "hatch-vcs>=0.3.0"] diff --git a/src/bentoml/_internal/monitoring/otlp.py b/src/bentoml/_internal/monitoring/otlp.py index 4db36836c18..8f1ca032157 100644 --- a/src/bentoml/_internal/monitoring/otlp.py +++ b/src/bentoml/_internal/monitoring/otlp.py @@ -27,7 +27,12 @@ from .base import MonitorBase try: - from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter + from opentelemetry.exporter.otlp.proto.grpc._log_exporter import ( + OTLPLogExporter as OTLPGrpcLogExporter, + ) + from opentelemetry.exporter.otlp.proto.http._log_exporter import ( + OTLPLogExporter as OTLPHttpLogExporter, + ) except ImportError: raise MissingDependencyException( "'opentelemetry-exporter-otlp' is required to use OTLP exporter. Make sure to install it with 'pip install \"bentoml[monitor-otlp]\"" @@ -106,6 +111,7 @@ def __init__( timeout: int | str | None = None, compression: str | None = None, meta_sample_rate: float = 1.0, + protocol: t.Literal["http", "grpc"] = "http", **_: t.Any, ) -> None: """ @@ -119,6 +125,7 @@ def __init__( headers: The headers to use. timeout: The timeout to use. compression: The compression to use. + protocol: The protocol to use. """ super().__init__(name, **_) @@ -135,6 +142,8 @@ def __init__( self._schema: dict[str, dict[str, str]] = {} self._will_export_schema = False + self.protocol = protocol + def _init_logger(self) -> None: from opentelemetry.sdk.resources import SERVICE_INSTANCE_ID from opentelemetry.sdk.resources import SERVICE_NAME @@ -169,7 +178,27 @@ def _init_logger(self) -> None: if self.compression is not None: os.environ[OTEL_EXPORTER_OTLP_COMPRESSION] = self.compression - exporter = OTLPLogExporter() + exporter: OTLPHttpLogExporter | OTLPGrpcLogExporter + if self.protocol == "http": + exporter = OTLPHttpLogExporter( + endpoint=self.endpoint, + certificate_file=self.credentials, + headers=self.headers, + timeout=self.timeout, + compression=self.compression, + ) + elif self.protocol == "grpc": + exporter = OTLPGrpcLogExporter( + endpoint=self.endpoint, + insecure=self.insecure, + credentials=self.credentials, + headers=self.headers, + timeout=self.timeout, + compression=self.compression, + ) + else: + raise ValueError(f"Invalid protocol: {self.protocol}") + self.logger_provider.add_log_record_processor(BatchLogRecordProcessor(exporter)) handler = LoggingHandler( level=logging.NOTSET, logger_provider=self.logger_provider