fluent-plugin-pagerduty 0.0.1 → 0.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/.gitignore +1 -0
- data/README.md +80 -12
- data/fluent-plugin-pagerduty.gemspec +1 -2
- data/lib/fluent/plugin/out_pagerduty.rb +106 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e1ab17de590fac6a23aca6395aaacbad6e895a6
|
4
|
+
data.tar.gz: 4c57cc67becf6ca2fd81dcf7ab99b3a3987eb48b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d4c97238f8765492974989bc7fbe6149434a6855769123879c1a8ad0010d6fd1d5f484100174319bfed8d138d3da7a3e29f4ed0c78046509d258be5396a92de
|
7
|
+
data.tar.gz: cf500b232f2f5807d9515125f0b7c36df8b95b0ec4c8251b2afe0c0bfc7cd545de6e9bdb5dbc102494e6f3e355c7598222d85f034a5e3ca6aa74189bbe7c0a55
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,24 +1,26 @@
|
|
1
|
-
# fluent-plugin-pagerduty
|
1
|
+
# fluent-plugin-pagerduty
|
2
2
|
|
3
3
|
Fluentd Output plugin to relay alert notification from application to [PagerDuty](http://www.pagerduty.com/).
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
|
-
install with `gem` or `fluent-gem` command as:
|
7
|
+
install with `td-agnet-gem` or `fluent-gem`, `gem` command as:
|
8
8
|
|
9
9
|
```
|
10
|
-
# for
|
11
|
-
$ gem install fluent-plugin-pagerduty
|
10
|
+
# for td-agent2 (recommend)
|
11
|
+
$ sudo td-agent-gem install fluent-plugin-pagerduty -v 0.0.1
|
12
12
|
|
13
13
|
# for td-agent
|
14
14
|
$ sudo /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-pagerduty -v 0.0.1
|
15
15
|
|
16
|
-
# for
|
17
|
-
$
|
16
|
+
# for system installed fluentd
|
17
|
+
$ gem install fluent-plugin-pagerduty
|
18
18
|
```
|
19
19
|
|
20
20
|
## Usage
|
21
21
|
|
22
|
+
<img width="1025" alt="screenshot 2017-03-18 18 20 43" src="https://cloud.githubusercontent.com/assets/1428486/24077350/ab9f9dd4-0c07-11e7-9f9f-8cd27a451b6e.png">
|
23
|
+
|
22
24
|
1. add service selecting `Service Type : Generic API system` on PagerDuty websites
|
23
25
|
2. copy API Key from the `Services` page.
|
24
26
|
3. install fluent-plugin-pagerduty with gem or fluent-gem command.
|
@@ -26,15 +28,19 @@ $ sudo td-agent-gem install fluent-plugin-pagerduty -v 0.0.1
|
|
26
28
|
5. restart fluentd process.
|
27
29
|
6. send test message for fluent-plugin-pagerduty
|
28
30
|
|
29
|
-
|
31
|
+
### Examples
|
32
|
+
|
33
|
+
#### Simple alert (JSON pass-thru)
|
34
|
+
|
35
|
+
In this example, a JSON record already conforming to the PagerDuty API is processed by Fluentd and passed through to PagerDuty as-is, triggering a simple alert.
|
30
36
|
|
31
37
|
```
|
32
38
|
<source>
|
33
|
-
type forward
|
39
|
+
@type forward
|
34
40
|
</source>
|
35
41
|
|
36
42
|
<source>
|
37
|
-
type http
|
43
|
+
@type http
|
38
44
|
port 8888
|
39
45
|
</source>
|
40
46
|
|
@@ -44,8 +50,6 @@ $ sudo td-agent-gem install fluent-plugin-pagerduty -v 0.0.1
|
|
44
50
|
</match>
|
45
51
|
```
|
46
52
|
|
47
|
-
#### notify example
|
48
|
-
|
49
53
|
```
|
50
54
|
# via forward
|
51
55
|
$ echo '{"description":"Form validation has failed","details":{"name":"success","mail":"failed"}}' | fluent-cat notify.pagerduty
|
@@ -54,6 +58,70 @@ $ echo '{"description":"Form validation has failed","details":{"name":"success",
|
|
54
58
|
$ curl http://localhost:8888/notify.pagerduty -F 'json={"description":"Form validation has failed","details":{"name":"success","mail":"failed"}}'
|
55
59
|
```
|
56
60
|
|
61
|
+
#### Advanced alert (transformed JSON)
|
62
|
+
|
63
|
+
In this example, a JSON record is referenced to build a PagerDuty event with an incident key for managing [de-duplication](https://v2.developer.pagerduty.com/docs/events-api#incident-de-duplication-and-incident_key).
|
64
|
+
|
65
|
+
```
|
66
|
+
<source>
|
67
|
+
@type forward
|
68
|
+
</source>
|
69
|
+
|
70
|
+
<source>
|
71
|
+
@type http
|
72
|
+
port 8888
|
73
|
+
</source>
|
74
|
+
|
75
|
+
<match notify.pagerduty>
|
76
|
+
type pagerduty
|
77
|
+
service_key ******************
|
78
|
+
description Alarm@${Node["Location"]}:: ${Log["Message"]}
|
79
|
+
incident_key [${tag_parts[-1]}] ${Log["File"]}:${Log["Line"]}
|
80
|
+
</match>
|
81
|
+
```
|
82
|
+
|
83
|
+
```
|
84
|
+
# via forward
|
85
|
+
$ echo '{"Node":{"Location":"Somewhere","IP Address":"10.0.0.1"},"Log":{"Level": "ERROR","File":"FooBar.cpp","Line":42,"Message":"A very important logging message"}}' | fluent-cat notify.pagerduty
|
86
|
+
|
87
|
+
# via http
|
88
|
+
$ curl http://localhost:8888/notify.pagerduty -F 'json={"Node":{"Location":"Somewhere","IP Address":"10.0.0.1"},"Log":{"Level": "ERROR","File":"FooBar.cpp","Line":42,"Message":"A very important logging message"}}'
|
89
|
+
```
|
90
|
+
|
91
|
+
|
92
|
+
### Option Parameters
|
93
|
+
|
94
|
+
- `service_key` (required)
|
95
|
+
|
96
|
+
The unique API identifier generated for each PagerDuty service belonging to a PagerDuty account. Must be present for any PagerDuty events.
|
97
|
+
|
98
|
+
- `event_type` (optional)
|
99
|
+
|
100
|
+
The PagerDuty event type: `trigger`, `acknowledge`, or `resolve`. If unspecified, the default is `trigger`.
|
101
|
+
|
102
|
+
- `description` (conditionally required)
|
103
|
+
|
104
|
+
The message content of a PagerDuty event. PagerDuty event types of `trigger` must contain a description. The content of the description may be built using Placeholders (see next section).
|
105
|
+
|
106
|
+
- `incident_key` (optional)
|
107
|
+
|
108
|
+
The identifier used for PagerDuty's [de-duplication of events](https://v2.developer.pagerduty.com/docs/events-api#incident-de-duplication-and-incident_key). The content of the incident key may be built using Placeholders (see next section).
|
109
|
+
|
110
|
+
### Placeholders
|
111
|
+
|
112
|
+
These placeholders are available:
|
113
|
+
|
114
|
+
* ${…}
|
115
|
+
* `hashName["key"]` Value of `key` in named hash
|
116
|
+
* `arrayName[N]` Value at index _N_ in named array
|
117
|
+
* `primitive` Value of named primitive
|
118
|
+
|
119
|
+
Placeholders are built recursively and concatenated. For example, a specific value within a hash containing an array of hashes could be referenced as: `${foo["bar"][2]["baz"]}`.
|
120
|
+
* ${tag} Input tag
|
121
|
+
* ${tag\_parts[N]} Input tag splitted by '.' indexed with _N_ such as `${tag_parts[0]}`, `${tag_parts[-1]}`.
|
122
|
+
|
123
|
+
Placeholder functionality is derived from features of [fluent-plugin-record-reformer](https://github.com/sonots/fluent-plugin-record-reformer).
|
124
|
+
|
57
125
|
## Contributing
|
58
126
|
|
59
127
|
1. Fork it
|
@@ -72,5 +140,5 @@ Copyright (c) 2013- Kentaro Yoshida (@yoshi_ken)
|
|
72
140
|
|
73
141
|
## License
|
74
142
|
|
75
|
-
Apache License, Version 2.0
|
143
|
+
[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
76
144
|
|
@@ -4,10 +4,9 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "fluent-plugin-pagerduty"
|
7
|
-
spec.version = "0.0
|
7
|
+
spec.version = "0.1.0"
|
8
8
|
spec.authors = ["Kentaro Yoshida"]
|
9
9
|
spec.email = ["y.ken.studio@gmail.com"]
|
10
|
-
spec.description = %q{Fluentd Input plugin to replay alert notification for PagerDuty API.}
|
11
10
|
spec.summary = %q{Fluentd Input plugin to replay alert notification for PagerDuty API.}
|
12
11
|
spec.homepage = "https://github.com/y-ken/fluent-plugin-pagerduty"
|
13
12
|
spec.license = "Apache License, Version 2.0"
|
@@ -9,34 +9,137 @@ class Fluent::PagerdutyOutput < Fluent::Output
|
|
9
9
|
config_param :service_key, :string, :default => nil
|
10
10
|
config_param :event_type, :string, :default => 'trigger'
|
11
11
|
config_param :description, :string, :default => nil
|
12
|
+
config_param :incident_key, :string, :default => nil
|
12
13
|
|
13
14
|
def configure(conf)
|
14
15
|
super
|
15
16
|
|
17
|
+
# API requires service key
|
16
18
|
if @service_key.nil?
|
17
19
|
$log.warn "pagerduty: service_key required."
|
18
20
|
end
|
21
|
+
|
22
|
+
# PagerDuty trigger event type requires description, other event types do not
|
23
|
+
if @event_type == 'trigger' && @description.nil?
|
24
|
+
$log.warn "pagerduty: description required for trigger event_type."
|
25
|
+
end
|
19
26
|
end
|
20
27
|
|
21
28
|
def emit(tag, es, chain)
|
22
29
|
es.each do |time,record|
|
23
|
-
call_pagerduty(record)
|
30
|
+
call_pagerduty(tag, record)
|
24
31
|
end
|
25
32
|
|
26
33
|
chain.next
|
27
34
|
end
|
28
35
|
|
29
|
-
def call_pagerduty(record)
|
36
|
+
def call_pagerduty(tag, record)
|
30
37
|
begin
|
38
|
+
expander = PlaceholderExpander.new({:log => log})
|
39
|
+
tag_parts = tag.split('.')
|
40
|
+
placeholder_values = {
|
41
|
+
'tag' => tag,
|
42
|
+
'tag_parts' => tag_parts,
|
43
|
+
'record' => record,
|
44
|
+
}
|
45
|
+
|
46
|
+
placeholders = expander.prepare_placeholders(placeholder_values)
|
47
|
+
|
31
48
|
service_key = record['service_key'] || @service_key
|
32
49
|
event_type = record['event_type'] || @event_type
|
33
50
|
description = record['description'] || record['message'] || @description
|
51
|
+
incident_key = record['incident_key'] || @incident_key
|
34
52
|
details = record['details'] || record
|
35
53
|
options = {"details" => details}
|
36
|
-
|
54
|
+
|
55
|
+
description = expander.expand(description, placeholders)
|
56
|
+
|
57
|
+
if !@incident_key.nil?
|
58
|
+
incident_key = expander.expand(incident_key, placeholders)
|
59
|
+
api = PagerdutyIncident.new(service_key, incident_key)
|
60
|
+
else
|
61
|
+
api = Pagerduty.new(service_key)
|
62
|
+
end
|
63
|
+
|
37
64
|
incident = api.trigger description, options
|
38
65
|
rescue => e
|
39
66
|
$log.error "pagerduty: request failed. ", :error_class=>e.class, :error=>e.message
|
40
67
|
end
|
41
68
|
end
|
42
69
|
end
|
70
|
+
|
71
|
+
|
72
|
+
# Modified PlaceholderExpander borrowed from fluent-plugin-record-reformer
|
73
|
+
# https://github.com/sonots/fluent-plugin-record-reformer
|
74
|
+
# Original author: Naotoshi Seo
|
75
|
+
# MIT License: https://github.com/sonots/fluent-plugin-record-reformer/blob/master/LICENSE
|
76
|
+
# Modifications: Michael Karlesky
|
77
|
+
# Changes:
|
78
|
+
# - Stripped down to limited use case
|
79
|
+
# - Building of placeholders is now recursive to handle any depth of hash, array, and primitive
|
80
|
+
class PlaceholderExpander
|
81
|
+
attr_reader :placeholders, :log
|
82
|
+
|
83
|
+
def initialize(params)
|
84
|
+
@log = params[:log]
|
85
|
+
end
|
86
|
+
|
87
|
+
def prepare_placeholders(placeholder_values)
|
88
|
+
placeholders = {}
|
89
|
+
|
90
|
+
placeholder_values.each do |key, value|
|
91
|
+
# For any entry in `placeholder_values` that is a hash, we effectively ignore its internal name.
|
92
|
+
# For example, `record` is an important hash, but referencing it at the top-level is superfluous namespacing.
|
93
|
+
# Instead of '${record["Node"]["Location"]}',
|
94
|
+
# '${Node["Location"]}' more closely maps to a user's knowledge of a data to be processed.
|
95
|
+
if value.kind_of?(Hash)
|
96
|
+
value.each do |key, value|
|
97
|
+
build_placeholders(placeholders, key, value)
|
98
|
+
end
|
99
|
+
else
|
100
|
+
build_placeholders(placeholders, key, value)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
placeholders
|
105
|
+
end
|
106
|
+
|
107
|
+
# Expand string (`${foo["bar"]}`) with placeholders
|
108
|
+
def expand(str, placeholders)
|
109
|
+
single_placeholder_matched = str.match(/\A(\${[^}]+}|__[A-Z_]+__)\z/)
|
110
|
+
if single_placeholder_matched
|
111
|
+
log_if_unknown_placeholder($1, placeholders)
|
112
|
+
return placeholders[single_placeholder_matched[1]]
|
113
|
+
end
|
114
|
+
str.gsub(/(\${[^}]+}|__[A-Z_]+__)/) {
|
115
|
+
log_if_unknown_placeholder($1, placeholders)
|
116
|
+
placeholders[$1]
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
# Recurses to build any depth of hash, arrays, and primitives
|
123
|
+
def build_placeholders(placeholders, key, value)
|
124
|
+
if value.kind_of?(Array) # tag_parts, etc
|
125
|
+
size = value.size
|
126
|
+
value.each_with_index do |v, idx|
|
127
|
+
build_placeholders(placeholders, "#{key}[#{idx}]", v)
|
128
|
+
build_placeholders(placeholders, "#{key}[#{idx-size}]", v) # support [-1]
|
129
|
+
end
|
130
|
+
elsif value.kind_of?(Hash) # record, etc
|
131
|
+
value.each do |k, v|
|
132
|
+
build_placeholders(placeholders, %Q[#{key}["#{k}"]], v) # record["foo"]
|
133
|
+
end
|
134
|
+
else
|
135
|
+
placeholders.store("${#{key}}", value)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def log_if_unknown_placeholder(placeholder, placeholders)
|
140
|
+
unless placeholders.include?(placeholder)
|
141
|
+
log.warn "pagerduty: unknown placeholder `#{placeholder}` found"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-pagerduty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kentaro Yoshida
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
-
description:
|
69
|
+
description:
|
70
70
|
email:
|
71
71
|
- y.ken.studio@gmail.com
|
72
72
|
executables: []
|