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
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions