Skip to content

Commit 73e205a

Browse files
chore(PubSub): Implement logging with GoogleSdkLoggerDelegator
1 parent 0ab1897 commit 73e205a

File tree

16 files changed

+181
-97
lines changed

16 files changed

+181
-97
lines changed

google-cloud-pubsub-v1/.owlbot.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
OwlBot.modifier path: "lib/google/cloud/pubsub/v1/schema_service/client.rb" do |content|
16+
content.gsub! "# @return [::Logger,:default,nil]",
17+
"# @return [::Logger,::Google::Logging::GoogleSdkLoggerDelegator,:default,nil]"
18+
end
19+
OwlBot.modifier path: "lib/google/cloud/pubsub/v1/subscription_admin/client.rb" do |content|
20+
content.gsub! "# @return [::Logger,:default,nil]",
21+
"# @return [::Logger,::Google::Logging::GoogleSdkLoggerDelegator,:default,nil]"
22+
end
23+
OwlBot.modifier path: "lib/google/cloud/pubsub/v1/topic_admin/client.rb" do |content|
24+
content.gsub! "# @return [::Logger,:default,nil]",
25+
"# @return [::Logger,::Google::Logging::GoogleSdkLoggerDelegator,:default,nil]"
26+
end
27+
OwlBot.modifier path: "lib/google/cloud/pubsub/v1/schema_service/client.rb" do |content|
28+
content.gsub! "config_attr :logger, :default, ::Logger, nil, :default",
29+
"config_attr :logger, :default, [::Logger, ::Google::Logging::GoogleSdkLoggerDelegator], nil, :default"
30+
end
31+
OwlBot.modifier path: "lib/google/cloud/pubsub/v1/subscription_admin/client.rb" do |content|
32+
content.gsub! "config_attr :logger, :default, ::Logger, nil, :default",
33+
"config_attr :logger, :default, [::Logger, ::Google::Logging::GoogleSdkLoggerDelegator], nil, :default"
34+
end
35+
OwlBot.modifier path: "lib/google/cloud/pubsub/v1/topic_admin/client.rb" do |content|
36+
content.gsub! "config_attr :logger, :default, ::Logger, nil, :default",
37+
"config_attr :logger, :default, [::Logger, ::Google::Logging::GoogleSdkLoggerDelegator], nil, :default"
38+
end
39+
40+
# Add google-logging-utils as a dependency
41+
OwlBot.modifier path: "google-cloud-pubsub-v1.gemspec" do |content|
42+
content.gsub!(/
43+
end\z/, "\n gem.add_dependency \"google-logging-utils\", \"~> 0.3.0\"\nend")
44+
end
45+
46+
OwlBot.move_files

google-cloud-pubsub/Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ gem "retriable", "~> 3.1.2"
3535
gem "simplecov", "~> 0.22"
3636
gem "yard", "~> 0.9.37"
3737
gem "yard-doctest", "~> 0.1.17"
38+
gem "google-logging-utils", "~> 0.3.0"

google-cloud-pubsub/README.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,30 @@ To disable logging across all of Google Cloud Ruby SDK Gems, set the `GOOGLE_SDK
117117
export GOOGLE_SDK_RUBY_LOGGING_GEMS=pubsub
118118
```
119119

120-
You can programmatically configure a custom logger:
120+
You can programmatically configure a custom logger. The logger can be set globally for the Pub/Sub library, or provided on a per-client basis.
121+
122+
To set a logger globally, configure it on the `Google::Cloud` configuration object:
121123

122124
```ruby
123125
require "google/cloud/pubsub"
124126
require "logger"
125127

126-
# Configure a logger for the pubsub library
128+
# Configure a global logger for the pubsub library
127129
Google::Cloud.configure.pubsub.logger = Logger.new "my-app.log"
128130
```
129131

130-
If the custom logger is not configured, it will default to a standard stdout logger.
132+
Alternatively, you can provide a logger directly to the `PubSub` client initializer. If a logger instance is provided, it will override any globally configured logger.
133+
134+
```ruby
135+
require "google/cloud/pubsub"
136+
require "logger"
137+
138+
# Provide a logger directly to the client
139+
custom_logger = Logger.new "pubsub-client.log"
140+
pubsub = Google::Cloud::PubSub.new logger: custom_logger
141+
```
142+
143+
If no custom logger is configured, a default logger that writes to standard output will be used.
131144

132145

133146
## Supported Ruby Versions

google-cloud-pubsub/lib/google/cloud/pubsub.rb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515

1616
require "google-cloud-pubsub"
17+
require "google/cloud/pubsub/logging"
1718
require "google/cloud/pubsub/project"
1819
require "google/cloud/config"
1920
require "google/cloud/env"
@@ -70,11 +71,16 @@ module PubSub
7071
#
7172
# * `https://www.googleapis.com/auth/pubsub`
7273
# @param [Numeric] timeout Default timeout to use in requests. Optional.
74+
# @param [String] universe_domain A custom universe domain. Optional.
7375
# @param [String] endpoint Override of the endpoint host name. Optional.
7476
# If the param is nil, uses the default endpoint.
7577
# @param [String] emulator_host Pub/Sub emulator host. Optional.
7678
# If the param is nil, uses the value of the `emulator_host` config.
77-
# @param universe_domain [String] A custom universe domain. Optional.
79+
# @param [Logger] logger Optional Logger instance for emitting
80+
# library-level debug logs. If not provided, it will default to
81+
# configure.logger, which defaults to Logger.new STDOUT if not set. To
82+
# enable logging, set environment variable GOOGLE_SDK_RUBY_LOGGING_GEMS
83+
# to "all" or a comma separated list of gem names, including "pubsub".
7884
#
7985
# @return [Google::Cloud::PubSub::Project]
8086
#
@@ -92,13 +98,15 @@ def self.new project_id: nil,
9298
timeout: nil,
9399
universe_domain: nil,
94100
endpoint: nil,
95-
emulator_host: nil
101+
emulator_host: nil,
102+
logger: nil
96103
project_id ||= default_project_id
97104
scope ||= configure.scope
98105
timeout ||= configure.timeout
99106
endpoint ||= configure.endpoint
100107
universe_domain ||= configure.universe_domain
101108
emulator_host ||= configure.emulator_host
109+
logger ||= configure.logger
102110

103111
if emulator_host
104112
credentials = :this_channel_is_insecure
@@ -114,10 +122,12 @@ def self.new project_id: nil,
114122
project_id = project_id.to_s # Always cast to a string
115123
raise ArgumentError, "project_id is missing" if project_id.empty?
116124

125+
logging = Google::Cloud::PubSub::Logging.create logger
117126
service = PubSub::Service.new project_id, credentials,
118127
host: endpoint,
119128
timeout: timeout,
120-
universe_domain: universe_domain
129+
universe_domain: universe_domain,
130+
logging: logging
121131
PubSub::Project.new service
122132
end
123133

google-cloud-pubsub/lib/google/cloud/pubsub/async_publisher.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
require "google/cloud/pubsub/publish_result"
2222
require "google/cloud/pubsub/service"
2323
require "google/cloud/pubsub/convert"
24-
require "google/cloud/pubsub/logger_helper"
2524

2625
module Google
2726
module Cloud
@@ -60,7 +59,6 @@ module PubSub
6059
#
6160
class AsyncPublisher
6261
include MonitorMixin
63-
include Google::Cloud::PubSub::LoggerHelper
6462

6563
attr_reader :topic_name
6664
attr_reader :max_bytes
@@ -381,7 +379,7 @@ def publish_batch_sync topic_name, batch, reason: "unknown"
381379
grpc = @service.publish topic_name,
382380
items.map(&:msg),
383381
compress: compress && batch.total_message_bytes >= compression_bytes_threshold
384-
log_batch "publish-batch", reason, "publish", items.count, items.sum(&:bytesize)
382+
service.logging.log_batch "publish-batch", reason, "publish", items.count, items.sum(&:bytesize)
385383
items.zip Array(grpc.message_ids) do |item, id|
386384
@flow_controller.release item.bytesize
387385
next unless item.callback

google-cloud-pubsub/lib/google/cloud/pubsub/batch_publisher.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515

1616
require "google/cloud/pubsub/convert"
17-
require "google/cloud/pubsub/logger_helper"
1817

1918
module Google
2019
module Cloud
@@ -36,7 +35,6 @@ module PubSub
3635
# end
3736
#
3837
class BatchPublisher
39-
include Google::Cloud::PubSub::LoggerHelper
4038

4139
##
4240
# @private The messages to publish
@@ -124,7 +122,7 @@ def publish_batch_messages topic_name, service, reason: "unknown"
124122
grpc = service.publish topic_name,
125123
messages,
126124
compress: compress && total_message_bytes >= compression_bytes_threshold
127-
log_batch "publish-batch", reason, "publish", messages.count, @total_message_bytes
125+
service.logging.log_batch "publish-batch", reason, "publish", messages.count, @total_message_bytes
128126
to_gcloud_messages Array(grpc.message_ids)
129127
end
130128
end

google-cloud-pubsub/lib/google/cloud/pubsub/logger_helper.rb renamed to google-cloud-pubsub/lib/google/cloud/pubsub/logging.rb

Lines changed: 21 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,81 +12,59 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414
require "logger"
15+
require "google/logging/google_sdk_logger_delegator"
16+
require "google/cloud/config"
1517

1618
module Google
1719
module Cloud
1820
module PubSub
19-
LOG_NAME = "pubsub".freeze
20-
private_constant :LOG_NAME
21-
22-
##
23-
# The logger for the Pub/Sub library.
24-
# @return [Logger]
25-
def self.logger
26-
is_logging_enabled ? configure.logger : Logger.new(nil)
27-
end
28-
29-
##
30-
# Checks if logging is enabled for the Pub/Sub library.
31-
# @return [Boolean]
32-
def self.is_logging_enabled
33-
begin
34-
env_var = ENV["GOOGLE_SDK_RUBY_LOGGING_GEMS"]
35-
return false if (configure.logger.nil? || env_var == "none")
36-
return true if env_var == "all"
37-
# parse env var by removing whitespace and splitting by comma
38-
packages = env_var&.gsub(/\s+/, "")&.split(",") || []
39-
packages.include?(LOG_NAME)
40-
rescue StandardError => e
41-
warn "Failed to determine logging configuration. Logging disabled. Error: #{e.class}: #{e.message}"
42-
false
43-
end
44-
end
45-
4621
##
4722
# @private
48-
module LoggerHelper
23+
class Logging
24+
LOG_NAME = "pubsub".freeze
4925
VALID_LOG_LEVELS = [:debug, :info, :warn, :error, :fatal].freeze
50-
private_constant :VALID_LOG_LEVELS
26+
private_constant :VALID_LOG_LEVELS, :LOG_NAME
5127

52-
private
28+
##
29+
# @private
30+
def self.create logger
31+
new logger
32+
end
5333

5434
# rubocop:disable Naming/BlockForwarding
55-
def log_safely level, subtag, &message_block
35+
def log level, subtag, &message_block
5636
return unless VALID_LOG_LEVELS.include?(level) && block_given?
57-
begin
58-
Google::Cloud::PubSub.logger.public_send(level, "#{LOG_NAME}:#{subtag}", &message_block)
59-
rescue StandardError
60-
# Ignore all logging errors.
61-
end
37+
@logging_delegator.public_send(level, "#{LOG_NAME}:#{subtag}", &message_block)
6238
end
6339
# rubocop:enable Naming/BlockForwarding
6440

6541
def log_batch logger_name, reason, type, num_messages, total_bytes
66-
log_safely :info, logger_name do
42+
log :info, logger_name do
6743
"#{reason} triggered #{type} batch of #{num_messages} messages, a total of #{total_bytes} bytes"
6844
end
6945
end
7046

7147
def log_ack_nack ack_ids, type
72-
# exit early to avoid unnecessary loop
73-
return unless Google::Cloud::PubSub.is_logging_enabled
7448
ack_ids.each do |ack_id|
75-
log_safely :info, "ack-nack" do
49+
log :info, "ack-nack" do
7650
"message (ackID #{ack_id}) #{type}"
7751
end
7852
end
7953
end
8054

8155
def log_expiry expired
82-
# exit early to avoid unnecessary loop
83-
return unless Google::Cloud::PubSub.is_logging_enabled
8456
expired.each do |ack_id, item|
85-
log_safely :info, "expiry" do
57+
log :info, "expiry" do
8658
"message (ID #{item.message_id}, ackID #{ack_id}) has been dropped from leasing due to a timeout"
8759
end
8860
end
8961
end
62+
63+
private
64+
65+
def initialize logger
66+
@logging_delegator = Google::Logging::GoogleSdkLoggerDelegator.new LOG_NAME, logger
67+
end
9068
end
9169
end
9270
end

google-cloud-pubsub/lib/google/cloud/pubsub/message_listener/inventory.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
require "google/cloud/pubsub/logger_helper"
1615
require "monitor"
1716

1817
module Google
@@ -29,7 +28,6 @@ def self.from rec_msg
2928
end
3029

3130
include MonitorMixin
32-
include LoggerHelper
3331

3432
attr_reader :stream
3533
attr_reader :limit
@@ -88,7 +86,7 @@ def remove_expired!
8886
extension_time = Time.new - extension
8987
expired, keep = @inventory.partition { |_ack_id, item| item.pulled_at < extension_time }
9088
@inventory = keep.to_h
91-
log_expiry expired
89+
stream.subscriber.service.logging.log_expiry expired
9290
@wait_cond.broadcast
9391
end
9492
end

0 commit comments

Comments
 (0)