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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 96e70bdf4f296d3d857f89dbd2bb8938cb8b859e
4
- data.tar.gz: 1aee8fba1aca9fc563c819c7e262623fe4366acc
3
+ metadata.gz: 3e1ab17de590fac6a23aca6395aaacbad6e895a6
4
+ data.tar.gz: 4c57cc67becf6ca2fd81dcf7ab99b3a3987eb48b
5
5
  SHA512:
6
- metadata.gz: 8787ed0e0f46fc14f5aaf7efbf2b1662cb439e9bf68ced78b65de5b507e2d2d2e46a22ebd25ef232040c1e4181ac7217e04ec53d0f56f6e7107237898c2e7f8e
7
- data.tar.gz: 26c760145fa0902f8856bf2ebf23e24e54136c813a9de17ca61270956e083b62c12c9ac8580d951a4b3c973055b535e7d90333b9f478220724870a767604094c
6
+ metadata.gz: 3d4c97238f8765492974989bc7fbe6149434a6855769123879c1a8ad0010d6fd1d5f484100174319bfed8d138d3da7a3e29f4ed0c78046509d258be5396a92de
7
+ data.tar.gz: cf500b232f2f5807d9515125f0b7c36df8b95b0ec4c8251b2afe0c0bfc7cd545de6e9bdb5dbc102494e6f3e355c7598222d85f034a5e3ca6aa74189bbe7c0a55
data/.gitignore CHANGED
@@ -16,3 +16,4 @@ test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
18
  vendor/*
19
+ *.DS_Store
data/README.md CHANGED
@@ -1,24 +1,26 @@
1
- # fluent-plugin-pagerduty does not work
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 fluentd
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 td-agent2
17
- $ sudo td-agent-gem install fluent-plugin-pagerduty -v 0.0.1
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
- #### configuration example
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.1"
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
- api = Pagerduty.new(service_key)
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.1
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: 2017-03-19 00:00:00.000000000 Z
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: Fluentd Input plugin to replay alert notification for PagerDuty API.
69
+ description:
70
70
  email:
71
71
  - y.ken.studio@gmail.com
72
72
  executables: []