mirror of https://github.com/statping/statping
commit
cbb80bb55a
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,3 +1,13 @@
|
||||||
|
# 0.90.56 (06-25-2020)
|
||||||
|
- Modified metrics now include service name for each service metric
|
||||||
|
- Added switch for true/false notifier values
|
||||||
|
- Added list for notifiers that have static values (in drop down)
|
||||||
|
- Fixed oAuth form saving
|
||||||
|
- Fixed some HTTP Cookie issues
|
||||||
|
- Added error if Theme Editor returns an error from API
|
||||||
|
- Added Pushover priority and sounds
|
||||||
|
- Added HTTP headers for outgoing requests (includes User-Agent=Statping and Statping-Version=0.90.55)
|
||||||
|
|
||||||
# 0.90.55 (06-18-2020)
|
# 0.90.55 (06-18-2020)
|
||||||
- Added 404 page
|
- Added 404 page
|
||||||
- Modified Statping's PR process, dev -> master
|
- Modified Statping's PR process, dev -> master
|
||||||
|
|
|
@ -9,7 +9,7 @@ const errorReporter = "https://bed4d75404924cb3a799e370733a1b64@sentry.statping.
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
axios.defaults.withCredentials = true
|
||||||
}
|
}
|
||||||
|
|
||||||
async oauth() {
|
async oauth() {
|
||||||
|
@ -251,17 +251,13 @@ class Api {
|
||||||
}
|
}
|
||||||
|
|
||||||
token() {
|
token() {
|
||||||
const tk = $cookies.get(tokenKey)
|
return $cookies.get(tokenKey);
|
||||||
if (!tk) {
|
|
||||||
return {admin: false};
|
|
||||||
}
|
|
||||||
return tk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
authToken() {
|
authToken() {
|
||||||
const tk = $cookies.get(tokenKey)
|
const tk = $cookies.get(tokenKey)
|
||||||
if (tk.token) {
|
if (tk) {
|
||||||
return {'Authorization': 'Bearer ' + tk.token};
|
return {'Authorization': 'Bearer ' + tk};
|
||||||
} else {
|
} else {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,12 @@
|
||||||
},
|
},
|
||||||
async createAssets() {
|
async createAssets() {
|
||||||
this.pending = true
|
this.pending = true
|
||||||
const resp = await Api.theme_generate(true)
|
let resp
|
||||||
|
try {
|
||||||
|
resp = await Api.theme_generate(true)
|
||||||
|
} catch(e) {
|
||||||
|
this.error = e.response.data.error
|
||||||
|
}
|
||||||
this.pending = false
|
this.pending = false
|
||||||
await this.fetchTheme()
|
await this.fetchTheme()
|
||||||
},
|
},
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
this.$store.commit('setHasAllData', false)
|
this.$store.commit('setHasAllData', false)
|
||||||
this.$store.commit('setToken', null)
|
this.$store.commit('setToken', null)
|
||||||
this.$store.commit('setAdmin', false)
|
this.$store.commit('setAdmin', false)
|
||||||
this.$cookies.remove("statping_auth")
|
// this.$cookies.remove("statping_auth")
|
||||||
await this.$router.push('/logout')
|
await this.$router.push('/logout')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,16 @@
|
||||||
<td>8080</td>
|
<td>8080</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><kbd>{{"\{\{.Service.DowntimeAgo\}\}"}}</kbd></td>
|
<td><kbd>{{"\{\{.Service.Downtime.Human\}\}"}}</kbd></td>
|
||||||
<td>35 minutes ago</td>
|
<td>2 minutes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><kbd>{{"\{\{.Service.Uptime.Human\}\}"}}</kbd></td>
|
||||||
|
<td>13 hours</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><kbd>{{"\{\{.Service.Online\}\}"}}</kbd></td>
|
||||||
|
<td>true/false</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><kbd>{{"\{\{.Service.LastStatusCode\}\}"}}</kbd></td>
|
<td><kbd>{{"\{\{.Service.LastStatusCode\}\}"}}</kbd></td>
|
||||||
|
@ -49,6 +57,22 @@
|
||||||
<td><kbd>{{"\{\{.Service.FailuresLast24Hours\}\}"}}</kbd></td>
|
<td><kbd>{{"\{\{.Service.FailuresLast24Hours\}\}"}}</kbd></td>
|
||||||
<td>38</td>
|
<td>38</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><kbd>{{"\{\{.Service.LastOnline\}\}"}}</kbd></td>
|
||||||
|
<td>2020-11-05T13:15:30Z</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><kbd>{{"\{\{.Service.LastOffline\}\}"}}</kbd></td>
|
||||||
|
<td>2020-10-01T13:15:30Z</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><kbd>{{"\{\{.Service.Online24Hours\}\}"}}</kbd></td>
|
||||||
|
<td>0.99</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><kbd>{{"\{\{.Service.Online7Days\}\}"}}</kbd></td>
|
||||||
|
<td>0.97</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
<small>Additional variables within the Service struct</small>
|
<small>Additional variables within the Service struct</small>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -80,9 +80,8 @@
|
||||||
if (auth.error) {
|
if (auth.error) {
|
||||||
this.error = true
|
this.error = true
|
||||||
} else if (auth.token) {
|
} else if (auth.token) {
|
||||||
const u = {username: this.username, admin: auth.admin, token: auth.token}
|
// this.$cookies.set("statping_auth", auth.token)
|
||||||
this.$cookies.set("statping_auth", JSON.stringify(u))
|
await this.$store.dispatch('loadAdmin')
|
||||||
this.$store.dispatch('loadAdmin')
|
|
||||||
this.$store.commit('setAdmin', auth.admin)
|
this.$store.commit('setAdmin', auth.admin)
|
||||||
this.$router.push('/dashboard')
|
this.$router.push('/dashboard')
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,23 @@
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<p class="small text-muted" v-html="notifier.description"/>
|
<p class="small text-muted" v-html="notifier.description"/>
|
||||||
|
|
||||||
<div v-for="(form, index) in notifier.form" v-bind:key="index" class="form-group">
|
<div v-if="notifier.method==='mobile'" class="col-6 offset-3">
|
||||||
|
<img :src="qrcode" class="img-thumbnail">
|
||||||
|
<span class="text-muted small center">Scan this QR Code on the Statping Mobile App for quick setup</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="notifier.method!=='mobile'" v-for="(form, index) in notifier.form" v-bind:key="index" class="form-group">
|
||||||
<label class="text-capitalize">{{form.title}}</label>
|
<label class="text-capitalize">{{form.title}}</label>
|
||||||
<input v-if="form.type === 'text' || 'number' || 'password'" v-model="notifier[form.field.toLowerCase()]" :type="form.type" class="form-control" :placeholder="form.placeholder" >
|
<input v-if="formVisible(['text', 'number', 'password', 'email'], form)" v-model="notifier[form.field.toLowerCase()]" :type="form.type" class="form-control" :placeholder="form.placeholder" >
|
||||||
|
|
||||||
|
<select v-if="formVisible(['list'], form)" v-model="notifier[form.field.toLowerCase()]" class="form-control">
|
||||||
|
<option v-for="(val, k) in form.list_options" :value="val">{{val}}</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<span v-if="formVisible(['switch'], form)" @click="notifier[form.field.toLowerCase()] = !!notifier[form.field.toLowerCase()]" class="switch switch-rd-gr float-right mt-2">
|
||||||
|
<input v-model="notifier[form.field.toLowerCase()]" type="checkbox" class="switch-sm" :id="`switch_${notifier.name}_${form.field}`" v-bind:checked="notifier[form.field.toLowerCase()]">
|
||||||
|
<label class="mb-0" :for="`switch_${notifier.name}_${form.field}`"></label>
|
||||||
|
</span>
|
||||||
|
|
||||||
<small class="form-text text-muted" v-html="form.small_text"></small>
|
<small class="form-text text-muted" v-html="form.small_text"></small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -155,7 +169,7 @@ export default {
|
||||||
theme: 'neat',
|
theme: 'neat',
|
||||||
mode: "mymode",
|
mode: "mymode",
|
||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
json: true,
|
json: this.notifier.data_type === "json",
|
||||||
autoRefresh: true,
|
autoRefresh: true,
|
||||||
mime: this.notifier.data_type === "json" ? "application/json" : "text/plain"
|
mime: this.notifier.data_type === "json" ? "application/json" : "text/plain"
|
||||||
},
|
},
|
||||||
|
@ -163,9 +177,18 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
core() {
|
||||||
|
return this.$store.getters.core
|
||||||
|
},
|
||||||
|
qrcode() {
|
||||||
|
const u = `statping://setup?domain=${this.core.domain}&api=${this.core.api_secret}`
|
||||||
|
return "https://chart.googleapis.com/chart?chs=500x500&cht=qr&chl=" + encodeURIComponent(u)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
formVisible(want, form) {
|
||||||
|
return !!want.includes(form.type);
|
||||||
|
},
|
||||||
visible(isVisible, entry) {
|
visible(isVisible, entry) {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
this.$refs.cmfailure.codemirror.refresh()
|
this.$refs.cmfailure.codemirror.refresh()
|
||||||
|
@ -173,13 +196,19 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onCmSuccessReady(cm) {
|
onCmSuccessReady(cm) {
|
||||||
|
this.success_data = this.notifier.success_data
|
||||||
|
if (this.notifier.data_type === "json") {
|
||||||
this.success_data = beautify(this.notifier.success_data, this.beautifySettings)
|
this.success_data = beautify(this.notifier.success_data, this.beautifySettings)
|
||||||
|
}
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
cm.refresh();
|
cm.refresh();
|
||||||
},1);
|
},1);
|
||||||
},
|
},
|
||||||
onCmFailureReady(cm) {
|
onCmFailureReady(cm) {
|
||||||
|
this.failure_data = this.notifier.failure_data
|
||||||
|
if (this.notifier.data_type === "json") {
|
||||||
this.failure_data = beautify(this.notifier.failure_data, this.beautifySettings)
|
this.failure_data = beautify(this.notifier.failure_data, this.beautifySettings)
|
||||||
|
}
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
cm.refresh();
|
cm.refresh();
|
||||||
},1);
|
},1);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="saveOAuth">
|
<form @submit.prevent="saveOAuth">
|
||||||
{{core.oauth}}
|
|
||||||
<div class="card text-black-50 bg-white mb-3">
|
<div class="card text-black-50 bg-white mb-3">
|
||||||
<div class="card-header">Internal Login</div>
|
<div class="card-header">Internal Login</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
@ -146,8 +145,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="btn btn-primary btn-block" @click.prevent="saveOAuth" type="submit">
|
<button class="btn btn-primary btn-block" @click.prevent="saveOAuth" type="submit" :disabled="loading">
|
||||||
Save OAuth Settings
|
<font-awesome-icon v-if="loading" icon="circle-notch" class="mr-2" spin/> Save OAuth Settings
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
@ -162,9 +161,6 @@
|
||||||
core() {
|
core() {
|
||||||
return this.$store.getters.core
|
return this.$store.getters.core
|
||||||
},
|
},
|
||||||
auth() {
|
|
||||||
return this.$store.getters.oauth
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -172,6 +168,7 @@
|
||||||
slack_enabled: false,
|
slack_enabled: false,
|
||||||
github_enabled: false,
|
github_enabled: false,
|
||||||
local_enabled: false,
|
local_enabled: false,
|
||||||
|
loading: false,
|
||||||
oauth: {
|
oauth: {
|
||||||
gh_client_id: "",
|
gh_client_id: "",
|
||||||
gh_client_secret: "",
|
gh_client_secret: "",
|
||||||
|
@ -185,8 +182,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
async mounted() {
|
||||||
this.oauth = this.auth
|
this.oauth = await Api.oauth()
|
||||||
this.local_enabled = this.has('local')
|
this.local_enabled = this.has('local')
|
||||||
this.github_enabled = this.has('github')
|
this.github_enabled = this.has('github')
|
||||||
this.google_enabled = this.has('google')
|
this.google_enabled = this.has('google')
|
||||||
|
@ -216,12 +213,12 @@
|
||||||
return this.oauth.oauth_providers.split(",").includes(val)
|
return this.oauth.oauth_providers.split(",").includes(val)
|
||||||
},
|
},
|
||||||
async saveOAuth() {
|
async saveOAuth() {
|
||||||
let c = this.core
|
this.loading = true
|
||||||
c.oauth = this.oauth
|
this.oauth.oauth_providers = this.providers()
|
||||||
c.oauth.oauth_providers = this.providers()
|
await Api.oauth_save(this.oauth)
|
||||||
await Api.oauth_save(c)
|
|
||||||
const oauth = await Api.oauth()
|
const oauth = await Api.oauth()
|
||||||
this.$store.commit('setOAuth', oauth)
|
this.$store.commit('setOAuth', oauth)
|
||||||
|
this.loading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,12 +74,12 @@
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="text-capitalize">{{ $t('setup.project_name') }}</label>
|
<label class="text-capitalize">{{ $t('setup.project_name') }}</label>
|
||||||
<input @keyup="canSubmit" v-model="setup.project" id="project" type="text" class="form-control" placeholder="Great Uptime" required>
|
<input @keyup="canSubmit" v-model="setup.project" id="project" type="text" class="form-control" placeholder="Work Servers" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="text-capitalize">{{ $t('setup.project_description') }}</label>
|
<label class="text-capitalize">{{ $t('setup.project_description') }}</label>
|
||||||
<input @keyup="canSubmit" v-model="setup.description" id="description" type="text" class="form-control" placeholder="Great Uptime">
|
<input @keyup="canSubmit" v-model="setup.description" id="description" type="text" class="form-control" placeholder="Monitors all of my work services">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -100,6 +100,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="text-capitalize">{{ $t('setup.password_confirm') }}</label>
|
<label class="text-capitalize">{{ $t('setup.password_confirm') }}</label>
|
||||||
<input @keyup="canSubmit" v-model="setup.confirm_password" id="password_confirm" type="password" class="form-control" placeholder="password" required>
|
<input @keyup="canSubmit" v-model="setup.confirm_password" id="password_confirm" type="password" class="form-control" placeholder="password" required>
|
||||||
|
<span v-if="passnomatch" class="small text-danger">Both passwords should match</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -108,7 +109,7 @@
|
||||||
<label class="text-capitalize">{{ $t('email') }}</label>
|
<label class="text-capitalize">{{ $t('email') }}</label>
|
||||||
<input @keyup="canSubmit" v-model="setup.email" id="email" type="text" class="form-control" placeholder="myemail@domain.com">
|
<input @keyup="canSubmit" v-model="setup.email" id="email" type="text" class="form-control" placeholder="myemail@domain.com">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-4">
|
<div class="col-4 text-right">
|
||||||
<label class="d-none d-sm-block text-capitalize text-capitalize">{{ $t('setup.newsletter') }}</label>
|
<label class="d-none d-sm-block text-capitalize text-capitalize">{{ $t('setup.newsletter') }}</label>
|
||||||
<span @click="setup.newsletter = !!setup.newsletter" class="switch">
|
<span @click="setup.newsletter = !!setup.newsletter" class="switch">
|
||||||
<input v-model="setup.newsletter" type="checkbox" name="send_newsletter" class="switch" id="send_newsletter" :checked="setup.newsletter">
|
<input v-model="setup.newsletter" type="checkbox" name="send_newsletter" class="switch" id="send_newsletter" :checked="setup.newsletter">
|
||||||
|
@ -145,6 +146,7 @@
|
||||||
error: null,
|
error: null,
|
||||||
loading: false,
|
loading: false,
|
||||||
disabled: true,
|
disabled: true,
|
||||||
|
passnomatch: false,
|
||||||
setup: {
|
setup: {
|
||||||
language: "en",
|
language: "en",
|
||||||
db_connection: "sqlite",
|
db_connection: "sqlite",
|
||||||
|
@ -186,6 +188,11 @@
|
||||||
canSubmit() {
|
canSubmit() {
|
||||||
this.error = null
|
this.error = null
|
||||||
const s = this.setup
|
const s = this.setup
|
||||||
|
if (s.confirm_password.length > 0 && s.confirm_password !== s.password) {
|
||||||
|
this.passnomatch = true
|
||||||
|
} else {
|
||||||
|
this.passnomatch = false
|
||||||
|
}
|
||||||
if (s.db_connection !== 'sqlite') {
|
if (s.db_connection !== 'sqlite') {
|
||||||
if (!s.db_host || !s.db_port || !s.db_user || !s.db_password || !s.db_database) {
|
if (!s.db_host || !s.db_port || !s.db_user || !s.db_password || !s.db_database) {
|
||||||
this.disabled = true
|
this.disabled = true
|
||||||
|
|
|
@ -38,7 +38,7 @@ const routes = [
|
||||||
beforeEnter: async (to, from, next) => {
|
beforeEnter: async (to, from, next) => {
|
||||||
if (to.matched.some(record => record.meta.requiresAuth)) {
|
if (to.matched.some(record => record.meta.requiresAuth)) {
|
||||||
let tk = await Api.token()
|
let tk = await Api.token()
|
||||||
if (to.path !== '/login' && !tk.admin) {
|
if (to.path !== '/login' && !tk) {
|
||||||
next('/login')
|
next('/login')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,9 +147,9 @@ export default new Vuex.Store({
|
||||||
const core = await Api.core()
|
const core = await Api.core()
|
||||||
const token = await Api.token()
|
const token = await Api.token()
|
||||||
context.commit("setCore", core);
|
context.commit("setCore", core);
|
||||||
context.commit('setAdmin', token.admin)
|
context.commit('setAdmin', token)
|
||||||
context.commit('setCore', core)
|
context.commit('setCore', core)
|
||||||
context.commit('setUser', token.token!==undefined)
|
context.commit('setUser', token!==undefined)
|
||||||
},
|
},
|
||||||
async loadRequired(context) {
|
async loadRequired(context) {
|
||||||
const groups = await Api.groups()
|
const groups = await Api.groups()
|
||||||
|
@ -170,14 +170,8 @@ export default new Vuex.Store({
|
||||||
const messages = await Api.messages()
|
const messages = await Api.messages()
|
||||||
context.commit("setMessages", messages)
|
context.commit("setMessages", messages)
|
||||||
context.commit("setHasPublicData", true)
|
context.commit("setHasPublicData", true)
|
||||||
try {
|
|
||||||
const checkins = await Api.checkins()
|
const checkins = await Api.checkins()
|
||||||
context.commit("setCheckins", checkins);
|
context.commit("setCheckins", checkins);
|
||||||
} catch(e) {
|
|
||||||
window.console.error(e)
|
|
||||||
await Api.logout()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const notifiers = await Api.notifiers()
|
const notifiers = await Api.notifiers()
|
||||||
context.commit("setNotifiers", notifiers);
|
context.commit("setNotifiers", notifiers);
|
||||||
const users = await Api.users()
|
const users = await Api.users()
|
||||||
|
|
|
@ -3,14 +3,23 @@ module.exports = {
|
||||||
assetsDir: 'assets',
|
assetsDir: 'assets',
|
||||||
filenameHashing: false,
|
filenameHashing: false,
|
||||||
devServer: {
|
devServer: {
|
||||||
proxy: {
|
disableHostCheck: true,
|
||||||
|
proxyTable: {
|
||||||
'/api': {
|
'/api': {
|
||||||
logLevel: 'debug',
|
logLevel: 'debug',
|
||||||
target: 'http://0.0.0.0:8585'
|
target: 'http://0.0.0.0:8585',
|
||||||
|
changeOrigin: true,
|
||||||
|
pathRewrite: {
|
||||||
|
'^/api': ''
|
||||||
|
}
|
||||||
},
|
},
|
||||||
'/oauth': {
|
'/oauth': {
|
||||||
logLevel: 'debug',
|
logLevel: 'debug',
|
||||||
target: 'http://0.0.0.0:8585/oauth/'
|
target: 'http://0.0.0.0:8585',
|
||||||
|
changeOrigin: true,
|
||||||
|
pathRewrite: {
|
||||||
|
'^/oauth': ''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,13 +46,20 @@ func apiRenewHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func apiUpdateOAuthHandler(w http.ResponseWriter, r *http.Request) {
|
func apiUpdateOAuthHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var c core.OAuth
|
var c core.OAuth
|
||||||
err := DecodeJSON(r, &c)
|
if err := DecodeJSON(r, &c); err != nil {
|
||||||
if err != nil {
|
|
||||||
sendErrorJson(err, w, r)
|
sendErrorJson(err, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
app := core.App
|
app := core.App
|
||||||
app.OAuth = c
|
app.OAuth = c
|
||||||
|
if err := app.Update(); err != nil {
|
||||||
|
sendErrorJson(err, w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(app)
|
||||||
|
|
||||||
sendJsonAction(app.OAuth, "update", w, r)
|
sendJsonAction(app.OAuth, "update", w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
jwtKey string
|
jwtKey []byte
|
||||||
httpServer *http.Server
|
httpServer *http.Server
|
||||||
usingSSL bool
|
usingSSL bool
|
||||||
mainTmpl = `{{define "main" }} {{ template "base" . }} {{ end }}`
|
mainTmpl = `{{define "main" }} {{ template "base" . }} {{ end }}`
|
||||||
|
@ -96,7 +96,11 @@ func IsFullAuthenticated(r *http.Request) bool {
|
||||||
if ok := hasAuthorizationHeader(r); ok {
|
if ok := hasAuthorizationHeader(r); ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return IsAdmin(r)
|
claim, err := getJwtToken(r)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return claim.Admin
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScopeName will show private JSON fields in the API.
|
// ScopeName will show private JSON fields in the API.
|
||||||
|
|
|
@ -33,7 +33,7 @@ func setJwtToken(user *users.User, w http.ResponseWriter) (JwtClaim, string) {
|
||||||
ExpiresAt: expirationTime.Unix(),
|
ExpiresAt: expirationTime.Unix(),
|
||||||
}}
|
}}
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwtClaim)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwtClaim)
|
||||||
tokenString, err := token.SignedString([]byte(jwtKey))
|
tokenString, err := token.SignedString(jwtKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("error setting token: ", err)
|
log.Errorln("error setting token: ", err)
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ func setJwtToken(user *users.User, w http.ResponseWriter) (JwtClaim, string) {
|
||||||
Value: tokenString,
|
Value: tokenString,
|
||||||
Expires: expirationTime,
|
Expires: expirationTime,
|
||||||
MaxAge: int(time.Duration(72 * time.Hour).Seconds()),
|
MaxAge: int(time.Duration(72 * time.Hour).Seconds()),
|
||||||
|
Path: "/",
|
||||||
})
|
})
|
||||||
return jwtClaim, tokenString
|
return jwtClaim, tokenString
|
||||||
}
|
}
|
||||||
|
@ -56,11 +57,12 @@ func getJwtToken(r *http.Request) (JwtClaim, error) {
|
||||||
}
|
}
|
||||||
return JwtClaim{}, err
|
return JwtClaim{}, err
|
||||||
}
|
}
|
||||||
tknStr := c.Value
|
|
||||||
var claims JwtClaim
|
var claims JwtClaim
|
||||||
tkn, err := jwt.ParseWithClaims(tknStr, &claims, func(token *jwt.Token) (interface{}, error) {
|
tkn, err := jwt.ParseWithClaims(c.Value, &claims, func(token *jwt.Token) (interface{}, error) {
|
||||||
return []byte(jwtKey), nil
|
return jwtKey, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == jwt.ErrSignatureInvalid {
|
if err == jwt.ErrSignatureInvalid {
|
||||||
return JwtClaim{}, err
|
return JwtClaim{}, err
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"github.com/statping/statping/types/users"
|
"github.com/statping/statping/types/users"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
"golang.org/x/oauth2/github"
|
|
||||||
"golang.org/x/oauth2/google"
|
"golang.org/x/oauth2/google"
|
||||||
"golang.org/x/oauth2/slack"
|
"golang.org/x/oauth2/slack"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -51,40 +50,18 @@ func oauthHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func oauthLogin(oauth *oAuth, w http.ResponseWriter, r *http.Request) {
|
func oauthLogin(oauth *oAuth, w http.ResponseWriter, r *http.Request) {
|
||||||
log.Infoln(oauth)
|
|
||||||
user := &users.User{
|
user := &users.User{
|
||||||
Id: 0,
|
Id: 0,
|
||||||
Username: oauth.Username,
|
Username: oauth.Username,
|
||||||
Email: oauth.Email,
|
Email: oauth.Email,
|
||||||
Admin: null.NewNullBool(true),
|
Admin: null.NewNullBool(true),
|
||||||
}
|
}
|
||||||
log.Infoln(fmt.Sprintf("OAuth User %s logged in from IP %s", oauth.Email, r.RemoteAddr))
|
log.Infoln(fmt.Sprintf("OAuth %s User %s logged in from IP %s", oauth.Type, oauth.Email, r.RemoteAddr))
|
||||||
|
|
||||||
setJwtToken(user, w)
|
setJwtToken(user, w)
|
||||||
|
|
||||||
//returnJson(user, w, r)
|
//returnJson(user, w, r)
|
||||||
http.Redirect(w, r, core.App.Domain, http.StatusPermanentRedirect)
|
http.Redirect(w, r, core.App.Domain+"/dashboard", http.StatusPermanentRedirect)
|
||||||
}
|
|
||||||
|
|
||||||
func githubOAuth(r *http.Request) (*oAuth, error) {
|
|
||||||
c := *core.App
|
|
||||||
code := r.URL.Query().Get("code")
|
|
||||||
|
|
||||||
config := &oauth2.Config{
|
|
||||||
ClientID: c.OAuth.GithubClientID,
|
|
||||||
ClientSecret: c.OAuth.GithubClientSecret,
|
|
||||||
Endpoint: github.Endpoint,
|
|
||||||
}
|
|
||||||
|
|
||||||
gg, err := config.Exchange(r.Context(), code)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &oAuth{
|
|
||||||
Token: gg.AccessToken,
|
|
||||||
RefreshToken: gg.RefreshToken,
|
|
||||||
Valid: gg.Valid(),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func googleOAuth(r *http.Request) (*oAuth, error) {
|
func googleOAuth(r *http.Request) (*oAuth, error) {
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/statping/statping/types/core"
|
||||||
|
"github.com/statping/statping/utils"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
"golang.org/x/oauth2/github"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func githubOAuth(r *http.Request) (*oAuth, error) {
|
||||||
|
c := *core.App
|
||||||
|
code := r.URL.Query().Get("code")
|
||||||
|
|
||||||
|
config := &oauth2.Config{
|
||||||
|
ClientID: c.OAuth.GithubClientID,
|
||||||
|
ClientSecret: c.OAuth.GithubClientSecret,
|
||||||
|
Endpoint: github.Endpoint,
|
||||||
|
}
|
||||||
|
|
||||||
|
gg, err := config.Exchange(r.Context(), code)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
headers := []string{
|
||||||
|
"Accept=application/vnd.github.machine-man-preview+json",
|
||||||
|
"Authorization=token " + gg.AccessToken,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, _, err := utils.HttpRequest("https://api.github.com/user", "GET", nil, headers, nil, 10*time.Second, true, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var user githubUser
|
||||||
|
if err := json.Unmarshal(resp, &user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &oAuth{
|
||||||
|
Token: gg.AccessToken,
|
||||||
|
RefreshToken: gg.RefreshToken,
|
||||||
|
Valid: gg.Valid(),
|
||||||
|
Username: strings.ToLower(user.Name),
|
||||||
|
Email: strings.ToLower(user.Email),
|
||||||
|
Type: "github",
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type githubUser struct {
|
||||||
|
Login string `json:"login"`
|
||||||
|
ID int `json:"id"`
|
||||||
|
NodeID string `json:"node_id"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
GravatarID string `json:"gravatar_id"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
FollowersURL string `json:"followers_url"`
|
||||||
|
FollowingURL string `json:"following_url"`
|
||||||
|
GistsURL string `json:"gists_url"`
|
||||||
|
StarredURL string `json:"starred_url"`
|
||||||
|
SubscriptionsURL string `json:"subscriptions_url"`
|
||||||
|
OrganizationsURL string `json:"organizations_url"`
|
||||||
|
ReposURL string `json:"repos_url"`
|
||||||
|
EventsURL string `json:"events_url"`
|
||||||
|
ReceivedEventsURL string `json:"received_events_url"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
SiteAdmin bool `json:"site_admin"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Company string `json:"company"`
|
||||||
|
Blog string `json:"blog"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Hireable bool `json:"hireable"`
|
||||||
|
Bio string `json:"bio"`
|
||||||
|
TwitterUsername string `json:"twitter_username"`
|
||||||
|
PublicRepos int `json:"public_repos"`
|
||||||
|
PublicGists int `json:"public_gists"`
|
||||||
|
Followers int `json:"followers"`
|
||||||
|
Following int `json:"following"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
PrivateGists int `json:"private_gists"`
|
||||||
|
TotalPrivateRepos int `json:"total_private_repos"`
|
||||||
|
OwnedPrivateRepos int `json:"owned_private_repos"`
|
||||||
|
DiskUsage int `json:"disk_usage"`
|
||||||
|
Collaborators int `json:"collaborators"`
|
||||||
|
TwoFactorAuthentication bool `json:"two_factor_authentication"`
|
||||||
|
Plan struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Space int `json:"space"`
|
||||||
|
PrivateRepos int `json:"private_repos"`
|
||||||
|
Collaborators int `json:"collaborators"`
|
||||||
|
} `json:"plan"`
|
||||||
|
}
|
|
@ -1,12 +1,10 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
sentryhttp "github.com/getsentry/sentry-go/http"
|
sentryhttp "github.com/getsentry/sentry-go/http"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
"github.com/statping/statping/source"
|
"github.com/statping/statping/source"
|
||||||
"github.com/statping/statping/types/core"
|
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/pprof"
|
"net/http/pprof"
|
||||||
|
@ -192,5 +190,5 @@ func resetRouter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func resetCookies() {
|
func resetCookies() {
|
||||||
jwtKey = fmt.Sprintf("%s_%d", core.App.ApiSecret, utils.Now().Nanosecond())
|
jwtKey = []byte(utils.NewSHA256Hash())
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ var email = &emailer{¬ifications.Notification{
|
||||||
Type: "switch",
|
Type: "switch",
|
||||||
Title: "Disable TLS/SSL",
|
Title: "Disable TLS/SSL",
|
||||||
Placeholder: "",
|
Placeholder: "",
|
||||||
SmallText: "To Disable TLS/SSL insert 'true'",
|
SmallText: "Enabling this will set Insecure Skip Verify to true",
|
||||||
DbField: "api_key",
|
DbField: "api_key",
|
||||||
}}},
|
}}},
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ var Pushover = &pushover{¬ifications.Notification{
|
||||||
Form: []notifications.NotificationForm{{
|
Form: []notifications.NotificationForm{{
|
||||||
Type: "text",
|
Type: "text",
|
||||||
Title: "User Token",
|
Title: "User Token",
|
||||||
Placeholder: "Insert your device's Pushover Token",
|
Placeholder: "Insert your Pushover User Token",
|
||||||
DbField: "api_key",
|
DbField: "api_key",
|
||||||
Required: true,
|
Required: true,
|
||||||
}, {
|
}, {
|
||||||
|
@ -50,16 +50,51 @@ var Pushover = &pushover{¬ifications.Notification{
|
||||||
Placeholder: "Create an Application and insert the API Key here",
|
Placeholder: "Create an Application and insert the API Key here",
|
||||||
DbField: "api_secret",
|
DbField: "api_secret",
|
||||||
Required: true,
|
Required: true,
|
||||||
|
}, {
|
||||||
|
Type: "list",
|
||||||
|
Title: "Priority",
|
||||||
|
Placeholder: "Set the notification priority level",
|
||||||
|
DbField: "Var1",
|
||||||
|
Required: true,
|
||||||
|
ListOptions: []string{"Lowest", "Low", "Normal", "High", "Emergency"},
|
||||||
|
}, {
|
||||||
|
Type: "list",
|
||||||
|
Title: "Notification Sound",
|
||||||
|
Placeholder: "Choose a sound for this Pushover notification",
|
||||||
|
DbField: "Var2",
|
||||||
|
Required: true,
|
||||||
|
ListOptions: []string{"none", "pushover", "bike", "bugle", "cashregister", "classical", "cosmic", "falling", "gamelan", "incoming", "intermissioon", "magic", "mechanical", "painobar", "siren", "spacealarm", "tugboat", "alien", "climb", "persistent", "echo", "updown"},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func priority(val string) string {
|
||||||
|
switch strings.ToLower(val) {
|
||||||
|
case "lowest":
|
||||||
|
return "-2"
|
||||||
|
case "low":
|
||||||
|
return "-1"
|
||||||
|
case "normal":
|
||||||
|
return "0"
|
||||||
|
case "high":
|
||||||
|
return "1"
|
||||||
|
case "emergency":
|
||||||
|
return "2"
|
||||||
|
default:
|
||||||
|
return "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Send will send a HTTP Post to the Pushover API. It accepts type: string
|
// Send will send a HTTP Post to the Pushover API. It accepts type: string
|
||||||
func (t *pushover) sendMessage(message string) (string, error) {
|
func (t *pushover) sendMessage(message string) (string, error) {
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
v.Set("token", t.ApiSecret)
|
v.Set("token", t.ApiSecret)
|
||||||
v.Set("user", t.ApiKey)
|
v.Set("user", t.ApiKey)
|
||||||
v.Set("message", message)
|
v.Set("message", message)
|
||||||
|
v.Set("priority", priority(t.Var1))
|
||||||
|
if t.Var2 != "" {
|
||||||
|
v.Set("sound", t.Var2)
|
||||||
|
}
|
||||||
rb := strings.NewReader(v.Encode())
|
rb := strings.NewReader(v.Encode())
|
||||||
|
|
||||||
content, _, err := utils.HttpRequest(pushoverUrl, "POST", "application/x-www-form-urlencoded", nil, rb, time.Duration(10*time.Second), true, nil)
|
content, _, err := utils.HttpRequest(pushoverUrl, "POST", "application/x-www-form-urlencoded", nil, rb, time.Duration(10*time.Second), true, nil)
|
||||||
|
|
|
@ -50,13 +50,13 @@ var Twilio = &twilio{¬ifications.Notification{
|
||||||
DbField: "api_secret",
|
DbField: "api_secret",
|
||||||
Required: true,
|
Required: true,
|
||||||
}, {
|
}, {
|
||||||
Type: "text",
|
Type: "number",
|
||||||
Title: "SMS to Phone Number",
|
Title: "SMS to Phone Number",
|
||||||
Placeholder: "18555555555",
|
Placeholder: "18555555555",
|
||||||
DbField: "Var1",
|
DbField: "Var1",
|
||||||
Required: true,
|
Required: true,
|
||||||
}, {
|
}, {
|
||||||
Type: "text",
|
Type: "number",
|
||||||
Title: "From Phone Number",
|
Title: "From Phone Number",
|
||||||
Placeholder: "18555555555",
|
Placeholder: "18555555555",
|
||||||
DbField: "Var2",
|
DbField: "Var2",
|
||||||
|
|
|
@ -31,9 +31,9 @@ var Webhook = &webhooker{¬ifications.Notification{
|
||||||
Author: "Hunter Long",
|
Author: "Hunter Long",
|
||||||
AuthorUrl: "https://github.com/hunterlong",
|
AuthorUrl: "https://github.com/hunterlong",
|
||||||
Icon: "fas fa-code-branch",
|
Icon: "fas fa-code-branch",
|
||||||
Delay: time.Duration(1 * time.Second),
|
Delay: time.Duration(3 * time.Second),
|
||||||
SuccessData: `{"id": {{.Service.Id}}, "online": true}`,
|
SuccessData: `{"id": "{{.Service.Id}}", "online": true}`,
|
||||||
FailureData: `{"id": {{.Service.Id}}, "online": false}`,
|
FailureData: `{"id": "{{.Service.Id}}", "online": false}`,
|
||||||
DataType: "json",
|
DataType: "json",
|
||||||
Limits: 180,
|
Limits: 180,
|
||||||
Form: []notifications.NotificationForm{{
|
Form: []notifications.NotificationForm{{
|
||||||
|
@ -44,12 +44,13 @@ var Webhook = &webhooker{¬ifications.Notification{
|
||||||
DbField: "Host",
|
DbField: "Host",
|
||||||
Required: true,
|
Required: true,
|
||||||
}, {
|
}, {
|
||||||
Type: "text",
|
Type: "list",
|
||||||
Title: "HTTP Method",
|
Title: "HTTP Method",
|
||||||
Placeholder: "POST",
|
Placeholder: "POST",
|
||||||
SmallText: "Choose a HTTP method for example: GET, POST, DELETE, or PATCH.",
|
SmallText: "Choose a HTTP method for example: GET, POST, DELETE, or PATCH.",
|
||||||
DbField: "Var1",
|
DbField: "Var1",
|
||||||
Required: true,
|
Required: true,
|
||||||
|
ListOptions: []string{"GET", "POST", "PATCH", "DELETE"},
|
||||||
}, {
|
}, {
|
||||||
Type: "text",
|
Type: "text",
|
||||||
Title: "Content Type",
|
Title: "Content Type",
|
||||||
|
@ -82,8 +83,7 @@ func (w *webhooker) sendHttpWebhook(body string) (*http.Response, error) {
|
||||||
utils.Log.Infoln(fmt.Sprintf("sending body: '%v' to %v as a %v request", body, w.Host, w.Var1))
|
utils.Log.Infoln(fmt.Sprintf("sending body: '%v' to %v as a %v request", body, w.Host, w.Var1))
|
||||||
client := new(http.Client)
|
client := new(http.Client)
|
||||||
client.Timeout = time.Duration(10 * time.Second)
|
client.Timeout = time.Duration(10 * time.Second)
|
||||||
var buf *bytes.Buffer
|
buf := bytes.NewBuffer(nil)
|
||||||
buf = bytes.NewBuffer(nil)
|
|
||||||
if w.Var2 != "" {
|
if w.Var2 != "" {
|
||||||
buf = bytes.NewBuffer([]byte(body))
|
buf = bytes.NewBuffer([]byte(body))
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,7 @@ func (w *webhooker) sendHttpWebhook(body string) (*http.Response, error) {
|
||||||
req.Header.Add("Content-Type", w.ApiKey)
|
req.Header.Add("Content-Type", w.ApiKey)
|
||||||
}
|
}
|
||||||
req.Header.Set("User-Agent", "Statping")
|
req.Header.Set("User-Agent", "Statping")
|
||||||
|
req.Header.Set("Statping-Version", utils.Version)
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -28,7 +28,6 @@ func (f *Failure) AfterDelete() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Failure) AfterCreate() {
|
func (f *Failure) AfterCreate() {
|
||||||
metrics.Inc("failure", f.Service)
|
|
||||||
metrics.Query("failure", "create")
|
metrics.Query("failure", "create")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ func (h *Hit) AfterDelete() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hit) AfterCreate() {
|
func (h *Hit) AfterCreate() {
|
||||||
metrics.Inc("success", h.Service)
|
|
||||||
metrics.Query("hit", "create")
|
metrics.Query("hit", "create")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ var (
|
||||||
Name: "service_online",
|
Name: "service_online",
|
||||||
Help: "If service is online",
|
Help: "If service is online",
|
||||||
},
|
},
|
||||||
[]string{"service", "name", "type"},
|
[]string{"service", "type"},
|
||||||
)
|
)
|
||||||
|
|
||||||
// service failures
|
// service failures
|
||||||
|
|
|
@ -88,7 +88,7 @@ func isIPv6(address string) bool {
|
||||||
// checkIcmp will send a ICMP ping packet to the service
|
// checkIcmp will send a ICMP ping packet to the service
|
||||||
func CheckIcmp(s *Service, record bool) (*Service, error) {
|
func CheckIcmp(s *Service, record bool) (*Service, error) {
|
||||||
defer s.updateLastCheck()
|
defer s.updateLastCheck()
|
||||||
timer := prometheus.NewTimer(metrics.ServiceTimer(s.Id))
|
timer := prometheus.NewTimer(metrics.ServiceTimer(s.Name))
|
||||||
defer timer.ObserveDuration()
|
defer timer.ObserveDuration()
|
||||||
|
|
||||||
if err := utils.Ping(s.Domain, s.Timeout); err != nil {
|
if err := utils.Ping(s.Domain, s.Timeout); err != nil {
|
||||||
|
@ -105,7 +105,7 @@ func CheckIcmp(s *Service, record bool) (*Service, error) {
|
||||||
// CheckGrpc will check a gRPC service
|
// CheckGrpc will check a gRPC service
|
||||||
func CheckGrpc(s *Service, record bool) (*Service, error) {
|
func CheckGrpc(s *Service, record bool) (*Service, error) {
|
||||||
defer s.updateLastCheck()
|
defer s.updateLastCheck()
|
||||||
timer := prometheus.NewTimer(metrics.ServiceTimer(s.Id))
|
timer := prometheus.NewTimer(metrics.ServiceTimer(s.Name))
|
||||||
defer timer.ObserveDuration()
|
defer timer.ObserveDuration()
|
||||||
|
|
||||||
dnsLookup, err := dnsCheck(s)
|
dnsLookup, err := dnsCheck(s)
|
||||||
|
@ -152,7 +152,7 @@ func CheckGrpc(s *Service, record bool) (*Service, error) {
|
||||||
// checkTcp will check a TCP service
|
// checkTcp will check a TCP service
|
||||||
func CheckTcp(s *Service, record bool) (*Service, error) {
|
func CheckTcp(s *Service, record bool) (*Service, error) {
|
||||||
defer s.updateLastCheck()
|
defer s.updateLastCheck()
|
||||||
timer := prometheus.NewTimer(metrics.ServiceTimer(s.Id))
|
timer := prometheus.NewTimer(metrics.ServiceTimer(s.Name))
|
||||||
defer timer.ObserveDuration()
|
defer timer.ObserveDuration()
|
||||||
|
|
||||||
dnsLookup, err := dnsCheck(s)
|
dnsLookup, err := dnsCheck(s)
|
||||||
|
@ -219,7 +219,7 @@ func (s *Service) updateLastCheck() {
|
||||||
// checkHttp will check a HTTP service
|
// checkHttp will check a HTTP service
|
||||||
func CheckHttp(s *Service, record bool) (*Service, error) {
|
func CheckHttp(s *Service, record bool) (*Service, error) {
|
||||||
defer s.updateLastCheck()
|
defer s.updateLastCheck()
|
||||||
timer := prometheus.NewTimer(metrics.ServiceTimer(s.Id))
|
timer := prometheus.NewTimer(metrics.ServiceTimer(s.Name))
|
||||||
defer timer.ObserveDuration()
|
defer timer.ObserveDuration()
|
||||||
|
|
||||||
dnsLookup, err := dnsCheck(s)
|
dnsLookup, err := dnsCheck(s)
|
||||||
|
@ -285,7 +285,7 @@ func CheckHttp(s *Service, record bool) (*Service, error) {
|
||||||
s.LastResponse = string(content)
|
s.LastResponse = string(content)
|
||||||
s.LastStatusCode = res.StatusCode
|
s.LastStatusCode = res.StatusCode
|
||||||
|
|
||||||
metrics.Gauge("status_code", float64(res.StatusCode), s.Id)
|
metrics.Gauge("status_code", float64(res.StatusCode), s.Name)
|
||||||
|
|
||||||
if s.Expected.String != "" {
|
if s.Expected.String != "" {
|
||||||
match, err := regexp.MatchString(s.Expected.String, string(content))
|
match, err := regexp.MatchString(s.Expected.String, string(content))
|
||||||
|
@ -329,7 +329,8 @@ func recordSuccess(s *Service) {
|
||||||
fmt.Sprintf("Service #%d '%v' Successful Response: %s | Lookup in: %s | Online: %v | Interval: %d seconds", s.Id, s.Name, humanMicro(hit.Latency), humanMicro(hit.PingTime), s.Online, s.Interval))
|
fmt.Sprintf("Service #%d '%v' Successful Response: %s | Lookup in: %s | Online: %v | Interval: %d seconds", s.Id, s.Name, humanMicro(hit.Latency), humanMicro(hit.PingTime), s.Online, s.Interval))
|
||||||
s.LastLookupTime = hit.PingTime
|
s.LastLookupTime = hit.PingTime
|
||||||
s.LastLatency = hit.Latency
|
s.LastLatency = hit.Latency
|
||||||
metrics.Gauge("online", 1., s.Id, s.Name, s.Type)
|
metrics.Gauge("online", 1., s.Name, s.Type)
|
||||||
|
metrics.Inc("success", s.Name)
|
||||||
sendSuccess(s)
|
sendSuccess(s)
|
||||||
s.SuccessNotified = true
|
s.SuccessNotified = true
|
||||||
}
|
}
|
||||||
|
@ -383,7 +384,8 @@ func recordFailure(s *Service, issue string) {
|
||||||
s.Online = false
|
s.Online = false
|
||||||
s.SuccessNotified = false
|
s.SuccessNotified = false
|
||||||
s.DownText = s.DowntimeText()
|
s.DownText = s.DowntimeText()
|
||||||
metrics.Gauge("online", 0., s.Id, s.Name, s.Type)
|
metrics.Gauge("online", 0., s.Name, s.Type)
|
||||||
|
metrics.Inc("failure", s.Name)
|
||||||
sendFailure(s, fail)
|
sendFailure(s, fail)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ func InitEnvs() {
|
||||||
Log.Errorln(err)
|
Log.Errorln(err)
|
||||||
defaultDir = "."
|
defaultDir = "."
|
||||||
}
|
}
|
||||||
Params.Set("VERSION", version)
|
Params.Set("VERSION", Version)
|
||||||
Params.SetDefault("DISABLE_HTTP", false)
|
Params.SetDefault("DISABLE_HTTP", false)
|
||||||
Params.SetDefault("STATPING_DIR", defaultDir)
|
Params.SetDefault("STATPING_DIR", defaultDir)
|
||||||
Params.SetDefault("GO_ENV", "production")
|
Params.SetDefault("GO_ENV", "production")
|
||||||
|
|
|
@ -21,7 +21,7 @@ var (
|
||||||
LastLines []*logRow
|
LastLines []*logRow
|
||||||
LockLines sync.Mutex
|
LockLines sync.Mutex
|
||||||
VerboseMode int
|
VerboseMode int
|
||||||
version string
|
Version string
|
||||||
allowReports bool
|
allowReports bool
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ func SentryInit(v *string, allow bool) {
|
||||||
if *v == "" {
|
if *v == "" {
|
||||||
*v = "development"
|
*v = "development"
|
||||||
}
|
}
|
||||||
version = *v
|
Version = *v
|
||||||
}
|
}
|
||||||
goEnv := Params.GetString("GO_ENV")
|
goEnv := Params.GetString("GO_ENV")
|
||||||
allowReports := Params.GetBool("ALLOW_REPORTS")
|
allowReports := Params.GetBool("ALLOW_REPORTS")
|
||||||
|
@ -44,7 +44,7 @@ func SentryInit(v *string, allow bool) {
|
||||||
if err := sentry.Init(sentry.ClientOptions{
|
if err := sentry.Init(sentry.ClientOptions{
|
||||||
Dsn: errorReporter,
|
Dsn: errorReporter,
|
||||||
Environment: goEnv,
|
Environment: goEnv,
|
||||||
Release: version,
|
Release: Version,
|
||||||
AttachStacktrace: true,
|
AttachStacktrace: true,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
Log.Errorln(err)
|
Log.Errorln(err)
|
||||||
|
@ -63,7 +63,7 @@ func SentryErr(err error) {
|
||||||
func SentryLogEntry(entry *Logger.Entry) {
|
func SentryLogEntry(entry *Logger.Entry) {
|
||||||
e := sentry.NewEvent()
|
e := sentry.NewEvent()
|
||||||
e.Message = entry.Message
|
e.Message = entry.Message
|
||||||
e.Release = version
|
e.Release = Version
|
||||||
e.Contexts = entry.Data
|
e.Contexts = entry.Data
|
||||||
sentry.CaptureEvent(e)
|
sentry.CaptureEvent(e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,6 +217,10 @@ func HttpRequest(url, method string, content interface{}, headers []string, body
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req.Header.Set("User-Agent", "Statping")
|
||||||
|
req.Header.Set("Statping-Version", Version)
|
||||||
|
|
||||||
var resp *http.Response
|
var resp *http.Response
|
||||||
|
|
||||||
dialer := &net.Dialer{
|
dialer := &net.Dialer{
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.90.55
|
0.90.56
|
||||||
|
|
Loading…
Reference in New Issue