Add basic filestack webhook.
closes #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.
This commit is contained in:
parent
998ace0ec2
commit
61a2b23f0c
|
@ -13,6 +13,7 @@
|
|||
- [#1685](https://github.com/influxdata/telegraf/issues/1685): Add additional redis metrics.
|
||||
- [#1539](https://github.com/influxdata/telegraf/pull/1539): Added capability to send metrics through Http API for OpenTSDB.
|
||||
- [#1471](https://github.com/influxdata/telegraf/pull/1471): iptables input plugin.
|
||||
- [#1542](https://github.com/influxdata/telegraf/pull/1542): Add filestack webhook plugin.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
|
|
|
@ -221,6 +221,7 @@ Telegraf can also collect metrics via the following service plugins:
|
|||
* [kafka_consumer](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/kafka_consumer)
|
||||
* [nats_consumer](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/nats_consumer)
|
||||
* [webhooks](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/webhooks)
|
||||
* [filestack](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/webhooks/filestack)
|
||||
* [github](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/webhooks/github)
|
||||
* [mandrill](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/webhooks/mandrill)
|
||||
* [rollbar](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/webhooks/rollbar)
|
||||
|
|
|
@ -15,6 +15,7 @@ $ sudo service telegraf start
|
|||
|
||||
## Available webhooks
|
||||
|
||||
- [Filestack](filestack/)
|
||||
- [Github](github/)
|
||||
- [Mandrill](mandrill/)
|
||||
- [Rollbar](rollbar/)
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# Filestack webhook
|
||||
|
||||
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`.
|
||||
|
||||
## Events
|
||||
|
||||
See the [webhook doc](https://www.filestack.com/docs/webhooks).
|
||||
|
||||
*Limitations*: It stores all events except video conversions events.
|
||||
|
||||
All events for logs the original timestamp, the action and the id.
|
||||
|
||||
**Tags:**
|
||||
* 'action' = `event.action` string
|
||||
|
||||
**Fields:**
|
||||
* 'id' = `event.id` string
|
|
@ -0,0 +1,44 @@
|
|||
package filestack
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/influxdata/telegraf"
|
||||
)
|
||||
|
||||
type FilestackWebhook struct {
|
||||
Path string
|
||||
acc telegraf.Accumulator
|
||||
}
|
||||
|
||||
func (fs *FilestackWebhook) Register(router *mux.Router, acc telegraf.Accumulator) {
|
||||
router.HandleFunc(fs.Path, fs.eventHandler).Methods("POST")
|
||||
|
||||
log.Printf("Started the webhooks_filestack on %s\n", fs.Path)
|
||||
fs.acc = acc
|
||||
}
|
||||
|
||||
func (fs *FilestackWebhook) eventHandler(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
event := &FilestackEvent{}
|
||||
err = json.Unmarshal(body, event)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
fs.acc.AddFields("filestack_webhooks", event.Fields(), event.Tags(), time.Unix(event.TimeStamp, 0))
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package filestack
|
||||
|
||||
import "strconv"
|
||||
|
||||
type FilestackEvent struct {
|
||||
Action string `json:"action"`
|
||||
TimeStamp int64 `json:"timestamp"`
|
||||
Id int `json:"id"`
|
||||
}
|
||||
|
||||
func (fe *FilestackEvent) Tags() map[string]string {
|
||||
return map[string]string{
|
||||
"action": fe.Action,
|
||||
}
|
||||
}
|
||||
|
||||
func (fe *FilestackEvent) Fields() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"id": strconv.Itoa(fe.Id),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package filestack
|
||||
|
||||
func DialogOpenJSON() string {
|
||||
return `{
|
||||
"action": "fp.dialog",
|
||||
"timestamp": 1435584646,
|
||||
"id": 102,
|
||||
"text": {
|
||||
"mimetypes": ["*/*"],
|
||||
"iframe": false,
|
||||
"language": "en",
|
||||
"id": "1435584650723",
|
||||
"mobile": false,
|
||||
"app":{
|
||||
"upsell": "false",
|
||||
"apikey": "YOUR_API_KEY",
|
||||
"customization":{
|
||||
"saveas_subheader": "Save it down to your local device or onto the Cloud",
|
||||
"folder_subheader": "Choose a folder to share with this application",
|
||||
"open_subheader": "Choose from the files on your local device or the ones you have online",
|
||||
"folder_header": "Select a folder",
|
||||
"help_text": "",
|
||||
"saveas_header": "Save your file",
|
||||
"open_header": "Upload a file"
|
||||
}
|
||||
},
|
||||
"dialogType": "open",
|
||||
"auth": false,
|
||||
"welcome_header": "Upload a file",
|
||||
"welcome_subheader": "Choose from the files on your local device or the ones you have online",
|
||||
"help_text": "",
|
||||
"recent_path": "/",
|
||||
"extensions": null,
|
||||
"maxSize": 0,
|
||||
"signature": null,
|
||||
"policy": null,
|
||||
"custom_providers": "imgur,cloudapp",
|
||||
"intra": false
|
||||
}
|
||||
}`
|
||||
}
|
||||
|
||||
func UploadJSON() string {
|
||||
return `{
|
||||
"action":"fp.upload",
|
||||
"timestamp":1443444905,
|
||||
"id":100946,
|
||||
"text":{
|
||||
"url":"https://www.filestackapi.com/api/file/WAunDTTqQfCNWwUUyf6n",
|
||||
"client":"Facebook",
|
||||
"type":"image/jpeg",
|
||||
"filename":"1579337399020824.jpg",
|
||||
"size":139154
|
||||
}
|
||||
}`
|
||||
}
|
||||
|
||||
func VideoConversionJSON() string {
|
||||
return `{
|
||||
"status":"completed",
|
||||
"message":"Done",
|
||||
"data":{
|
||||
"thumb":"https://cdn.filestackcontent.com/f1e8V88QDuxzOvtOAq1W",
|
||||
"thumb100x100":"https://process.filestackapi.com/AhTgLagciQByzXpFGRI0Az/resize=w:100,h:100,f:crop/output=f:jpg,q:66/https://cdn.filestackcontent.com/f1e8V88QDuxzOvtOAq1W",
|
||||
"thumb200x200":"https://process.filestackapi.com/AhTgLagciQByzXpFGRI0Az/resize=w:200,h:200,f:crop/output=f:jpg,q:66/https://cdn.filestackcontent.com/f1e8V88QDuxzOvtOAq1W",
|
||||
"thumb300x300":"https://process.filestackapi.com/AhTgLagciQByzXpFGRI0Az/resize=w:300,h:300,f:crop/output=f:jpg,q:66/https://cdn.filestackcontent.com/f1e8V88QDuxzOvtOAq1W",
|
||||
"url":"https://cdn.filestackcontent.com/VgvFVdvvTkml0WXPIoGn"
|
||||
},
|
||||
"metadata":{
|
||||
"result":{
|
||||
"audio_channels":2,
|
||||
"audio_codec":"vorbis",
|
||||
"audio_sample_rate":44100,
|
||||
"created_at":"2015/12/21 20:45:19 +0000",
|
||||
"duration":10587,
|
||||
"encoding_progress":100,
|
||||
"encoding_time":8,
|
||||
"extname":".webm",
|
||||
"file_size":293459,
|
||||
"fps":24,
|
||||
"height":260,
|
||||
"mime_type":"video/webm",
|
||||
"started_encoding_at":"2015/12/21 20:45:22 +0000",
|
||||
"updated_at":"2015/12/21 20:45:32 +0000",
|
||||
"video_bitrate":221,
|
||||
"video_codec":"vp8",
|
||||
"width":300
|
||||
},
|
||||
"source":{
|
||||
"audio_bitrate":125,
|
||||
"audio_channels":2,
|
||||
"audio_codec":"aac",
|
||||
"audio_sample_rate":44100,
|
||||
"created_at":"2015/12/21 20:45:19 +0000",
|
||||
"duration":10564,
|
||||
"extname":".mp4",
|
||||
"file_size":875797,
|
||||
"fps":24,
|
||||
"height":360,
|
||||
"mime_type":"video/mp4",
|
||||
"updated_at":"2015/12/21 20:45:32 +0000",
|
||||
"video_bitrate":196,
|
||||
"video_codec":"h264",
|
||||
"width":480
|
||||
}
|
||||
},
|
||||
"timestamp":"1453850583",
|
||||
"uuid":"638311d89d2bc849563a674a45809b7c"
|
||||
}`
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package filestack
|
||||
|
||||
import (
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func postWebhooks(md *FilestackWebhook, eventBody string) *httptest.ResponseRecorder {
|
||||
req, _ := http.NewRequest("POST", "/filestack", strings.NewReader(eventBody))
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
md.eventHandler(w, req)
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
func TestDialogEvent(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
fs := &FilestackWebhook{Path: "/filestack", acc: &acc}
|
||||
resp := postWebhooks(fs, DialogOpenJSON())
|
||||
if resp.Code != http.StatusOK {
|
||||
t.Errorf("POST returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusOK)
|
||||
}
|
||||
|
||||
fields := map[string]interface{}{
|
||||
"id": "102",
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"action": "fp.dialog",
|
||||
}
|
||||
|
||||
acc.AssertContainsTaggedFields(t, "filestack_webhooks", fields, tags)
|
||||
}
|
||||
|
||||
func TestParseError(t *testing.T) {
|
||||
fs := &FilestackWebhook{Path: "/filestack"}
|
||||
resp := postWebhooks(fs, "")
|
||||
if resp.Code != http.StatusBadRequest {
|
||||
t.Errorf("POST returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUploadEvent(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
fs := &FilestackWebhook{Path: "/filestack", acc: &acc}
|
||||
resp := postWebhooks(fs, UploadJSON())
|
||||
if resp.Code != http.StatusOK {
|
||||
t.Errorf("POST returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusOK)
|
||||
}
|
||||
|
||||
fields := map[string]interface{}{
|
||||
"id": "100946",
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"action": "fp.upload",
|
||||
}
|
||||
|
||||
acc.AssertContainsTaggedFields(t, "filestack_webhooks", fields, tags)
|
||||
}
|
||||
|
||||
func TestVideoConversionEvent(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
fs := &FilestackWebhook{Path: "/filestack", acc: &acc}
|
||||
resp := postWebhooks(fs, VideoConversionJSON())
|
||||
if resp.Code != http.StatusBadRequest {
|
||||
t.Errorf("POST returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusBadRequest)
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
|
||||
"github.com/influxdata/telegraf/plugins/inputs/webhooks/filestack"
|
||||
"github.com/influxdata/telegraf/plugins/inputs/webhooks/github"
|
||||
"github.com/influxdata/telegraf/plugins/inputs/webhooks/mandrill"
|
||||
"github.com/influxdata/telegraf/plugins/inputs/webhooks/rollbar"
|
||||
|
@ -26,9 +27,10 @@ func init() {
|
|||
type Webhooks struct {
|
||||
ServiceAddress string
|
||||
|
||||
Github *github.GithubWebhook
|
||||
Mandrill *mandrill.MandrillWebhook
|
||||
Rollbar *rollbar.RollbarWebhook
|
||||
Github *github.GithubWebhook
|
||||
Filestack *filestack.FilestackWebhook
|
||||
Mandrill *mandrill.MandrillWebhook
|
||||
Rollbar *rollbar.RollbarWebhook
|
||||
}
|
||||
|
||||
func NewWebhooks() *Webhooks {
|
||||
|
@ -40,6 +42,9 @@ func (wb *Webhooks) SampleConfig() string {
|
|||
## Address and port to host Webhook listener on
|
||||
service_address = ":1619"
|
||||
|
||||
[inputs.webhooks.filestack]
|
||||
path = "/filestack"
|
||||
|
||||
[inputs.webhooks.github]
|
||||
path = "/github"
|
||||
|
||||
|
|
Loading…
Reference in New Issue