Skip to content

Commit 2d3da34

Browse files
francois2metzsparrc
authored andcommitted
Add basic filestack webhook.
closes influxdata#1542 Generalize event. Add doc. Update default config. Add filestack to the list of plugins. Check that video conversion event returns 400. Update the readme. Update the changelog.
1 parent 094eda2 commit 2d3da34

File tree

9 files changed

+277
-3
lines changed

9 files changed

+277
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- [#1685](https://github.com/influxdata/telegraf/issues/1685): Add additional redis metrics.
1414
- [#1539](https://github.com/influxdata/telegraf/pull/1539): Added capability to send metrics through Http API for OpenTSDB.
1515
- [#1471](https://github.com/influxdata/telegraf/pull/1471): iptables input plugin.
16+
- [#1542](https://github.com/influxdata/telegraf/pull/1542): Add filestack webhook plugin.
1617

1718
### Bugfixes
1819

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ Telegraf can also collect metrics via the following service plugins:
221221
* [kafka_consumer](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/kafka_consumer)
222222
* [nats_consumer](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/nats_consumer)
223223
* [webhooks](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/webhooks)
224+
* [filestack](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/webhooks/filestack)
224225
* [github](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/webhooks/github)
225226
* [mandrill](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/webhooks/mandrill)
226227
* [rollbar](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/webhooks/rollbar)

plugins/inputs/webhooks/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ $ sudo service telegraf start
1515

1616
## Available webhooks
1717

18+
- [Filestack](filestack/)
1819
- [Github](github/)
1920
- [Mandrill](mandrill/)
2021
- [Rollbar](rollbar/)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Filestack webhook
2+
3+
You should configure your Filestack's Webhooks to point at the `webhooks` service. To do this go to `filestack.com/`, select your app and click `Credentials > Webhooks`. In the resulting page, set the `URL` to `http://<my_ip>:1619/filestack`, and click on `Add`.
4+
5+
## Events
6+
7+
See the [webhook doc](https://www.filestack.com/docs/webhooks).
8+
9+
*Limitations*: It stores all events except video conversions events.
10+
11+
All events for logs the original timestamp, the action and the id.
12+
13+
**Tags:**
14+
* 'action' = `event.action` string
15+
16+
**Fields:**
17+
* 'id' = `event.id` string
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package filestack
2+
3+
import (
4+
"encoding/json"
5+
"io/ioutil"
6+
"log"
7+
"net/http"
8+
"time"
9+
10+
"github.com/gorilla/mux"
11+
"github.com/influxdata/telegraf"
12+
)
13+
14+
type FilestackWebhook struct {
15+
Path string
16+
acc telegraf.Accumulator
17+
}
18+
19+
func (fs *FilestackWebhook) Register(router *mux.Router, acc telegraf.Accumulator) {
20+
router.HandleFunc(fs.Path, fs.eventHandler).Methods("POST")
21+
22+
log.Printf("Started the webhooks_filestack on %s\n", fs.Path)
23+
fs.acc = acc
24+
}
25+
26+
func (fs *FilestackWebhook) eventHandler(w http.ResponseWriter, r *http.Request) {
27+
defer r.Body.Close()
28+
body, err := ioutil.ReadAll(r.Body)
29+
if err != nil {
30+
w.WriteHeader(http.StatusBadRequest)
31+
return
32+
}
33+
34+
event := &FilestackEvent{}
35+
err = json.Unmarshal(body, event)
36+
if err != nil {
37+
w.WriteHeader(http.StatusBadRequest)
38+
return
39+
}
40+
41+
fs.acc.AddFields("filestack_webhooks", event.Fields(), event.Tags(), time.Unix(event.TimeStamp, 0))
42+
43+
w.WriteHeader(http.StatusOK)
44+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package filestack
2+
3+
import "strconv"
4+
5+
type FilestackEvent struct {
6+
Action string `json:"action"`
7+
TimeStamp int64 `json:"timestamp"`
8+
Id int `json:"id"`
9+
}
10+
11+
func (fe *FilestackEvent) Tags() map[string]string {
12+
return map[string]string{
13+
"action": fe.Action,
14+
}
15+
}
16+
17+
func (fe *FilestackEvent) Fields() map[string]interface{} {
18+
return map[string]interface{}{
19+
"id": strconv.Itoa(fe.Id),
20+
}
21+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package filestack
2+
3+
func DialogOpenJSON() string {
4+
return `{
5+
"action": "fp.dialog",
6+
"timestamp": 1435584646,
7+
"id": 102,
8+
"text": {
9+
"mimetypes": ["*/*"],
10+
"iframe": false,
11+
"language": "en",
12+
"id": "1435584650723",
13+
"mobile": false,
14+
"app":{
15+
"upsell": "false",
16+
"apikey": "YOUR_API_KEY",
17+
"customization":{
18+
"saveas_subheader": "Save it down to your local device or onto the Cloud",
19+
"folder_subheader": "Choose a folder to share with this application",
20+
"open_subheader": "Choose from the files on your local device or the ones you have online",
21+
"folder_header": "Select a folder",
22+
"help_text": "",
23+
"saveas_header": "Save your file",
24+
"open_header": "Upload a file"
25+
}
26+
},
27+
"dialogType": "open",
28+
"auth": false,
29+
"welcome_header": "Upload a file",
30+
"welcome_subheader": "Choose from the files on your local device or the ones you have online",
31+
"help_text": "",
32+
"recent_path": "/",
33+
"extensions": null,
34+
"maxSize": 0,
35+
"signature": null,
36+
"policy": null,
37+
"custom_providers": "imgur,cloudapp",
38+
"intra": false
39+
}
40+
}`
41+
}
42+
43+
func UploadJSON() string {
44+
return `{
45+
"action":"fp.upload",
46+
"timestamp":1443444905,
47+
"id":100946,
48+
"text":{
49+
"url":"https://www.filestackapi.com/api/file/WAunDTTqQfCNWwUUyf6n",
50+
"client":"Facebook",
51+
"type":"image/jpeg",
52+
"filename":"1579337399020824.jpg",
53+
"size":139154
54+
}
55+
}`
56+
}
57+
58+
func VideoConversionJSON() string {
59+
return `{
60+
"status":"completed",
61+
"message":"Done",
62+
"data":{
63+
"thumb":"https://cdn.filestackcontent.com/f1e8V88QDuxzOvtOAq1W",
64+
"thumb100x100":"https://process.filestackapi.com/AhTgLagciQByzXpFGRI0Az/resize=w:100,h:100,f:crop/output=f:jpg,q:66/https://cdn.filestackcontent.com/f1e8V88QDuxzOvtOAq1W",
65+
"thumb200x200":"https://process.filestackapi.com/AhTgLagciQByzXpFGRI0Az/resize=w:200,h:200,f:crop/output=f:jpg,q:66/https://cdn.filestackcontent.com/f1e8V88QDuxzOvtOAq1W",
66+
"thumb300x300":"https://process.filestackapi.com/AhTgLagciQByzXpFGRI0Az/resize=w:300,h:300,f:crop/output=f:jpg,q:66/https://cdn.filestackcontent.com/f1e8V88QDuxzOvtOAq1W",
67+
"url":"https://cdn.filestackcontent.com/VgvFVdvvTkml0WXPIoGn"
68+
},
69+
"metadata":{
70+
"result":{
71+
"audio_channels":2,
72+
"audio_codec":"vorbis",
73+
"audio_sample_rate":44100,
74+
"created_at":"2015/12/21 20:45:19 +0000",
75+
"duration":10587,
76+
"encoding_progress":100,
77+
"encoding_time":8,
78+
"extname":".webm",
79+
"file_size":293459,
80+
"fps":24,
81+
"height":260,
82+
"mime_type":"video/webm",
83+
"started_encoding_at":"2015/12/21 20:45:22 +0000",
84+
"updated_at":"2015/12/21 20:45:32 +0000",
85+
"video_bitrate":221,
86+
"video_codec":"vp8",
87+
"width":300
88+
},
89+
"source":{
90+
"audio_bitrate":125,
91+
"audio_channels":2,
92+
"audio_codec":"aac",
93+
"audio_sample_rate":44100,
94+
"created_at":"2015/12/21 20:45:19 +0000",
95+
"duration":10564,
96+
"extname":".mp4",
97+
"file_size":875797,
98+
"fps":24,
99+
"height":360,
100+
"mime_type":"video/mp4",
101+
"updated_at":"2015/12/21 20:45:32 +0000",
102+
"video_bitrate":196,
103+
"video_codec":"h264",
104+
"width":480
105+
}
106+
},
107+
"timestamp":"1453850583",
108+
"uuid":"638311d89d2bc849563a674a45809b7c"
109+
}`
110+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package filestack
2+
3+
import (
4+
"github.com/influxdata/telegraf/testutil"
5+
"net/http"
6+
"net/http/httptest"
7+
8+
"strings"
9+
"testing"
10+
)
11+
12+
func postWebhooks(md *FilestackWebhook, eventBody string) *httptest.ResponseRecorder {
13+
req, _ := http.NewRequest("POST", "/filestack", strings.NewReader(eventBody))
14+
w := httptest.NewRecorder()
15+
16+
md.eventHandler(w, req)
17+
18+
return w
19+
}
20+
21+
func TestDialogEvent(t *testing.T) {
22+
var acc testutil.Accumulator
23+
fs := &FilestackWebhook{Path: "/filestack", acc: &acc}
24+
resp := postWebhooks(fs, DialogOpenJSON())
25+
if resp.Code != http.StatusOK {
26+
t.Errorf("POST returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusOK)
27+
}
28+
29+
fields := map[string]interface{}{
30+
"id": "102",
31+
}
32+
33+
tags := map[string]string{
34+
"action": "fp.dialog",
35+
}
36+
37+
acc.AssertContainsTaggedFields(t, "filestack_webhooks", fields, tags)
38+
}
39+
40+
func TestParseError(t *testing.T) {
41+
fs := &FilestackWebhook{Path: "/filestack"}
42+
resp := postWebhooks(fs, "")
43+
if resp.Code != http.StatusBadRequest {
44+
t.Errorf("POST returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusBadRequest)
45+
}
46+
}
47+
48+
func TestUploadEvent(t *testing.T) {
49+
var acc testutil.Accumulator
50+
fs := &FilestackWebhook{Path: "/filestack", acc: &acc}
51+
resp := postWebhooks(fs, UploadJSON())
52+
if resp.Code != http.StatusOK {
53+
t.Errorf("POST returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusOK)
54+
}
55+
56+
fields := map[string]interface{}{
57+
"id": "100946",
58+
}
59+
60+
tags := map[string]string{
61+
"action": "fp.upload",
62+
}
63+
64+
acc.AssertContainsTaggedFields(t, "filestack_webhooks", fields, tags)
65+
}
66+
67+
func TestVideoConversionEvent(t *testing.T) {
68+
var acc testutil.Accumulator
69+
fs := &FilestackWebhook{Path: "/filestack", acc: &acc}
70+
resp := postWebhooks(fs, VideoConversionJSON())
71+
if resp.Code != http.StatusBadRequest {
72+
t.Errorf("POST returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusBadRequest)
73+
}
74+
}

plugins/inputs/webhooks/webhooks.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/influxdata/telegraf"
1111
"github.com/influxdata/telegraf/plugins/inputs"
1212

13+
"github.com/influxdata/telegraf/plugins/inputs/webhooks/filestack"
1314
"github.com/influxdata/telegraf/plugins/inputs/webhooks/github"
1415
"github.com/influxdata/telegraf/plugins/inputs/webhooks/mandrill"
1516
"github.com/influxdata/telegraf/plugins/inputs/webhooks/rollbar"
@@ -26,9 +27,10 @@ func init() {
2627
type Webhooks struct {
2728
ServiceAddress string
2829

29-
Github *github.GithubWebhook
30-
Mandrill *mandrill.MandrillWebhook
31-
Rollbar *rollbar.RollbarWebhook
30+
Github *github.GithubWebhook
31+
Filestack *filestack.FilestackWebhook
32+
Mandrill *mandrill.MandrillWebhook
33+
Rollbar *rollbar.RollbarWebhook
3234
}
3335

3436
func NewWebhooks() *Webhooks {
@@ -40,6 +42,9 @@ func (wb *Webhooks) SampleConfig() string {
4042
## Address and port to host Webhook listener on
4143
service_address = ":1619"
4244
45+
[inputs.webhooks.filestack]
46+
path = "/filestack"
47+
4348
[inputs.webhooks.github]
4449
path = "/github"
4550

0 commit comments

Comments
 (0)