fluent-plugin-grafana-loki 1.0.2 → 1.1.0
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/README.md +63 -4
- data/lib/fluent/plugin/out_loki.rb +51 -33
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d29e69ac3bede62dac1fa9aba38b5b96bd322150f13748a85ef91e5a044c5d8
|
4
|
+
data.tar.gz: dc521c086b7a88e1163e1257b31dab968b26082655b764b89685e0945e72cc25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8fdacb9474dba6bcf8a7395a9126945bc3c123b8cdb318fc95f7658943b5465819e226a8ac65a5c0b1dc0a3d66c9fd8b551170d5b9416601d693484c10f87d4
|
7
|
+
data.tar.gz: 025c5f3e296af6e3e19daf132ad0411795386073c1573ba2766984812c2801f5cc985a90ddeb7bba4c736b70538d55047070bb98b6d1dfe6e669ab7437204a89
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@ This plugin offers two line formats and uses protobuf to send compressed data to
|
|
6
6
|
|
7
7
|
Key features:
|
8
8
|
* extra_labels - labels to be added to every line of a logfile, useful for designating environments
|
9
|
-
*
|
9
|
+
* label - This section allows you to specify labels from your log fields
|
10
10
|
|
11
11
|
## Installation
|
12
12
|
|
@@ -29,6 +29,64 @@ In your Fluentd configuration, use `@type loki`. Additional configuration is opt
|
|
29
29
|
</match>
|
30
30
|
```
|
31
31
|
|
32
|
+
### Using labels
|
33
|
+
|
34
|
+
Simple label from top level attribute
|
35
|
+
```
|
36
|
+
<match mytag>
|
37
|
+
@type loki
|
38
|
+
# ...
|
39
|
+
<label>
|
40
|
+
fluentd_worker
|
41
|
+
</label>
|
42
|
+
# ...
|
43
|
+
</match>
|
44
|
+
```
|
45
|
+
|
46
|
+
You can rewrite the label keys as well as the following
|
47
|
+
|
48
|
+
```
|
49
|
+
<match mytag>
|
50
|
+
@type loki
|
51
|
+
# ...
|
52
|
+
<label>
|
53
|
+
worker fluentd_worker
|
54
|
+
</label>
|
55
|
+
# ...
|
56
|
+
</match>
|
57
|
+
```
|
58
|
+
|
59
|
+
You can use record accessor syntax for nested field. https://docs.fluentd.org/plugin-helper-overview/api-plugin-helper-record_accessor#syntax
|
60
|
+
|
61
|
+
```
|
62
|
+
<match mytag>
|
63
|
+
@type loki
|
64
|
+
# ...
|
65
|
+
<label>
|
66
|
+
container $.kubernetes.container
|
67
|
+
</label>
|
68
|
+
# ...
|
69
|
+
</match>
|
70
|
+
```
|
71
|
+
|
72
|
+
### Extracting Kubernetes labels
|
73
|
+
|
74
|
+
As Kubernetes labels are a list of nested key-value pairs there is a separate option to extract them.
|
75
|
+
Note that special characters like "`. - /`" will be overwritten with `_`.
|
76
|
+
Use with the `remove_keys kubernetes` option to eliminate metadata from the log.
|
77
|
+
```
|
78
|
+
<match mytag>
|
79
|
+
@type loki
|
80
|
+
# ...
|
81
|
+
extract_kubernetes_labels true
|
82
|
+
remove_keys kubernetes
|
83
|
+
<label>
|
84
|
+
container $.kubernetes.container
|
85
|
+
</label>
|
86
|
+
# ...
|
87
|
+
</match>
|
88
|
+
```
|
89
|
+
|
32
90
|
### Multi-worker usage
|
33
91
|
|
34
92
|
Loki doesn't currently support out-of-order inserts - if you try to insert a log entry an earlier timestamp after a log entry with with identical labels but a later timestamp, the insert will fail with `HTTP status code: 500, message: rpc error: code = Unknown desc = Entry out of order`. Therefore, in order to use this plugin in a multi worker Fluentd setup, you'll need to include the worker ID in the labels.
|
@@ -45,7 +103,9 @@ For example, using [fluent-plugin-record-modifier](https://github.com/repeatedly
|
|
45
103
|
<match mytag>
|
46
104
|
@type loki
|
47
105
|
# ...
|
48
|
-
|
106
|
+
<label>
|
107
|
+
fluentd_worker
|
108
|
+
</label>
|
49
109
|
# ...
|
50
110
|
</match>
|
51
111
|
```
|
@@ -112,8 +172,7 @@ Loki is intended to index and group log streams using only a small set of labels
|
|
112
172
|
|
113
173
|
There are few configurations settings to control the output format.
|
114
174
|
- extra_labels: (default: nil) set of labels to include with every Loki stream. eg `{"env":"dev", "datacenter": "dc1"}`
|
115
|
-
- remove_keys: (default: nil) comma separated list of needless record keys to remove. All other keys will be placed into the log line
|
116
|
-
- label_keys: (default: "job,instance") comma separated list of keys to use as stream labels. All other keys will be placed into the log line
|
175
|
+
- remove_keys: (default: nil) comma separated list of needless record keys to remove. All other keys will be placed into the log line. You can use [record_accessor syntax](https://docs.fluentd.org/plugin-helper-overview/api-plugin-helper-record_accessor#syntax).
|
117
176
|
- line_format: format to use when flattening the record to a log line. Valid values are "json" or "key_value". If set to "json" the log line sent to Loki will be the fluentd record (excluding any keys extracted out as labels) dumped as json. If set to "key_value", the log line will be each item in the record concatenated together (separated by a single space) in the format `<key>=<value>`.
|
118
177
|
- drop_single_key: if set to true and after extracting label_keys a record only has a single key remaining, the log line sent to Loki will just be the value of the record key.
|
119
178
|
|
@@ -24,36 +24,38 @@ require 'time'
|
|
24
24
|
module Fluent
|
25
25
|
module Plugin
|
26
26
|
# Subclass of Fluent Plugin Output
|
27
|
-
class LokiOutput < Fluent::Plugin::Output
|
27
|
+
class LokiOutput < Fluent::Plugin::Output # rubocop:disable Metrics/ClassLength
|
28
28
|
Fluent::Plugin.register_output('loki', self)
|
29
29
|
|
30
|
-
helpers :compat_parameters
|
30
|
+
helpers :compat_parameters, :record_accessor
|
31
|
+
|
32
|
+
attr_accessor :record_accessors
|
31
33
|
|
32
34
|
DEFAULT_BUFFER_TYPE = 'memory'
|
33
35
|
|
34
|
-
|
36
|
+
desc 'url of loki server'
|
35
37
|
config_param :url, :string, default: 'https://logs-us-west1.grafana.net'
|
36
38
|
|
37
|
-
|
39
|
+
desc 'BasicAuth credentials'
|
38
40
|
config_param :username, :string, default: nil
|
39
41
|
config_param :password, :string, default: nil, secret: true
|
40
42
|
|
41
|
-
|
43
|
+
desc 'Loki tenant id'
|
42
44
|
config_param :tenant, :string, default: nil
|
43
45
|
|
44
|
-
|
46
|
+
desc 'extra labels to add to all log streams'
|
45
47
|
config_param :extra_labels, :hash, default: {}
|
46
48
|
|
47
|
-
|
49
|
+
desc 'format to use when flattening the record to a log line'
|
48
50
|
config_param :line_format, :enum, list: %i[json key_value], default: :key_value
|
49
51
|
|
50
|
-
|
51
|
-
config_param :
|
52
|
+
desc 'extract kubernetes labels as loki labels'
|
53
|
+
config_param :extract_kubernetes_labels, :bool, default: false
|
52
54
|
|
53
|
-
|
54
|
-
config_param :remove_keys, :
|
55
|
+
desc 'comma separated list of needless record keys to remove'
|
56
|
+
config_param :remove_keys, :array, default: %w[], value_type: :string
|
55
57
|
|
56
|
-
|
58
|
+
desc 'if a record only has 1 key, then just set the log line to the value and discard the key.'
|
57
59
|
config_param :drop_single_key, :bool, default: false
|
58
60
|
|
59
61
|
config_section :buffer do
|
@@ -64,9 +66,18 @@ module Fluent
|
|
64
66
|
def configure(conf)
|
65
67
|
compat_parameters_convert(conf, :buffer)
|
66
68
|
super
|
67
|
-
|
68
|
-
|
69
|
-
|
69
|
+
@record_accessors = {}
|
70
|
+
conf.elements.select { |element| element.name == 'label' }.each do |element|
|
71
|
+
element.each_pair do |k, v|
|
72
|
+
element.key?(k) # to suppress unread configuration warning
|
73
|
+
v = k if v.empty?
|
74
|
+
@record_accessors[k] = record_accessor_create(v)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
@remove_keys_accessors = []
|
78
|
+
@remove_keys.each do |key|
|
79
|
+
@remove_keys_accessors.push(record_accessor_create(key))
|
80
|
+
end
|
70
81
|
end
|
71
82
|
|
72
83
|
def multi_workers_ready?
|
@@ -84,7 +95,7 @@ module Fluent
|
|
84
95
|
def write(chunk)
|
85
96
|
# streams by label
|
86
97
|
payload = generic_to_loki(chunk)
|
87
|
-
body = { 'streams'
|
98
|
+
body = { 'streams' => payload }
|
88
99
|
|
89
100
|
# add ingest path to loki url
|
90
101
|
uri = URI.parse(url + '/api/prom/push')
|
@@ -101,7 +112,7 @@ module Fluent
|
|
101
112
|
}
|
102
113
|
log.debug "sending #{req.body.length} bytes to loki"
|
103
114
|
res = Net::HTTP.start(uri.hostname, uri.port, **opts) { |http| http.request(req) }
|
104
|
-
unless res
|
115
|
+
unless res&.is_a?(Net::HTTPSuccess)
|
105
116
|
res_summary = if res
|
106
117
|
"#{res.code} #{res.message} #{res.body}"
|
107
118
|
else
|
@@ -135,10 +146,8 @@ module Fluent
|
|
135
146
|
data_labels = {} if data_labels.nil?
|
136
147
|
data_labels = data_labels.merge(@extra_labels)
|
137
148
|
|
138
|
-
|
139
|
-
|
140
|
-
formatted_labels.push("#{k}=\"#{v}\"")
|
141
|
-
end
|
149
|
+
data_labels.each do |k, v|
|
150
|
+
formatted_labels.push(%(#{k}="#{v.gsub('"', '\\"')}")) if v
|
142
151
|
end
|
143
152
|
'{' + formatted_labels.join(',') + '}'
|
144
153
|
end
|
@@ -147,7 +156,7 @@ module Fluent
|
|
147
156
|
payload = []
|
148
157
|
streams.each do |k, v|
|
149
158
|
# create a stream for each label set.
|
150
|
-
# Additionally sort the entries by timestamp just
|
159
|
+
# Additionally sort the entries by timestamp just in case we
|
151
160
|
# got them out of order.
|
152
161
|
# 'labels' => '{worker="0"}',
|
153
162
|
payload.push(
|
@@ -169,7 +178,7 @@ module Fluent
|
|
169
178
|
when :key_value
|
170
179
|
formatted_labels = []
|
171
180
|
record.each do |k, v|
|
172
|
-
formatted_labels.push(
|
181
|
+
formatted_labels.push(%(#{k}="#{v}"))
|
173
182
|
end
|
174
183
|
line = formatted_labels.join(' ')
|
175
184
|
end
|
@@ -177,22 +186,31 @@ module Fluent
|
|
177
186
|
line
|
178
187
|
end
|
179
188
|
|
189
|
+
#
|
180
190
|
# convert a line to loki line with labels
|
181
191
|
def line_to_loki(record)
|
182
192
|
chunk_labels = {}
|
183
193
|
line = ''
|
184
194
|
if record.is_a?(Hash)
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
195
|
+
@record_accessors&.each do |name, accessor|
|
196
|
+
new_key = name.gsub(%r{[.\-\/]}, '_')
|
197
|
+
chunk_labels[new_key] = accessor.call(record)
|
198
|
+
accessor.delete(record)
|
199
|
+
end
|
200
|
+
|
201
|
+
if @extract_kubernetes_labels && record.key?('kubernetes')
|
202
|
+
kubernetes_labels = record['kubernetes']['labels']
|
203
|
+
kubernetes_labels.each_key do |l|
|
204
|
+
new_key = l.gsub(%r{[.\-\/]}, '_')
|
205
|
+
chunk_labels[new_key] = kubernetes_labels[l]
|
194
206
|
end
|
195
|
-
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# remove needless keys.
|
210
|
+
@remove_keys_accessors&.each do |deleter|
|
211
|
+
deleter.delete(record)
|
212
|
+
end
|
213
|
+
|
196
214
|
line = record_to_line(record)
|
197
215
|
else
|
198
216
|
line = record.to_s
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-grafana-loki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- woodsaj
|
@@ -9,22 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-10-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - "
|
18
|
+
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '0'
|
21
21
|
type: :development
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- - "
|
25
|
+
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
27
|
+
version: '0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: rake
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -105,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
105
|
- !ruby/object:Gem::Version
|
106
106
|
version: '0'
|
107
107
|
requirements: []
|
108
|
-
rubygems_version: 3.0.
|
108
|
+
rubygems_version: 3.0.3
|
109
109
|
signing_key:
|
110
110
|
specification_version: 4
|
111
111
|
summary: Output plugin to ship logs to a Grafana Loki server
|