fluent-plugin-gcloud-pubsub-custom-subscriber 1.3.2 → 1.3.3Z
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|