Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Provider: Prometheus #186

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
# skyhook

Parses webhooks and forwards them in the proper format to Discord.

[![Discord](https://discordapp.com/api/guilds/303595820345851905/widget.png)](https://discord.gg/js7wD7p)

## Setup

You can use the [site](https://skyhookapi.com/) to create the right webhook link. If you want to manually do it, here are the steps:

1. Create a webhook in Discord (Server Settings -> Webhooks -> Create Webhook)
2. Copy the webhook url
3. Turn the Discord webhook url into a skyhook webhook url like so:

```
Replace discordapp.com in url with skyhookapi.com
https://discordapp.com/api/webhooks/firstPartOfWebhook/secondPartOfWebhook
->
https://skyhookapi.com/api/webhooks/firstPartOfWebhook/secondPartOfWebhook
```

4. Add the provider you want to the end of the url:

```
https://skyhookapi.com/api/webhooks/firstPartOfWebhook/secondPartOfWebhook/providerGoesHere
```

## Supported Providers

- [AppVeyor](https://www.appveyor.com/docs/notifications/#webhook-payload-default) - `/appveyor`
- [Basecamp 3](https://github.com/basecamp/bc3-api/blob/master/sections/webhooks.md) - `/basecamp`
- [BitBucket](https://confluence.atlassian.com/bitbucket/manage-webhooks-735643732.html) - `/bitbucket`
Expand All @@ -34,6 +42,7 @@ https://skyhookapi.com/api/webhooks/firstPartOfWebhook/secondPartOfWebhook/provi
- [NewRelic](https://docs.newrelic.com/docs/alerts/new-relic-alerts/managing-notification-channels/customize-your-webhook-payload) - `/newrelic`
- [Patreon](https://www.patreon.com/platform/documentation/webhooks) - `/patreon`
- [Pingdom](https://www.pingdom.com/resources/webhooks) - `/pingdom`
- [Prometheus](https://prometheus.io/docs/alerting/latest/configuration/#webhook_config) - `/prometheus`
- [Rollbar](https://docs.rollbar.com/docs/webhooks) - `/rollbar`
- [Travis](https://docs.travis-ci.com/user/notifications/#Webhooks-Delivery-Format) - `/travis`
- [Trello](https://developers.trello.com/apis/webhooks) - `/trello`
Expand All @@ -45,38 +54,50 @@ If you want support for a new provider, just create a pull request and add it!
Alternatively, a new provider can also be requested by creating an [issue](https://github.com/Commit451/skyhook/issues).

## Contributing

If you wish to contribute, follow our [contributing guide](CONTRIBUTING.md).

### Creating a Provider

If you want to create a new provider please follow the examples shown at our small [documentation](docs/CreateNewProvider.md).

## Testing Locally

To build:

```
npm run build
```

To run server (after building):

```
npm start
```

To run tests:

```
npm test
```

Through Docker:

```
docker run -it --rm -p 8080:8080 commit451/skyhook
```

## Deploying

- [Docker](docs/docker)
- [Google Cloud](docs/gcloud)

## Thanks

Special thanks to all our amazing contributors. skyhookapi.com is hosted for free for you, so if you feel so inclined, [buy a coffee!](https://ko-fi.com/jawnnypoo)

## License

skyhook is available under the MIT license. See the LICENSE file for more info.

\ ゜o゜)ノ
\ ゜ o ゜)ノ
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { Unity } from './provider/Unity'
import { UptimeRobot } from './provider/UptimeRobot'
import { VSTS } from './provider/VSTS'
import { Type } from './util/TSUtility'
import { Prometheus } from './provider/Prometheus'

dotenv.config()

Expand Down Expand Up @@ -58,6 +59,7 @@ const providers: Type<BaseProvider>[] = [
NewRelic,
Patreon,
Pingdom,
Prometheus,
Rollbar,
Travis,
Trello,
Expand Down
81 changes: 81 additions & 0 deletions src/provider/Prometheus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Embed, EmbedField, EmbedAuthor } from '../model/DiscordApi'
import { TypeParseProvder } from './BaseProvider'

export class Prometheus extends TypeParseProvder {
wh1337 marked this conversation as resolved.
Show resolved Hide resolved
private embed: Embed
constructor() {
super()
this.setEmbedColor(0x205081)
this.embed = {}
}

public preParse(): void {
this.headers = ['x-skyhook-event']
// Prometheus does not have a type, so we set our own.
this.headers['x-skyhook-event'] = 'fire'
}

public getName(): string {
return 'Prometheus'
}

public getType(): string | null {
// Prometheus does not have a type, so we set our own.
return this.headers['x-skyhook-event']
}

public knownTypes(): string[] {
return ['fire']
}

/**
* There is no event type for this provider. Creating a single
* method to handle all events.
*/
public async fire(): Promise<void> {
// Set Embed Author
this.embed.author = this.extractAuthor()

// Set Embed Title
this.embed.title = this.body.groupLabels?.alertname

this.embed.url = this.body.externalURL

// Set Embed Fields
this.embed.fields = this.extractAlertDescriptions()

this.addEmbed(this.embed)
}

private extractAuthor(): EmbedAuthor {
return {
name: 'Prometheus Alert',
icon_url: 'https://avatars.githubusercontent.com/u/3380462?s=200&v=4',
}
}

private extractAlertDescriptions(): EmbedField[] {
const fieldArray: EmbedField[] = []

// As per https://discord.com/developers/docs/resources/channel#embed-limits-limits
// Embed fields are limited to 25 fields.

if (this.body.alerts) {
for (let i = 0; i < Math.min(this.body.alerts.length, 25); i++) {
// Get current Alert
const alert = this.body.alerts[i]

// Push alert to fieldArray
fieldArray.push({
name: alert.labels.alertname,
value: alert.annotations.description,
inline: false,
})
}

return fieldArray
} else {
return []
}
}
}
10 changes: 10 additions & 0 deletions test/prometheus/prometheus-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { expect } from 'chai'
import { Tester } from '../Tester'
import { Prometheus } from '../../src/provider/Prometheus'

describe('/POST prometheus', () => {
it('fires when called', async () => {
const res = await Tester.test(new Prometheus(), 'prometheus.json')
expect(res).to.not.be.null
})
})
37 changes: 37 additions & 0 deletions test/prometheus/prometheus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"receiver": "webhook",
"status": "firing",
"alerts": [
{
"status": "firing",
"labels": {
"alertname": "API Latency",
"dc": "eu-west-1",
"instance": "localhost:9090",
"job": "prometheus24"
},
"annotations": {
"description": "API has a latency of greater than 200ms"
},
"startsAt": "2018-08-03T09:52:26.739266876+02:00",
"endsAt": "0001-01-01T00:00:00Z",
"generatorURL": "http://example.com:9090/graph?g0.expr=go_memstats_alloc_bytes+%3E+0\u0026g0.tab=1"
}
],
"groupLabels": {
"alertname": "API Latency",
"job": "prometheus24"
},
"commonLabels": {
"alertname": "Test",
"dc": "eu-west-1",
"instance": "localhost:9090",
"job": "prometheus24"
},
"commonAnnotations": {
"description": "some description"
},
"externalURL": "http://example.com:9093",
"version": "4",
"groupKey": "{}:{alertname=\"Test\", job=\"prometheus24\"}"
}