Skip to content

google-cloud-pubsub Service class doesn't pass logger to v1 TopicAdmin/SubscriptionAdmin clients #32440

@Fallie

Description

@Fallie

Environment details

  • OS: macOS Tahoe
  • Ruby version: ruby 3.4.8
  • Gem name and version: google-cloud-pubsub version 3.2.0

Description:

The Google::Cloud::PubSub::Service class accepts a logger: parameter in its constructor and stores it in @logger, but does not pass this logger to the underlying v1 API clients (TopicAdmin::Client and SubscriptionAdmin::Client) when they are initialized.

Expected behavior:

The logger passed to PubSub.new should be propagated to the underlying v1 API clients so that all SDK logging respects the same logger configuration.

Steps to reproduce

  1. When creating a PubSub client with a custom logger:
rubyclient = Google::Cloud::PubSub.new(
  project_id: "my-project",
  logger: Rails.logger  # Custom logger at >=INFO level
)
  1. Publish binary data PubSub.client.publisher(binary_data) and monitor the log.
  2. Observe warning as below:

JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0
/usr/local/bundle/gems/json-2.18.1/lib/json/common.rb:443:in 'JSON::Ext::Generator::State.generate'
/usr/local/bundle/gems/json-2.18.1/lib/json/common.rb:443:in 'JSON.generate'
/usr/local/bundle/gems/google-logging-utils-0.2.0/lib/google/logging/message.rb:264:in 'Google::Logging::Message#interpret_message'
/usr/local/bundle/gems/google-logging-utils-0.2.0/lib/google/logging/message.rb:108:in 'Google::Logging::Message#initialize'
/usr/local/bundle/gems/google-logging-utils-0.2.0/lib/google/logging/message.rb:67:in 'Class#new'
/usr/local/bundle/gems/google-logging-utils-0.2.0/lib/google/logging/message.rb:67:in 'Google::Logging::Message.from'
/usr/local/bundle/gems/gapic-common-1.2.0/lib/gapic/logging_concerns.rb:132:in 'Gapic::LoggingConcerns::StubLogger::LogEntryBuilder#build'
/usr/local/bundle/gems/gapic-common-1.2.0/lib/gapic/logging_concerns.rb:56:in 'block in Gapic::LoggingConcerns::StubLogger#log'
/usr/local/bundle/gems/logger-1.7.0/lib/logger.rb:685:in 'Logger#add'
/usr/local/bundle/gems/gapic-common-1.2.0/lib/gapic/logging_concerns.rb:52:in 'Gapic::LoggingConcerns::StubLogger#log'
/usr/local/bundle/gems/gapic-common-1.2.0/lib/gapic/logging_concerns.rb:67:in 'Gapic::LoggingConcerns::StubLogger#debug'
/usr/local/bundle/gems/gapic-common-1.2.0/lib/gapic/grpc/service_stub/rpc_call.rb:213:in 'Gapic::ServiceStub::RpcCall#log_single_request'
/usr/local/bundle/gems/gapic-common-1.2.0/lib/gapic/grpc/service_stub/rpc_call.rb:206:in 'Gapic::ServiceStub::RpcCall#log_request'
/usr/local/bundle/gems/gapic-common-1.2.0/lib/gapic/grpc/service_stub/rpc_call.rb:128:in 'Gapic::ServiceStub::RpcCall#call'
/usr/local/bundle/gems/gapic-common-1.2.0/lib/gapic/grpc/service_stub.rb:217:in 'Gapic::ServiceStub#call_rpc'
/usr/local/bundle/gems/google-cloud-pubsub-v1-1.14.2/lib/google/cloud/pubsub/v1/topic_admin/client.rb:550:in 'Google::Cloud::PubSub::TopicAdmin::Client#publish'
/usr/local/bundle/gems/google-cloud-pubsub-3.2.0/lib/google/cloud/pubsub/service.rb:128:in 'Google::Cloud::PubSub::Service#publish'

The logger is stored in the Service object but is not passed to the v1 clients. As a result, the v1 clients use the default :default logger configuration, which creates a DEBUG-level logger that triggered log_single_request unexpectedly.

Source code evidence:

In lib/google/cloud/pubsub/service.rb:

def topic_admin
  return mocked_topic_admin if mocked_topic_admin
  @topic_admin ||= TopicAdmin::Client.new do |config|
    config.credentials = credentials if credentials
    override_client_config_timeouts config if timeout
    config.endpoint = host if host
    config.universe_domain = universe_domain
    config.lib_name = "gccl"
    config.lib_version = Google::Cloud::PubSub::VERSION
    config.metadata = { "google-cloud-resource-prefix": "projects/#{@project}" }
    # Missing: config.logger = @logger
  end
end

The same issue exists in the subscription_admin method.

Work Around

Currently, we are able to bypass the bug by configuring the v1 clients directly via global configuration:

# config/initializers/google_cloud.rb

require "google/cloud/pubsub/v1"

custom_logger = Logger.new($stdout)
custom_logger.level = Logger::INFO
custom_logger.progname = "google-cloud-pubsub"

Google::Cloud::PubSub::V1::TopicAdmin::Client.configure do |config|
  config.logger = custom_logger
end

Google::Cloud::PubSub::V1::SubscriptionAdmin::Client.configure do |config|
  config.logger = custom_logger
end

Proposed Fix

The topic_admin and subscription_admin methods should pass the logger to the client configuration:

def topic_admin
  return mocked_topic_admin if mocked_topic_admin
  @topic_admin ||= TopicAdmin::Client.new do |config|
    config.credentials = credentials if credentials
    override_client_config_timeouts config if timeout
    config.endpoint = host if host
    config.universe_domain = universe_domain
    config.lib_name = "gccl"
    config.lib_version = Google::Cloud::PubSub::VERSION
    config.metadata = { "google-cloud-resource-prefix": "projects/#{@project}" }
    config.logger = @logger if @logger  # ← Add this line
  end
end

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions