fluent-plugin-gcloud-pubsub-custom-subscriber 1.3.2 → 1.3.3Z
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +3 -4
- data/CHANGELOG.md +0 -28
- data/README.md +12 -19
- data/fluent-plugin-gcloud-pubsub-custom.gemspec +14 -11
- data/lib/fluent/plugin/gcloud_pubsub/client.rb +21 -40
- data/lib/fluent/plugin/in_gcloud_pubsub.rb +4 -9
- data/lib/fluent/plugin/out_gcloud_pubsub.rb +18 -22
- data/test/plugin/test_in_gcloud_pubsub.rb +14 -37
- data/test/plugin/test_out_gcloud_pubsub.rb +70 -51
- metadata +45 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d98636b923d8f1e55b85770bf3c950590c994edea4e0232851ae843503a0a84
|
4
|
+
data.tar.gz: d9610eab7e90766acdcd9a19860e192e4b18240fc9f11ca789d532efa39c1827
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57fce3fcc4d9d76e5df6b48563e1145c7313b9e3240fdc832ed2b53d04a29650b36fb3bf88db26b78e0369acfe5721f2cfd6b4bf4f9b2fffc8daa1043956e7a3
|
7
|
+
data.tar.gz: e846defa23a5de13179171221a4b124a3059ce9c5230e38cd184454626c4000ffd0c1e0f92f472393fec5f992b81de172056d23e9c8fce4e2719778993f29565
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,33 +1,5 @@
|
|
1
1
|
## ChangeLog
|
2
2
|
|
3
|
-
### Release 1.3.1 - 2018/06/08
|
4
|
-
|
5
|
-
- Input plugin
|
6
|
-
- Dumps raw string to logs for parsing errors
|
7
|
-
|
8
|
-
### Release 1.3.0 - 2018/05/18
|
9
|
-
|
10
|
-
- Make attributes available
|
11
|
-
|
12
|
-
### Release 1.2.0 - 2018/04/24
|
13
|
-
|
14
|
-
- Output plugin
|
15
|
-
- Support inject section
|
16
|
-
|
17
|
-
### Release 1.1.0 - 2018/03/30
|
18
|
-
|
19
|
-
- Output plugin
|
20
|
-
- The placeholder is now available in topic param
|
21
|
-
|
22
|
-
### Release 1.0.3 - 2018/03/29
|
23
|
-
|
24
|
-
- Bump up google-cloud-pubsub to v0.30.x
|
25
|
-
- Make config file Fluentd v1 compatible
|
26
|
-
|
27
|
-
### Release 1.0.2 - 2017/09/11
|
28
|
-
|
29
|
-
- Bump up google-cloud-pubsub to v0.27.x
|
30
|
-
|
31
3
|
### Release 1.0.1 - 2017/09/05
|
32
4
|
|
33
5
|
- Bump up google-cloud-pubsub to v0.26.x
|
data/README.md
CHANGED
@@ -19,10 +19,6 @@ This plugin is forked from https://github.com/mdoi/fluent-plugin-gcloud-pubsub
|
|
19
19
|
- Add a pull style subscription to the topic
|
20
20
|
- Download your credential (json) or [set scope on GCE instance](https://cloud.google.com/compute/docs/api/how-tos/authorization)
|
21
21
|
|
22
|
-
When using output plugin, you need to grant Pub/Sub Publisher and Pub/Sub Viewer role to IAM.
|
23
|
-
|
24
|
-
Also, when using input plugin, you need to grant Pub/Sub Subscriber and Pub/Sub Viewer role to IAM.
|
25
|
-
|
26
22
|
## Requirements
|
27
23
|
|
28
24
|
| fluent-plugin-gcloud-pubsub-custom | fluentd | ruby |
|
@@ -60,13 +56,11 @@ Use `gcloud_pubsub` output plugin.
|
|
60
56
|
max_messages 1000
|
61
57
|
max_total_size 9800000
|
62
58
|
max_message_size 4000000
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
@type json
|
69
|
-
</format>
|
59
|
+
buffer_type file
|
60
|
+
buffer_path /path/to/your/buffer
|
61
|
+
flush_interval 1s
|
62
|
+
try_flush_interval 0.1
|
63
|
+
format json
|
70
64
|
</match>
|
71
65
|
```
|
72
66
|
|
@@ -80,7 +74,6 @@ Use `gcloud_pubsub` output plugin.
|
|
80
74
|
- You can also use environment variable such as `GCLOUD_KEYFILE`.
|
81
75
|
- `topic` (required)
|
82
76
|
- Set topic name to publish.
|
83
|
-
- You can use placeholder in this param. See: https://docs.fluentd.org/v1.0/articles/buffer-section
|
84
77
|
- `autocreate_topic` (optional, default: `false`)
|
85
78
|
- If set to `true`, specified topic will be created when it doesn't exist.
|
86
79
|
- `max_messages` (optional, default: `1000`)
|
@@ -91,8 +84,10 @@ Use `gcloud_pubsub` output plugin.
|
|
91
84
|
- See https://cloud.google.com/pubsub/quotas#other_limits
|
92
85
|
- `max_message_size` (optional, default: `4000000` = `4MB`)
|
93
86
|
- Messages exceeding `max_message_size` are not published because Pub/Sub clients cannot receive it.
|
94
|
-
- `
|
95
|
-
-
|
87
|
+
- `buffer_type`, `buffer_path`, `flush_interval`, `try_flush_interval`
|
88
|
+
- These are fluentd buffer configuration. See http://docs.fluentd.org/articles/buffer-plugin-overview
|
89
|
+
- `format` (optional, default: `json`)
|
90
|
+
- Set output format. See http://docs.fluentd.org/articles/out_file#format
|
96
91
|
|
97
92
|
### Pull messages
|
98
93
|
|
@@ -110,13 +105,11 @@ Use `gcloud_pubsub` input plugin.
|
|
110
105
|
return_immediately true
|
111
106
|
pull_interval 0.5
|
112
107
|
pull_threads 2
|
108
|
+
format json
|
113
109
|
parse_error_action exception
|
114
110
|
enable_rpc true
|
115
111
|
rpc_bind 0.0.0.0
|
116
112
|
rpc_port 24680
|
117
|
-
<parse>
|
118
|
-
@type json
|
119
|
-
</parse>
|
120
113
|
</source>
|
121
114
|
```
|
122
115
|
|
@@ -146,8 +139,8 @@ Use `gcloud_pubsub` input plugin.
|
|
146
139
|
- Pulling messages by intervals of specified seconds.
|
147
140
|
- `pull_threads` (optional, default: `1`)
|
148
141
|
- Set number of threads to pull messages.
|
149
|
-
- `
|
150
|
-
-
|
142
|
+
- `format` (optional, default: `json`)
|
143
|
+
- Set input format. See format section in http://docs.fluentd.org/articles/in_tail
|
151
144
|
- `parse_error_action` (optional, default: `exception`)
|
152
145
|
- Set error type when parsing messages fails.
|
153
146
|
- `exception`: Raise exception. Messages are not acknowledged.
|
@@ -3,12 +3,11 @@ $:.push File.expand_path('../lib', __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.name = "fluent-plugin-gcloud-pubsub-custom-subscriber"
|
6
|
-
gem.description = "Google Cloud Pub/Sub input/output plugin for Fluentd event collector without auto-create topic requiring only Pub/Sub subscriber ACL"
|
7
6
|
gem.license = "MIT"
|
8
|
-
gem.
|
9
|
-
gem.summary =
|
10
|
-
gem.version = "1.3.
|
11
|
-
gem.authors = ["Yoshihiro MIYAI"]
|
7
|
+
gem.description = "Google Cloud Pub/Sub input/output plugin for Fluentd event collector without auto-create topic requiring only Pub/Sub subscriber ACL"
|
8
|
+
gem.summary = "Google Cloud Pub/Sub input/output plugin for Fluentd event collector"
|
9
|
+
gem.version = "1.3.3Z"
|
10
|
+
gem.authors = ["Yoshihiro MIYAI", "mjchuable"]
|
12
11
|
gem.email = "msparrow17@gmail.com"
|
13
12
|
gem.has_rdoc = false
|
14
13
|
gem.files = `git ls-files`.split("\n")
|
@@ -16,11 +15,15 @@ Gem::Specification.new do |gem|
|
|
16
15
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
16
|
gem.require_paths = ['lib']
|
18
17
|
|
19
|
-
|
20
|
-
|
18
|
+
# fluentd version matrix against td-agent
|
19
|
+
# https://support.treasuredata.com/hc/en-us/articles/360001479187-The-td-agent-ChangeLog
|
20
|
+
gem.add_runtime_dependency "fluentd", "0.14.25" # for td-agent v3.1.0
|
21
|
+
|
22
|
+
gem.add_runtime_dependency "google-cloud-pubsub", "0.30.2"
|
23
|
+
gem.add_runtime_dependency "retryable", "2.0.4"
|
21
24
|
|
22
|
-
gem.add_development_dependency "bundler"
|
23
|
-
gem.add_development_dependency "rake"
|
24
|
-
gem.add_development_dependency "test-unit"
|
25
|
-
gem.add_development_dependency "test-unit-rr"
|
25
|
+
gem.add_development_dependency "bundler", "1.16.6"
|
26
|
+
gem.add_development_dependency "rake", "12.1.0"
|
27
|
+
gem.add_development_dependency "test-unit", "3.2.5"
|
28
|
+
gem.add_development_dependency "test-unit-rr", "1.0.5"
|
26
29
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'google/cloud/pubsub'
|
2
|
+
require 'retryable'
|
2
3
|
|
3
4
|
module Fluent
|
4
5
|
module GcloudPubSub
|
@@ -7,48 +8,23 @@ module Fluent
|
|
7
8
|
class RetryableError < Error
|
8
9
|
end
|
9
10
|
|
10
|
-
class Message
|
11
|
-
attr_reader :message, :attributes
|
12
|
-
def initialize(message, attributes={})
|
13
|
-
@message = message
|
14
|
-
@attributes = attributes
|
15
|
-
end
|
16
|
-
|
17
|
-
def bytesize()
|
18
|
-
attr_size = 0
|
19
|
-
@attributes.each do |key, val|
|
20
|
-
attr_size += key.bytesize + val.bytesize
|
21
|
-
end
|
22
|
-
@message.bytesize + attr_size
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
11
|
class Publisher
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
client = @pubsub.topic topic_name
|
37
|
-
if client.nil? && @autocreate_topic
|
38
|
-
client = @pubsub.create_topic topic_name
|
39
|
-
end
|
40
|
-
if client.nil?
|
41
|
-
raise Error.new "topic:#{topic_name} does not exist."
|
12
|
+
RETRY_COUNT = 5
|
13
|
+
RETRYABLE_ERRORS = [Google::Cloud::UnavailableError, Google::Cloud::DeadlineExceededError, Google::Cloud::InternalError]
|
14
|
+
|
15
|
+
# autocreate_topic is unused
|
16
|
+
def initialize(project, key, topic_name, skip_lookup)
|
17
|
+
Retryable.retryable(tries: RETRY_COUNT, on: RETRYABLE_ERRORS) do
|
18
|
+
pubsub = Google::Cloud::Pubsub.new project: project, keyfile: key
|
19
|
+
@client = pubsub.topic topic_name, skip_lookup: skip_lookup
|
42
20
|
end
|
43
|
-
|
44
|
-
@topics[topic_name] = client
|
45
|
-
client
|
21
|
+
raise Error.new "topic:#{topic_name} does not exist." if @client.nil?
|
46
22
|
end
|
47
23
|
|
48
|
-
def publish(
|
49
|
-
|
24
|
+
def publish(messages)
|
25
|
+
@client.publish do |batch|
|
50
26
|
messages.each do |m|
|
51
|
-
batch.publish m
|
27
|
+
batch.publish m
|
52
28
|
end
|
53
29
|
end
|
54
30
|
rescue Google::Cloud::UnavailableError, Google::Cloud::DeadlineExceededError, Google::Cloud::InternalError => ex
|
@@ -57,10 +33,15 @@ module Fluent
|
|
57
33
|
end
|
58
34
|
|
59
35
|
class Subscriber
|
36
|
+
RETRY_COUNT = 5
|
37
|
+
RETRYABLE_ERRORS = [Google::Cloud::UnavailableError, Google::Cloud::DeadlineExceededError, Google::Cloud::InternalError]
|
38
|
+
|
60
39
|
def initialize(project, key, topic_name, subscription_name)
|
61
|
-
|
62
|
-
|
63
|
-
|
40
|
+
Retryable.retryable(tries: RETRY_COUNT, on: RETRYABLE_ERRORS) do
|
41
|
+
pubsub = Google::Cloud::Pubsub.new project: project, keyfile: key
|
42
|
+
topic = pubsub.topic topic_name
|
43
|
+
@client = topic.subscription subscription_name
|
44
|
+
end
|
64
45
|
raise Error.new "subscription:#{subscription_name} does not exist." if @client.nil?
|
65
46
|
end
|
66
47
|
|
@@ -37,8 +37,8 @@ module Fluent::Plugin
|
|
37
37
|
config_param :return_immediately, :bool, default: true
|
38
38
|
desc 'Set number of threads to pull messages.'
|
39
39
|
config_param :pull_threads, :integer, default: 1
|
40
|
-
desc '
|
41
|
-
config_param :
|
40
|
+
desc 'Set input format.'
|
41
|
+
config_param :format, :string, default: DEFAULT_PARSER_TYPE
|
42
42
|
desc 'Set error type when parsing messages fails.'
|
43
43
|
config_param :parse_error_action, :enum, default: :exception, list: [:exception, :warning]
|
44
44
|
# for HTTP RPC
|
@@ -222,20 +222,15 @@ module Fluent::Plugin
|
|
222
222
|
|
223
223
|
messages.each do |m|
|
224
224
|
line = m.message.data.chomp
|
225
|
-
attributes = m.attributes
|
226
225
|
@parser.parse(line) do |time, record|
|
227
226
|
if time && record
|
228
|
-
@attribute_keys.each do |key|
|
229
|
-
record[key] = attributes[key]
|
230
|
-
end
|
231
|
-
|
232
227
|
event_streams[@extract_tag.call(record)].add(time, record)
|
233
228
|
else
|
234
229
|
case @parse_error_action
|
235
230
|
when :exception
|
236
|
-
raise FailedParseError.new "pattern not match: #{line}"
|
231
|
+
raise FailedParseError.new "pattern not match: #{line.inspect}"
|
237
232
|
else
|
238
|
-
log.warn 'pattern not match', record: line
|
233
|
+
log.warn 'pattern not match', record: line.inspect
|
239
234
|
end
|
240
235
|
end
|
241
236
|
end
|
@@ -1,11 +1,9 @@
|
|
1
1
|
require 'fluent/plugin/output'
|
2
|
+
|
2
3
|
require 'fluent/plugin/gcloud_pubsub/client'
|
3
|
-
require 'fluent/plugin_helper/inject'
|
4
4
|
|
5
5
|
module Fluent::Plugin
|
6
6
|
class GcloudPubSubOutput < Output
|
7
|
-
include Fluent::PluginHelper::Inject
|
8
|
-
|
9
7
|
Fluent::Plugin.register_output('gcloud_pubsub', self)
|
10
8
|
|
11
9
|
helpers :compat_parameters, :formatter
|
@@ -21,14 +19,16 @@ module Fluent::Plugin
|
|
21
19
|
config_param :topic, :string
|
22
20
|
desc "If set to `true`, specified topic will be created when it doesn't exist."
|
23
21
|
config_param :autocreate_topic, :bool, :default => false
|
22
|
+
desc "Custom param - skips topic retrieval; service accounts can just solely have PubSub Publishing roles when set to true"
|
23
|
+
config_param :skip_lookup, :bool, :default => true
|
24
24
|
desc 'Publishing messages count per request to Cloud Pub/Sub.'
|
25
25
|
config_param :max_messages, :integer, :default => 1000
|
26
26
|
desc 'Publishing messages bytesize per request to Cloud Pub/Sub.'
|
27
27
|
config_param :max_total_size, :integer, :default => 9800000 # 9.8MB
|
28
28
|
desc 'Limit bytesize per message.'
|
29
29
|
config_param :max_message_size, :integer, :default => 4000000 # 4MB
|
30
|
-
desc '
|
31
|
-
config_param :
|
30
|
+
desc 'Set output format.'
|
31
|
+
config_param :format, :string, :default => 'json'
|
32
32
|
|
33
33
|
config_section :buffer do
|
34
34
|
config_set_default :@type, DEFAULT_BUFFER_TYPE
|
@@ -41,22 +41,17 @@ module Fluent::Plugin
|
|
41
41
|
def configure(conf)
|
42
42
|
compat_parameters_convert(conf, :buffer, :formatter)
|
43
43
|
super
|
44
|
-
placeholder_validate!(:topic, @topic)
|
45
44
|
@formatter = formatter_create
|
46
45
|
end
|
47
46
|
|
48
47
|
def start
|
49
48
|
super
|
50
|
-
@publisher = Fluent::GcloudPubSub::Publisher.new @project, @key, @
|
49
|
+
@publisher = Fluent::GcloudPubSub::Publisher.new @project, @key, @topic, @skip_lookup
|
50
|
+
log.debug "connected topic:#{@topic} in project #{@project}"
|
51
51
|
end
|
52
52
|
|
53
53
|
def format(tag, time, record)
|
54
|
-
|
55
|
-
attributes = {}
|
56
|
-
@attribute_keys.each do |key|
|
57
|
-
attributes[key] = record.delete(key)
|
58
|
-
end
|
59
|
-
[@formatter.format(tag, time, record), attributes].to_msgpack
|
54
|
+
@formatter.format(tag, time, record).to_msgpack
|
60
55
|
end
|
61
56
|
|
62
57
|
def formatted_to_msgpack_binary?
|
@@ -68,19 +63,16 @@ module Fluent::Plugin
|
|
68
63
|
end
|
69
64
|
|
70
65
|
def write(chunk)
|
71
|
-
topic = extract_placeholders(@topic, chunk.metadata)
|
72
|
-
|
73
66
|
messages = []
|
74
67
|
size = 0
|
75
68
|
|
76
|
-
chunk.msgpack_each do |msg
|
77
|
-
msg = Fluent::GcloudPubSub::Message.new(msg, attr)
|
69
|
+
chunk.msgpack_each do |msg|
|
78
70
|
if msg.bytesize > @max_message_size
|
79
71
|
log.warn 'Drop a message because its size exceeds `max_message_size`', size: msg.bytesize
|
80
72
|
next
|
81
73
|
end
|
82
74
|
if messages.length + 1 > @max_messages || size + msg.bytesize > @max_total_size
|
83
|
-
publish
|
75
|
+
publish messages
|
84
76
|
messages = []
|
85
77
|
size = 0
|
86
78
|
end
|
@@ -89,11 +81,15 @@ module Fluent::Plugin
|
|
89
81
|
end
|
90
82
|
|
91
83
|
if messages.length > 0
|
92
|
-
publish
|
84
|
+
publish messages
|
93
85
|
end
|
94
86
|
rescue Fluent::GcloudPubSub::RetryableError => ex
|
95
87
|
log.warn "Retryable error occurs. Fluentd will retry.", error_message: ex.to_s, error_class: ex.class.to_s
|
96
88
|
raise ex
|
89
|
+
rescue Google::Cloud::UnauthenticatedError => ex
|
90
|
+
log.warn "Encountered UnauthenticatedError, renewing @publisher instance", error_message: ex.to_s, error_class: ex.class.to_s
|
91
|
+
@publisher = Fluent::GcloudPubSub::Publisher.new @project, @key, @topic, @skip_lookup
|
92
|
+
raise ex
|
97
93
|
rescue => ex
|
98
94
|
log.error "unexpected error", error_message: ex.to_s, error_class: ex.class.to_s
|
99
95
|
log.error_backtrace
|
@@ -102,9 +98,9 @@ module Fluent::Plugin
|
|
102
98
|
|
103
99
|
private
|
104
100
|
|
105
|
-
def publish(
|
106
|
-
log.debug "send message topic:#{topic} length:#{messages.length} size:#{messages.map(&:bytesize).inject(:+)}"
|
107
|
-
@publisher.publish
|
101
|
+
def publish(messages)
|
102
|
+
log.debug "send message topic:#{@topic} length:#{messages.length} size:#{messages.map(&:bytesize).inject(:+)}"
|
103
|
+
@publisher.publish messages
|
108
104
|
end
|
109
105
|
end
|
110
106
|
end
|
@@ -11,6 +11,8 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
11
11
|
topic topic-test
|
12
12
|
subscription subscription-test
|
13
13
|
key key-test
|
14
|
+
format json
|
15
|
+
json_parser yajl
|
14
16
|
]
|
15
17
|
|
16
18
|
DEFAULT_HOST = '127.0.0.1'
|
@@ -18,16 +20,13 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
18
20
|
|
19
21
|
class DummyInvalidMsgData
|
20
22
|
def data
|
21
|
-
'foo:bar'
|
23
|
+
return 'foo:bar'
|
22
24
|
end
|
23
25
|
end
|
24
26
|
class DummyInvalidMessage
|
25
27
|
def message
|
26
28
|
DummyInvalidMsgData.new
|
27
29
|
end
|
28
|
-
def attributes
|
29
|
-
{"attr_1" => "a", "attr_2" => "b"}
|
30
|
-
end
|
31
30
|
end
|
32
31
|
|
33
32
|
def create_driver(conf=CONFIG)
|
@@ -56,7 +55,7 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
56
55
|
return_immediately true
|
57
56
|
pull_interval 2
|
58
57
|
pull_threads 3
|
59
|
-
|
58
|
+
format ltsv
|
60
59
|
enable_rpc true
|
61
60
|
rpc_bind 127.0.0.1
|
62
61
|
rpc_port 24681
|
@@ -71,7 +70,7 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
71
70
|
assert_equal(1000, d.instance.max_messages)
|
72
71
|
assert_equal(true, d.instance.return_immediately)
|
73
72
|
assert_equal(3, d.instance.pull_threads)
|
74
|
-
assert_equal(
|
73
|
+
assert_equal('ltsv', d.instance.format)
|
75
74
|
assert_equal(true, d.instance.enable_rpc)
|
76
75
|
assert_equal('127.0.0.1', d.instance.rpc_bind)
|
77
76
|
assert_equal(24681, d.instance.rpc_port)
|
@@ -83,7 +82,7 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
83
82
|
assert_equal(100, d.instance.max_messages)
|
84
83
|
assert_equal(true, d.instance.return_immediately)
|
85
84
|
assert_equal(1, d.instance.pull_threads)
|
86
|
-
assert_equal(
|
85
|
+
assert_equal('json', d.instance.format)
|
87
86
|
assert_equal(false, d.instance.enable_rpc)
|
88
87
|
assert_equal('0.0.0.0', d.instance.rpc_bind)
|
89
88
|
assert_equal(24680, d.instance.rpc_port)
|
@@ -109,7 +108,7 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
109
108
|
end
|
110
109
|
|
111
110
|
test '50x error occurred on connecting to Pub/Sub' do
|
112
|
-
@topic_mock.subscription('subscription-test').
|
111
|
+
@topic_mock.subscription('subscription-test').times(5) do
|
113
112
|
raise Google::Cloud::UnavailableError.new('TEST')
|
114
113
|
end
|
115
114
|
|
@@ -132,16 +131,13 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
132
131
|
sub_test_case 'emit' do
|
133
132
|
class DummyMsgData
|
134
133
|
def data
|
135
|
-
'{"foo": "bar"}'
|
134
|
+
return '{"foo": "bar"}'
|
136
135
|
end
|
137
136
|
end
|
138
137
|
class DummyMessage
|
139
138
|
def message
|
140
139
|
DummyMsgData.new
|
141
140
|
end
|
142
|
-
def attributes
|
143
|
-
{"attr_1" => "a", "attr_2" => "b"}
|
144
|
-
end
|
145
141
|
end
|
146
142
|
|
147
143
|
class DummyMsgDataWithTagKey
|
@@ -149,7 +145,7 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
149
145
|
@tag = tag
|
150
146
|
end
|
151
147
|
def data
|
152
|
-
'{"foo": "bar", "test_tag_key": "' + @tag + '"}'
|
148
|
+
return '{"foo": "bar", "test_tag_key": "' + @tag + '"}'
|
153
149
|
end
|
154
150
|
end
|
155
151
|
class DummyMessageWithTagKey
|
@@ -159,9 +155,6 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
159
155
|
def message
|
160
156
|
DummyMsgDataWithTagKey.new @tag
|
161
157
|
end
|
162
|
-
def attributes
|
163
|
-
{"attr_1" => "a", "attr_2" => "b"}
|
164
|
-
end
|
165
158
|
end
|
166
159
|
|
167
160
|
setup do
|
@@ -184,13 +177,13 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
184
177
|
test 'simple' do
|
185
178
|
messages = Array.new(1, DummyMessage.new)
|
186
179
|
@subscriber.pull(immediate: true, max: 100).at_least(1) { messages }
|
187
|
-
@subscriber.acknowledge(messages).
|
180
|
+
@subscriber.acknowledge(messages).once
|
188
181
|
|
189
182
|
d = create_driver
|
190
183
|
d.run(expect_emits: 1, timeout: 3)
|
191
184
|
emits = d.events
|
192
185
|
|
193
|
-
|
186
|
+
assert_equal(1, emits.length)
|
194
187
|
emits.each do |tag, time, record|
|
195
188
|
assert_equal("test", tag)
|
196
189
|
assert_equal({"foo" => "bar"}, record)
|
@@ -220,13 +213,13 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
220
213
|
DummyMessage.new
|
221
214
|
]
|
222
215
|
@subscriber.pull(immediate: true, max: 100).at_least(1) { messages }
|
223
|
-
@subscriber.acknowledge(messages).
|
216
|
+
@subscriber.acknowledge(messages).once
|
224
217
|
|
225
218
|
d = create_driver("#{CONFIG}\ntag_key test_tag_key")
|
226
219
|
d.run(expect_emits: 1, timeout: 3)
|
227
220
|
emits = d.events
|
228
221
|
|
229
|
-
|
222
|
+
assert_equal(3, emits.length)
|
230
223
|
# test tag
|
231
224
|
assert_equal("tag1", emits[0][0])
|
232
225
|
assert_equal("tag2", emits[1][0])
|
@@ -247,22 +240,6 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
247
240
|
assert_true d.events.empty?
|
248
241
|
end
|
249
242
|
|
250
|
-
test 'with attributes' do
|
251
|
-
messages = Array.new(1, DummyMessage.new)
|
252
|
-
@subscriber.pull(immediate: true, max: 100).at_least(1) { messages }
|
253
|
-
@subscriber.acknowledge(messages).at_least(1)
|
254
|
-
|
255
|
-
d = create_driver("#{CONFIG}\nattribute_keys attr_1")
|
256
|
-
d.run(expect_emits: 1, timeout: 3)
|
257
|
-
emits = d.events
|
258
|
-
|
259
|
-
assert(1 <= emits.length)
|
260
|
-
emits.each do |tag, time, record|
|
261
|
-
assert_equal("test", tag)
|
262
|
-
assert_equal({"foo" => "bar", "attr_1" => "a"}, record)
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
243
|
test 'invalid messages with parse_error_action warning' do
|
267
244
|
messages = Array.new(1, DummyInvalidMessage.new)
|
268
245
|
@subscriber.pull(immediate: true, max: 100).at_least(1) { messages }
|
@@ -300,7 +277,7 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
|
|
300
277
|
test 'retry if raised RetryableError on acknowledge' do
|
301
278
|
messages = Array.new(1, DummyMessage.new)
|
302
279
|
@subscriber.pull(immediate: true, max: 100).at_least(2) { messages }
|
303
|
-
@subscriber.acknowledge(messages).
|
280
|
+
@subscriber.acknowledge(messages).twice { raise Google::Cloud::UnavailableError.new('TEST') }
|
304
281
|
|
305
282
|
d = create_driver("#{CONFIG}\npull_interval 0.5")
|
306
283
|
d.run(expect_emits: 2, timeout: 3)
|
@@ -22,10 +22,6 @@ class GcloudPubSubOutputTest < Test::Unit::TestCase
|
|
22
22
|
Fluent::Test.setup
|
23
23
|
end
|
24
24
|
|
25
|
-
setup do
|
26
|
-
@time = event_time('2016-07-09 11:12:13 UTC')
|
27
|
-
end
|
28
|
-
|
29
25
|
sub_test_case 'configure' do
|
30
26
|
test 'default values are configured' do
|
31
27
|
d = create_driver(%[
|
@@ -79,65 +75,41 @@ class GcloudPubSubOutputTest < Test::Unit::TestCase
|
|
79
75
|
autocreate_topic true
|
80
76
|
])
|
81
77
|
|
82
|
-
@
|
83
|
-
|
84
|
-
@pubsub_mock.create_topic("topic-test").once { @publisher }
|
85
|
-
d.run(default_tag: "test") do
|
86
|
-
d.feed(@time, {"a" => "b"})
|
87
|
-
end
|
78
|
+
@pubsub_mock.topic("topic-test", skip_lookup: true).once { @publisher }
|
79
|
+
d.run
|
88
80
|
end
|
89
81
|
|
90
82
|
test '40x error occurred on connecting to Pub/Sub' do
|
91
83
|
d = create_driver
|
92
84
|
|
93
|
-
@pubsub_mock.topic('topic-test').once do
|
85
|
+
@pubsub_mock.topic('topic-test', skip_lookup: true).once do
|
94
86
|
raise Google::Cloud::NotFoundError.new('TEST')
|
95
87
|
end
|
96
88
|
|
97
89
|
assert_raise Google::Cloud::NotFoundError do
|
98
|
-
d.run
|
99
|
-
d.feed(@time, {"a" => "b"})
|
100
|
-
end
|
90
|
+
d.run {}
|
101
91
|
end
|
102
92
|
end
|
103
93
|
|
104
94
|
test '50x error occurred on connecting to Pub/Sub' do
|
105
95
|
d = create_driver
|
106
96
|
|
107
|
-
@pubsub_mock.topic('topic-test').
|
97
|
+
@pubsub_mock.topic('topic-test', skip_lookup: true).times(5) do
|
108
98
|
raise Google::Cloud::UnavailableError.new('TEST')
|
109
99
|
end
|
110
100
|
|
111
|
-
assert_raise
|
112
|
-
d.run
|
113
|
-
d.feed(@time, {"a" => "b"})
|
114
|
-
end
|
101
|
+
assert_raise Google::Cloud::UnavailableError do
|
102
|
+
d.run {}
|
115
103
|
end
|
116
104
|
end
|
117
105
|
|
118
106
|
test 'topic is nil' do
|
119
107
|
d = create_driver
|
120
108
|
|
121
|
-
@pubsub_mock.topic('topic-test').once { nil }
|
109
|
+
@pubsub_mock.topic('topic-test', skip_lookup: true).once { nil }
|
122
110
|
|
123
111
|
assert_raise Fluent::GcloudPubSub::Error do
|
124
|
-
d.run
|
125
|
-
d.feed(@time, {"a" => "b"})
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
test 'messages exceeding "max_message_size" are not published' do
|
131
|
-
d = create_driver(%[
|
132
|
-
project project-test
|
133
|
-
topic topic-test
|
134
|
-
key key-test
|
135
|
-
max_message_size 1000
|
136
|
-
])
|
137
|
-
|
138
|
-
@publisher.publish.times(0)
|
139
|
-
d.run(default_tag: "test") do
|
140
|
-
d.feed(@time, {"a" => "a" * 1000})
|
112
|
+
d.run {}
|
141
113
|
end
|
142
114
|
end
|
143
115
|
end
|
@@ -145,10 +117,14 @@ class GcloudPubSubOutputTest < Test::Unit::TestCase
|
|
145
117
|
sub_test_case 'publish' do
|
146
118
|
setup do
|
147
119
|
@publisher = mock!
|
148
|
-
@pubsub_mock = mock!.topic(anything) { @publisher }
|
120
|
+
@pubsub_mock = mock!.topic(anything, anything) { @publisher }
|
149
121
|
stub(Google::Cloud::Pubsub).new { @pubsub_mock }
|
150
122
|
end
|
151
123
|
|
124
|
+
setup do
|
125
|
+
@time = event_time('2016-07-09 11:12:13 UTC')
|
126
|
+
end
|
127
|
+
|
152
128
|
test 'messages are divided into "max_messages"' do
|
153
129
|
d = create_driver
|
154
130
|
@publisher.publish.times(2)
|
@@ -178,6 +154,20 @@ class GcloudPubSubOutputTest < Test::Unit::TestCase
|
|
178
154
|
end
|
179
155
|
end
|
180
156
|
|
157
|
+
test 'messages exceeding "max_message_size" are not published' do
|
158
|
+
d = create_driver(%[
|
159
|
+
project project-test
|
160
|
+
topic topic-test
|
161
|
+
key key-test
|
162
|
+
max_message_size 1000
|
163
|
+
])
|
164
|
+
|
165
|
+
@publisher.publish.times(0)
|
166
|
+
d.run(default_tag: "test") do
|
167
|
+
d.feed(@time, {"a" => "a" * 1000})
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
181
171
|
test 'accept "ASCII-8BIT" encoded multibyte strings' do
|
182
172
|
# on fluentd v0.14, all strings treated as "ASCII-8BIT" except specified encoding.
|
183
173
|
d = create_driver
|
@@ -206,21 +196,50 @@ class GcloudPubSubOutputTest < Test::Unit::TestCase
|
|
206
196
|
end
|
207
197
|
end
|
208
198
|
end
|
199
|
+
end
|
209
200
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
201
|
+
sub_test_case 'NotFoundError' do
|
202
|
+
setup do
|
203
|
+
@publisher = mock!
|
204
|
+
@pubsub_mock = mock!
|
205
|
+
@google_cloud_pubsub_stub = stub(Google::Cloud::Pubsub)
|
206
|
+
end
|
207
|
+
|
208
|
+
test 'raises NotFoundError on publishing to non-existing topic' do
|
209
|
+
d = create_driver
|
210
|
+
|
211
|
+
@google_cloud_pubsub_stub.new.once { @pubsub_mock }
|
212
|
+
@pubsub_mock.topic("topic-test", skip_lookup: true).once { @publisher }
|
213
|
+
@publisher.publish.once { raise Google::Cloud::NotFoundError.new('5:Resource not found (resource=marc-sg-publish-something)') }
|
214
|
+
|
215
|
+
assert_raises Google::Cloud::NotFoundError do
|
216
|
+
d.run(default_tag: "test") do
|
217
|
+
d.feed([{'a' => 1, 'b' => 2}])
|
218
|
+
end
|
222
219
|
end
|
223
|
-
assert_equal({"tag" => 'test', "foo" => "bar"}, JSON.parse(MessagePack.unpack(d.formatted.first)[0]))
|
224
220
|
end
|
225
221
|
end
|
222
|
+
|
223
|
+
sub_test_case 'UnauthenticatedError' do
|
224
|
+
setup do
|
225
|
+
@publisher = mock!
|
226
|
+
@pubsub_mock = mock!
|
227
|
+
@google_cloud_pubsub_stub = stub(Google::Cloud::Pubsub)
|
228
|
+
end
|
229
|
+
|
230
|
+
test 'renew publisher on UnauthenticatedError' do
|
231
|
+
d = create_driver
|
232
|
+
|
233
|
+
@google_cloud_pubsub_stub.new.twice { @pubsub_mock }
|
234
|
+
@pubsub_mock.topic("topic-test", skip_lookup: true).twice { @publisher }
|
235
|
+
@publisher.publish.once { raise Google::Cloud::UnauthenticatedError.new('16:Deadline Exceeded') }
|
236
|
+
|
237
|
+
assert_raises Google::Cloud::UnauthenticatedError do
|
238
|
+
d.run(default_tag: "test") do
|
239
|
+
d.feed([{'a' => 1, 'b' => 2}])
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
226
245
|
end
|
metadata
CHANGED
@@ -1,105 +1,114 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-gcloud-pubsub-custom-subscriber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.3Z
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yoshihiro MIYAI
|
8
|
+
- mjchuable
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2019-10-
|
12
|
+
date: 2019-10-23 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: fluentd
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
|
-
- -
|
18
|
+
- - '='
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.14.
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '2'
|
20
|
+
version: 0.14.25
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
24
|
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 0.14.15
|
30
|
-
- - "<"
|
25
|
+
- - '='
|
31
26
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
27
|
+
version: 0.14.25
|
33
28
|
- !ruby/object:Gem::Dependency
|
34
29
|
name: google-cloud-pubsub
|
35
30
|
requirement: !ruby/object:Gem::Requirement
|
36
31
|
requirements:
|
37
|
-
- -
|
32
|
+
- - '='
|
38
33
|
- !ruby/object:Gem::Version
|
39
|
-
version: 0.30.
|
34
|
+
version: 0.30.2
|
40
35
|
type: :runtime
|
41
36
|
prerelease: false
|
42
37
|
version_requirements: !ruby/object:Gem::Requirement
|
43
38
|
requirements:
|
44
|
-
- -
|
39
|
+
- - '='
|
45
40
|
- !ruby/object:Gem::Version
|
46
|
-
version: 0.30.
|
41
|
+
version: 0.30.2
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: retryable
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 2.0.4
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 2.0.4
|
47
56
|
- !ruby/object:Gem::Dependency
|
48
57
|
name: bundler
|
49
58
|
requirement: !ruby/object:Gem::Requirement
|
50
59
|
requirements:
|
51
|
-
- -
|
60
|
+
- - '='
|
52
61
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
62
|
+
version: 1.16.6
|
54
63
|
type: :development
|
55
64
|
prerelease: false
|
56
65
|
version_requirements: !ruby/object:Gem::Requirement
|
57
66
|
requirements:
|
58
|
-
- -
|
67
|
+
- - '='
|
59
68
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
69
|
+
version: 1.16.6
|
61
70
|
- !ruby/object:Gem::Dependency
|
62
71
|
name: rake
|
63
72
|
requirement: !ruby/object:Gem::Requirement
|
64
73
|
requirements:
|
65
|
-
- -
|
74
|
+
- - '='
|
66
75
|
- !ruby/object:Gem::Version
|
67
|
-
version:
|
76
|
+
version: 12.1.0
|
68
77
|
type: :development
|
69
78
|
prerelease: false
|
70
79
|
version_requirements: !ruby/object:Gem::Requirement
|
71
80
|
requirements:
|
72
|
-
- -
|
81
|
+
- - '='
|
73
82
|
- !ruby/object:Gem::Version
|
74
|
-
version:
|
83
|
+
version: 12.1.0
|
75
84
|
- !ruby/object:Gem::Dependency
|
76
85
|
name: test-unit
|
77
86
|
requirement: !ruby/object:Gem::Requirement
|
78
87
|
requirements:
|
79
|
-
- -
|
88
|
+
- - '='
|
80
89
|
- !ruby/object:Gem::Version
|
81
|
-
version:
|
90
|
+
version: 3.2.5
|
82
91
|
type: :development
|
83
92
|
prerelease: false
|
84
93
|
version_requirements: !ruby/object:Gem::Requirement
|
85
94
|
requirements:
|
86
|
-
- -
|
95
|
+
- - '='
|
87
96
|
- !ruby/object:Gem::Version
|
88
|
-
version:
|
97
|
+
version: 3.2.5
|
89
98
|
- !ruby/object:Gem::Dependency
|
90
99
|
name: test-unit-rr
|
91
100
|
requirement: !ruby/object:Gem::Requirement
|
92
101
|
requirements:
|
93
|
-
- -
|
102
|
+
- - '='
|
94
103
|
- !ruby/object:Gem::Version
|
95
|
-
version:
|
104
|
+
version: 1.0.5
|
96
105
|
type: :development
|
97
106
|
prerelease: false
|
98
107
|
version_requirements: !ruby/object:Gem::Requirement
|
99
108
|
requirements:
|
100
|
-
- -
|
109
|
+
- - '='
|
101
110
|
- !ruby/object:Gem::Version
|
102
|
-
version:
|
111
|
+
version: 1.0.5
|
103
112
|
description: Google Cloud Pub/Sub input/output plugin for Fluentd event collector
|
104
113
|
without auto-create topic requiring only Pub/Sub subscriber ACL
|
105
114
|
email: msparrow17@gmail.com
|
@@ -121,7 +130,7 @@ files:
|
|
121
130
|
- test/plugin/test_in_gcloud_pubsub.rb
|
122
131
|
- test/plugin/test_out_gcloud_pubsub.rb
|
123
132
|
- test/test_helper.rb
|
124
|
-
homepage:
|
133
|
+
homepage:
|
125
134
|
licenses:
|
126
135
|
- MIT
|
127
136
|
metadata: {}
|
@@ -136,13 +145,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
136
145
|
version: '0'
|
137
146
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
147
|
requirements:
|
139
|
-
- - "
|
148
|
+
- - ">"
|
140
149
|
- !ruby/object:Gem::Version
|
141
|
-
version:
|
150
|
+
version: 1.3.1
|
142
151
|
requirements: []
|
143
152
|
rubygems_version: 3.0.6
|
144
153
|
signing_key:
|
145
154
|
specification_version: 4
|
146
|
-
summary: Google Cloud Pub/Sub input/output plugin for Fluentd event collector
|
147
|
-
auto-create topic requiring only Pub/Sub subscriber ACL
|
155
|
+
summary: Google Cloud Pub/Sub input/output plugin for Fluentd event collector
|
148
156
|
test_files: []
|