mirror of
https://github.com/onedr0p/exportarr.git
synced 2026-02-06 10:57:32 +00:00
initial commit
This commit is contained in:
commit
fe0019c383
7
.dockerignore
Normal file
7
.dockerignore
Normal file
@ -0,0 +1,7 @@
|
||||
.git
|
||||
.github/
|
||||
.gitignore
|
||||
Dockerfile
|
||||
LICENSE
|
||||
README.md
|
||||
k8s/
|
||||
32
.github/workflows/main.yml
vendored
Normal file
32
.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
name: main
|
||||
on:
|
||||
push:
|
||||
branches: master
|
||||
tags:
|
||||
- v*
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: crazy-max/ghaction-docker-buildx@v1
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Login to GitHub Docker Registry
|
||||
run: echo "${DOCKERHUB_PASSWORD}" | docker login -u "${DOCKERHUB_USERNAME}" --password-stdin
|
||||
env:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Build Container Image
|
||||
run: |
|
||||
docker buildx build \
|
||||
-t onedr0p/radarr-exporter:${GITHUB_REF##*/} \
|
||||
--platform linux/amd64,linux/arm/v7,linux/arm64 \
|
||||
-f ./build/package/Dockerfile \
|
||||
--push .
|
||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
./radarr-exporter
|
||||
/vendor/
|
||||
/.idea/
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Devin Buhl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
120
README.md
Normal file
120
README.md
Normal file
@ -0,0 +1,120 @@
|
||||
# radarr-exporter
|
||||
|
||||
Prometheus Exporter for Radarr
|
||||
|
||||
[](https://hub.docker.com/r/onedr0p/radarr-exporter)
|
||||
[](https://goreportcard.com/report/github.com/onedr0p/radarr-exporter)
|
||||
|
||||
## Usage
|
||||
|
||||
|Name |Description |Default |
|
||||
|----------------------------|-------------------------------------------------------------|-----------------------|
|
||||
|`RADARR_URL` |Your Radarr URL |`http://127.0.0.1:7878`|
|
||||
|`RADARR_APIKEY` |Your Radarr API Key | |
|
||||
|`RADARR_BASIC_AUTH_ENABLED` |Set to `true` to enable Basic Auth |`false` |
|
||||
|`RADARR_BASIC_AUTH_USERNAME`|Set to your username if enabled Basic Auth | |
|
||||
|`RADARR_BASIC_AUTH_PASSWORD`|Set to your password if enabled Basic Auth | |
|
||||
|`DISABLE_SSL_VERIFY` |Set to `true` to disable SSL verification (use with caution) |`false` |
|
||||
|`LISTEN_PORT` |The port the exporter will listen on |`9707` |
|
||||
|`LISTEN_IP` |The IP the exporter will listen on |`0.0.0.0` |
|
||||
|`LOG_LEVEL` |Set the default Log Level |`INFO` |
|
||||
|
||||
### Run with Docker Compose
|
||||
|
||||
```yaml
|
||||
version: '3.7'
|
||||
services:
|
||||
radarr-exporter:
|
||||
image: onedr0p/radarr-exporter:v2.2.0
|
||||
environment:
|
||||
RADARR_URL: "http://localhost:7878"
|
||||
RADARR_APIKEY: "..."
|
||||
```
|
||||
|
||||
### Run with Kubernetes
|
||||
|
||||
See [radarr-exporter.yaml](./examples/kubernetes/radarr-exporter.yaml)
|
||||
|
||||
### Run with the command line
|
||||
|
||||
```cmd
|
||||
NAME:
|
||||
radarr-exporter start -
|
||||
|
||||
USAGE:
|
||||
radarr-exporter start [command options] [arguments...]
|
||||
|
||||
DESCRIPTION:
|
||||
Radarr Exporter
|
||||
|
||||
OPTIONS:
|
||||
--listen-port value Port the exporter will listen on (default: 9707) [$LISTEN_PORT]
|
||||
--listen-ip value IP the exporter will listen on (default: "0.0.0.0") [$LISTEN_IP]
|
||||
--log-level value Set the default Log Level (default: "INFO") [$LOG_LEVEL]
|
||||
--disable-ssl-verify Disable SSL Verifications (default: false) [$DISABLE_SSL_VERIFY]
|
||||
--url value Full URL to Radarr (default: "http://localhost:7878") [$RADARR_URL]
|
||||
--api-key value Radarr's API Key (default: "") [$RADARR_APIKEY]
|
||||
--basic-auth-enabled Enable Basic Auth (default: false) [$RADARR_BASIC_AUTH_ENABLED]
|
||||
--basic-auth-username value If Basic Auth is enabled, provide the username (default: "") [$RADARR_BASIC_AUTH_USERNAME]
|
||||
--basic-auth-password value If Basic Auth is enabled, provide the password (default: "") [$RADARR_BASIC_AUTH_PASSWORD]
|
||||
--help, -h show help (default: false)
|
||||
```
|
||||
|
||||
### Metrics
|
||||
|
||||
> **Note:** Due to changes in versions, these may not reflect what is currently being exported.
|
||||
|
||||
```bash
|
||||
# HELP radarr_history_total Total number of records in history
|
||||
# TYPE radarr_history_total gauge
|
||||
radarr_history_total{url="http://localhost:7878"} 6174
|
||||
# HELP radarr_movie_download_total Total number of downloaded movies
|
||||
# TYPE radarr_movie_download_total gauge
|
||||
radarr_movie_download_total{url="http://localhost:7878"} 4717
|
||||
# HELP radarr_movie_missing_total Total number of missing movies
|
||||
# TYPE radarr_movie_missing_total gauge
|
||||
radarr_movie_missing_total{url="http://localhost:7878"} 97
|
||||
# HELP radarr_movie_monitored_total Total number of monitored movies
|
||||
# TYPE radarr_movie_monitored_total gauge
|
||||
radarr_movie_monitored_total{url="http://localhost:7878"} 155
|
||||
# HELP radarr_movie_quality_total Total number of downloaded movies by quality
|
||||
# TYPE radarr_movie_quality_total gauge
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="Bluray-1080p"} 1222
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="Bluray-480p"} 99
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="Bluray-576p"} 267
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="Bluray-720p"} 1004
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="DVD"} 1347
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="HDTV-1080p"} 43
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="HDTV-720p"} 46
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="Remux-1080p"} 48
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="SDTV"} 25
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="WEBDL-1080p"} 465
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="WEBDL-480p"} 53
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="WEBDL-720p"} 94
|
||||
radarr_movie_quality_total{url="http://localhost:7878",quality="WEBRip-1080p"} 2
|
||||
# HELP radarr_movie_total Total number of movies
|
||||
# TYPE radarr_movie_total gauge
|
||||
radarr_movie_total{url="http://localhost:7878"} 4817
|
||||
# HELP radarr_movie_unmonitored_total Total number of unmonitored movies
|
||||
# TYPE radarr_movie_unmonitored_total gauge
|
||||
radarr_movie_unmonitored_total{url="http://localhost:7878"} 4662
|
||||
# HELP radarr_movies_bytes Total file size of all movies in bytes
|
||||
# TYPE radarr_movies_bytes gauge
|
||||
radarr_movie_bytes{url="http://localhost:7878"} 2.3326478328365e+13
|
||||
# HELP radarr_queue_total Total number of movies in queue by status
|
||||
# TYPE radarr_queue_total gauge
|
||||
radarr_queue_total{url="http://localhost:7878",status="Ok"} 1
|
||||
radarr_queue_total{url="http://localhost:7878",status="Warning"} 9
|
||||
# HELP radarr_root_folder_space_bytes Root folder space in bytes
|
||||
# TYPE radarr_root_folder_space_bytes gauge
|
||||
radarr_rootfolder_freespace_bytes{folder="/media/Library/Movies/",url="http://localhost:7878"} 2.5011930497024e+13
|
||||
# HELP radarr_status System Status
|
||||
# TYPE radarr_status gauge
|
||||
radarr_status{url="http://localhost:7878"} 1
|
||||
# HELP radarr_health_issues Health issues in Radarr
|
||||
# TYPE radarr_health_issues gauge
|
||||
radarr_health_issues{url="http://localhost:7878",message="Branch develop is for a previous version of Radarr, set branch to 'Aphrodite' for further updates",type="error",wikiurl="https://github.com/Radarr/Radarr/wiki/Health-checks#branch-develop-is-for-a-previous-version-of-radarr-set-branch-to-aphrodite-for-further-updates"} 1
|
||||
radarr_health_issues{url="http://localhost:7878",message="No download client is available",type="warning",wikiurl="https://github.com/Radarr/Radarr/wiki/Health-checks#no-download-client-is-available"} 1
|
||||
radarr_health_issues{url="http://localhost:7878",message="No indexers available with Automatic Search enabled, Radarr will not provide any automatic search results",type="warning",wikiurl="https://github.com/Radarr/Radarr/wiki/Health-checks#no-indexers-available-with-automatic-search-enabled-radarr-will-not-provide-any-automatic-search-results"} 1
|
||||
radarr_health_issues{url="http://localhost:7878",message="No indexers available with RSS sync enabled, Radarr will not grab new releases automatically",type="error",wikiurl="https://github.com/Radarr/Radarr/wiki/Health-checks#no-indexers-available-with-rss-sync-enabled-radarr-will-not-grab-new-releases-automatically"} 1
|
||||
```
|
||||
25
build/package/Dockerfile
Normal file
25
build/package/Dockerfile
Normal file
@ -0,0 +1,25 @@
|
||||
FROM golang:1.14-alpine as build
|
||||
|
||||
ENV GO111MODULE=on \
|
||||
CGO_ENABLED=0
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN apk --no-cache add ca-certificates \
|
||||
&& export GOOS=$(echo ${TARGETPLATFORM} | cut -d / -f1) \
|
||||
&& export GOARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \
|
||||
&& GOARM=$(echo ${TARGETPLATFORM} | cut -d / -f3); export GOARM=${GOARM:1} \
|
||||
&& go mod download \
|
||||
&& go build -a -tags netgo -ldflags '-w -extldflags "-static"' -o radarr-exporter /build/cmd/radarr-exporter/. \
|
||||
&& chmod +x radarr-exporter
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
|
||||
COPY --from=build /build/radarr-exporter /
|
||||
|
||||
ENTRYPOINT ["/radarr-exporter"]
|
||||
CMD ["start"]
|
||||
298
cmd/exportarr/main.go
Normal file
298
cmd/exportarr/main.go
Normal file
@ -0,0 +1,298 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/onedr0p/exportarr/internal/collector"
|
||||
"github.com/onedr0p/exportarr/internal/handlers"
|
||||
"github.com/onedr0p/exportarr/internal/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "Exportarr"
|
||||
app.EnableBashCompletion = true
|
||||
app.HideVersion = true
|
||||
app.Authors = []*cli.Author{
|
||||
&cli.Author{
|
||||
Name: "onedr0p",
|
||||
Email: "onedr0p@users.noreply.github.com",
|
||||
},
|
||||
&cli.Author{
|
||||
Name: "DirtyCajunRice",
|
||||
Email: "DirtyCajunRice@users.noreply.github.com",
|
||||
},
|
||||
}
|
||||
app.Commands = []*cli.Command{
|
||||
{
|
||||
Name: "radarr",
|
||||
Aliases: []string{"r"},
|
||||
Description: strings.Title("Radarr Exporter"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: "listen-port",
|
||||
Usage: "Port the exporter will listen on",
|
||||
Value: 9707,
|
||||
Required: false,
|
||||
EnvVars: []string{"RADARR_LISTEN_PORT"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "listen-ip",
|
||||
Usage: "IP the exporter will listen on",
|
||||
Value: "0.0.0.0",
|
||||
Required: false,
|
||||
EnvVars: []string{"RADARR_LISTEN_IP"},
|
||||
},
|
||||
// Move to top level arg?
|
||||
&cli.StringFlag{
|
||||
Name: "log-level",
|
||||
Usage: "Set the default Log Level",
|
||||
Value: "INFO",
|
||||
Required: false,
|
||||
EnvVars: []string{"RADARR_LOG_LEVEL"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "disable-ssl-verify",
|
||||
Usage: "Disable SSL Verifications",
|
||||
Value: false,
|
||||
Required: false,
|
||||
EnvVars: []string{"RADARR_DISABLE_SSL_VERIFY"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "url",
|
||||
Value: "http://127.0.0.1:7878",
|
||||
Usage: "Full URL to Radarr",
|
||||
Required: false,
|
||||
EnvVars: []string{"RADARR_URL"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "api-key",
|
||||
Usage: "Radarr's API Key",
|
||||
Required: true,
|
||||
EnvVars: []string{"RADARR_APIKEY"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "basic-auth-enabled",
|
||||
Usage: "Enable Basic Auth",
|
||||
Value: false,
|
||||
Required: false,
|
||||
EnvVars: []string{"RADARR_BASIC_AUTH_ENABLED"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "basic-auth-username",
|
||||
Usage: "If Basic Auth is enabled, provide the username",
|
||||
Required: false,
|
||||
EnvVars: []string{"RADARR_BASIC_AUTH_USERNAME"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "basic-auth-password",
|
||||
Usage: "If Basic Auth is enabled, provide the password",
|
||||
Required: false,
|
||||
EnvVars: []string{"RADARR_BASIC_AUTH_PASSWORD"},
|
||||
},
|
||||
},
|
||||
Action: radarr,
|
||||
},
|
||||
{
|
||||
Name: "sonarr",
|
||||
Aliases: []string{"s"},
|
||||
Description: strings.Title("Sonarr Exporter"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: "listen-port",
|
||||
Usage: "Port the exporter will listen on",
|
||||
Value: 9707,
|
||||
Required: false,
|
||||
EnvVars: []string{"SONARR_LISTEN_PORT"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "listen-ip",
|
||||
Usage: "IP the exporter will listen on",
|
||||
Value: "0.0.0.0",
|
||||
Required: false,
|
||||
EnvVars: []string{"SONARR_LISTEN_IP"},
|
||||
},
|
||||
// Move to top level arg?
|
||||
&cli.StringFlag{
|
||||
Name: "log-level",
|
||||
Usage: "Set the default Log Level",
|
||||
Value: "INFO",
|
||||
Required: false,
|
||||
EnvVars: []string{"SONARR_LOG_LEVEL"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "disable-ssl-verify",
|
||||
Usage: "Disable SSL Verifications",
|
||||
Value: false,
|
||||
Required: false,
|
||||
EnvVars: []string{"SONARR_DISABLE_SSL_VERIFY"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "url",
|
||||
Value: "http://127.0.0.1:7878",
|
||||
Usage: "Full URL to Radarr",
|
||||
Required: false,
|
||||
EnvVars: []string{"SONARR_URL"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "api-key",
|
||||
Usage: "Radarr's API Key",
|
||||
Required: true,
|
||||
EnvVars: []string{"SONARR_APIKEY"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "basic-auth-enabled",
|
||||
Usage: "Enable Basic Auth",
|
||||
Value: false,
|
||||
Required: false,
|
||||
EnvVars: []string{"SONARR_BASIC_AUTH_ENABLED"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "basic-auth-username",
|
||||
Usage: "If Basic Auth is enabled, provide the username",
|
||||
Required: false,
|
||||
EnvVars: []string{"SONARR_BASIC_AUTH_USERNAME"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "basic-auth-password",
|
||||
Usage: "If Basic Auth is enabled, provide the password",
|
||||
Required: false,
|
||||
EnvVars: []string{"SONARR_BASIC_AUTH_PASSWORD"},
|
||||
},
|
||||
},
|
||||
Action: sonarr,
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func radarr(c *cli.Context) (err error) {
|
||||
// Wire up Logging
|
||||
switch strings.ToUpper(c.String("log-level")) {
|
||||
case "TRACE":
|
||||
log.SetLevel(log.TraceLevel)
|
||||
case "DEBUG":
|
||||
log.SetLevel(log.DebugLevel)
|
||||
case "INFO":
|
||||
log.SetLevel(log.InfoLevel)
|
||||
case "WARN":
|
||||
log.SetLevel(log.WarnLevel)
|
||||
default:
|
||||
log.SetLevel(log.InfoLevel)
|
||||
}
|
||||
log.SetFormatter(&log.TextFormatter{})
|
||||
log.SetOutput(os.Stdout)
|
||||
|
||||
// Validate Url
|
||||
if !utils.IsValidUrl(c.String("url")) {
|
||||
log.Fatalf("%s is not a proper URL", c.String("url"))
|
||||
}
|
||||
|
||||
// Validate API Key
|
||||
if !utils.IsValidApikey(c.String("api-key")) {
|
||||
log.Fatalf("%s is not a proper API Key", c.String("api-key"))
|
||||
}
|
||||
|
||||
// Register the Collectors
|
||||
r := prometheus.NewRegistry()
|
||||
r.MustRegister(
|
||||
collector.NewMovieCollector(c),
|
||||
collector.NewQueueCollector(c),
|
||||
collector.NewHistoryCollector(c),
|
||||
collector.NewRootFolderCollector(c),
|
||||
collector.NewSystemStatusCollector(c),
|
||||
collector.NewSystemHealthCollector(c),
|
||||
)
|
||||
|
||||
// Set up the handlers
|
||||
handler := promhttp.HandlerFor(r, promhttp.HandlerOpts{})
|
||||
http.HandleFunc("/", handlers.IndexHandler)
|
||||
http.HandleFunc("/healthz", handlers.HealthzHandler)
|
||||
http.Handle("/metrics", handler)
|
||||
|
||||
// Serve up the metrics
|
||||
log.Infof("Listening on %s:%d", c.String("listen-ip"), c.Int("listen-port"))
|
||||
httpErr := http.ListenAndServe(
|
||||
fmt.Sprintf("%s:%d", c.String("listen-ip"), c.Int("listen-port")),
|
||||
logRequest(http.DefaultServeMux),
|
||||
)
|
||||
if httpErr != nil {
|
||||
return httpErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sonarr(c *cli.Context) (err error) {
|
||||
// Wire up Logging
|
||||
switch strings.ToUpper(c.String("log-level")) {
|
||||
case "TRACE":
|
||||
log.SetLevel(log.TraceLevel)
|
||||
case "DEBUG":
|
||||
log.SetLevel(log.DebugLevel)
|
||||
case "INFO":
|
||||
log.SetLevel(log.InfoLevel)
|
||||
case "WARN":
|
||||
log.SetLevel(log.WarnLevel)
|
||||
default:
|
||||
log.SetLevel(log.InfoLevel)
|
||||
}
|
||||
log.SetFormatter(&log.TextFormatter{})
|
||||
log.SetOutput(os.Stdout)
|
||||
|
||||
// Validate Url
|
||||
if !utils.IsValidUrl(c.String("url")) {
|
||||
log.Fatalf("%s is not a proper URL", c.String("url"))
|
||||
}
|
||||
|
||||
// Validate API Key
|
||||
if !utils.IsValidApikey(c.String("api-key")) {
|
||||
log.Fatalf("%s is not a proper API Key", c.String("api-key"))
|
||||
}
|
||||
|
||||
// Register the Collectors
|
||||
r := prometheus.NewRegistry()
|
||||
r.MustRegister(
|
||||
collector.NewMovieCollector(c),
|
||||
collector.NewQueueCollector(c),
|
||||
collector.NewHistoryCollector(c),
|
||||
collector.NewRootFolderCollector(c),
|
||||
collector.NewSystemStatusCollector(c),
|
||||
collector.NewSystemHealthCollector(c),
|
||||
)
|
||||
|
||||
// Set up the handlers
|
||||
handler := promhttp.HandlerFor(r, promhttp.HandlerOpts{})
|
||||
http.HandleFunc("/", handlers.IndexHandler)
|
||||
http.HandleFunc("/healthz", handlers.HealthzHandler)
|
||||
http.Handle("/metrics", handler)
|
||||
|
||||
// Serve up the metrics
|
||||
log.Infof("Listening on %s:%d", c.String("listen-ip"), c.Int("listen-port"))
|
||||
httpErr := http.ListenAndServe(
|
||||
fmt.Sprintf("%s:%d", c.String("listen-ip"), c.Int("listen-port")),
|
||||
logRequest(http.DefaultServeMux),
|
||||
)
|
||||
if httpErr != nil {
|
||||
return httpErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Log internal request to stdout
|
||||
func logRequest(handler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debugf("%s %s %s\n", r.RemoteAddr, r.Method, r.URL)
|
||||
handler.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
648
examples/grafana/dashboard.json
Normal file
648
examples/grafana/dashboard.json
Normal file
@ -0,0 +1,648 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": 30,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"datasource": "Prometheus",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 7,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"fieldOptions": {
|
||||
"calcs": [
|
||||
"last"
|
||||
],
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"from": "",
|
||||
"id": 1,
|
||||
"operator": "",
|
||||
"text": "Online",
|
||||
"to": "",
|
||||
"type": 1,
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"from": "",
|
||||
"id": 2,
|
||||
"operator": "",
|
||||
"text": "Offline",
|
||||
"to": "",
|
||||
"type": 1,
|
||||
"value": "null"
|
||||
},
|
||||
{
|
||||
"from": "",
|
||||
"id": 3,
|
||||
"operator": "",
|
||||
"text": "Offline",
|
||||
"to": "",
|
||||
"type": 1,
|
||||
"value": "0"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "rgb(255, 194, 48)",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"title": "status"
|
||||
},
|
||||
"overrides": [],
|
||||
"values": false
|
||||
},
|
||||
"graphMode": "area",
|
||||
"justifyMode": "center",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"pluginVersion": "6.6.2",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "radarr_system_status",
|
||||
"format": "time_series",
|
||||
"instant": true,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": "Prometheus",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 4,
|
||||
"x": 7,
|
||||
"y": 0
|
||||
},
|
||||
"id": 4,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"fieldOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"from": "",
|
||||
"id": 1,
|
||||
"operator": "",
|
||||
"text": "0",
|
||||
"to": "",
|
||||
"type": 1,
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "rgb(255, 194, 48)",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"title": "in queue",
|
||||
"unit": "locale"
|
||||
},
|
||||
"overrides": [],
|
||||
"values": false
|
||||
},
|
||||
"graphMode": "none",
|
||||
"justifyMode": "center",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"pluginVersion": "6.6.2",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(radarr_queue_total)",
|
||||
"format": "table",
|
||||
"instant": true,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": "Prometheus",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 4,
|
||||
"x": 11,
|
||||
"y": 0
|
||||
},
|
||||
"id": 5,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"fieldOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "rgb(255, 194, 48)",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"title": "missing",
|
||||
"unit": "locale"
|
||||
},
|
||||
"overrides": [],
|
||||
"values": false
|
||||
},
|
||||
"graphMode": "none",
|
||||
"justifyMode": "center",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"pluginVersion": "6.6.2",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "radarr_movie_missing_total",
|
||||
"format": "table",
|
||||
"instant": true,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": "Prometheus",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 4,
|
||||
"x": 15,
|
||||
"y": 0
|
||||
},
|
||||
"id": 3,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"fieldOptions": {
|
||||
"calcs": [
|
||||
"last"
|
||||
],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "rgb(255, 194, 48)",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"title": "wanted",
|
||||
"unit": "locale"
|
||||
},
|
||||
"overrides": [],
|
||||
"values": false
|
||||
},
|
||||
"graphMode": "none",
|
||||
"justifyMode": "center",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"pluginVersion": "6.6.2",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "radarr_movie_wanted_total",
|
||||
"format": "table",
|
||||
"instant": true,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": "Prometheus",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 7,
|
||||
"x": 0,
|
||||
"y": 5
|
||||
},
|
||||
"id": 6,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"fieldOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"from": "",
|
||||
"id": 1,
|
||||
"operator": "",
|
||||
"text": "0",
|
||||
"to": "",
|
||||
"type": 1,
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "rgb(255, 194, 48)",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"title": "movies",
|
||||
"unit": "locale"
|
||||
},
|
||||
"overrides": [],
|
||||
"values": false
|
||||
},
|
||||
"graphMode": "none",
|
||||
"justifyMode": "center",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"pluginVersion": "6.6.2",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "radarr_movie_total",
|
||||
"format": "table",
|
||||
"instant": true,
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": "Prometheus",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 4,
|
||||
"x": 7,
|
||||
"y": 5
|
||||
},
|
||||
"id": 10,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"fieldOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"from": "",
|
||||
"id": 1,
|
||||
"operator": "",
|
||||
"text": "0",
|
||||
"to": "",
|
||||
"type": 1,
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "rgb(255, 194, 48)",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"title": "monitored",
|
||||
"unit": "locale"
|
||||
},
|
||||
"overrides": [],
|
||||
"values": false
|
||||
},
|
||||
"graphMode": "none",
|
||||
"justifyMode": "center",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"pluginVersion": "6.6.2",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "radarr_movie_monitored_total",
|
||||
"format": "table",
|
||||
"instant": true,
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": "Prometheus",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 4,
|
||||
"x": 11,
|
||||
"y": 5
|
||||
},
|
||||
"id": 8,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"fieldOptions": {
|
||||
"calcs": [
|
||||
"last"
|
||||
],
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"from": "",
|
||||
"id": 1,
|
||||
"operator": "",
|
||||
"text": "0",
|
||||
"to": "",
|
||||
"type": 1,
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "rgb(255, 194, 48)",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"title": "d/l past month",
|
||||
"unit": "locale"
|
||||
},
|
||||
"overrides": [],
|
||||
"values": false
|
||||
},
|
||||
"graphMode": "none",
|
||||
"justifyMode": "center",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"pluginVersion": "6.6.2",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(increase(radarr_movie_download_total[30d]))",
|
||||
"format": "table",
|
||||
"instant": true,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": "Prometheus",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 4,
|
||||
"x": 15,
|
||||
"y": 5
|
||||
},
|
||||
"id": 7,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"fieldOptions": {
|
||||
"calcs": [
|
||||
"last"
|
||||
],
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"from": "",
|
||||
"id": 1,
|
||||
"operator": "",
|
||||
"text": "0",
|
||||
"to": "",
|
||||
"type": 1,
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "rgb(255, 194, 48)",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"title": "d/l past week",
|
||||
"unit": "locale"
|
||||
},
|
||||
"overrides": [],
|
||||
"values": false
|
||||
},
|
||||
"graphMode": "none",
|
||||
"justifyMode": "center",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"pluginVersion": "6.6.2",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(increase(radarr_movie_download_total[7d]))",
|
||||
"format": "table",
|
||||
"instant": true,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": true,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "Prometheus",
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 10,
|
||||
"w": 19,
|
||||
"x": 0,
|
||||
"y": 10
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 13,
|
||||
"legend": {
|
||||
"alignAsTable": false,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"hideEmpty": false,
|
||||
"hideZero": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": false,
|
||||
"show": false,
|
||||
"sideWidth": null,
|
||||
"total": true,
|
||||
"values": true
|
||||
},
|
||||
"lines": false,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"dataLinks": []
|
||||
},
|
||||
"percentage": false,
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sort_desc(sum(radarr_movie_quality_total) by (quality))",
|
||||
"format": "time_series",
|
||||
"instant": true,
|
||||
"legendFormat": "{{quality}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "",
|
||||
"tooltip": {
|
||||
"shared": false,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "series",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": [
|
||||
"total"
|
||||
]
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"decimals": null,
|
||||
"format": "locale",
|
||||
"label": "movies by quality",
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"datasource": "loki",
|
||||
"gridPos": {
|
||||
"h": 11,
|
||||
"w": 19,
|
||||
"x": 0,
|
||||
"y": 20
|
||||
},
|
||||
"id": 15,
|
||||
"options": {
|
||||
"showLabels": false,
|
||||
"showTime": false,
|
||||
"sortOrder": "Descending",
|
||||
"wrapLogMessage": true
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "{app_kubernetes_io_name=\"radarr\"}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "",
|
||||
"type": "logs"
|
||||
}
|
||||
],
|
||||
"refresh": "1m",
|
||||
"schemaVersion": 22,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-2d",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "Radarr",
|
||||
"uid": "A8iPssjZk",
|
||||
"version": 12
|
||||
}
|
||||
98
examples/kubernetes/radarr-exporter.yaml
Normal file
98
examples/kubernetes/radarr-exporter.yaml
Normal file
@ -0,0 +1,98 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: radarr-exporter
|
||||
namespace: monitoring
|
||||
labels:
|
||||
app.kubernetes.io/name: radarr-exporter
|
||||
app.kubernetes.io/instance: radarr-exporter
|
||||
spec:
|
||||
clusterIP: None
|
||||
selector:
|
||||
app.kubernetes.io/name: radarr-exporter
|
||||
app.kubernetes.io/instance: radarr-exporter
|
||||
ports:
|
||||
- name: monitoring
|
||||
port: 9707
|
||||
---
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: radarr-exporter
|
||||
namespace: monitoring
|
||||
labels:
|
||||
app.kubernetes.io/name: radarr-exporter
|
||||
app.kubernetes.io/instance: radarr-exporter
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: radarr-exporter
|
||||
app.kubernetes.io/instance: radarr-exporter
|
||||
endpoints:
|
||||
- port: monitoring
|
||||
interval: 4m
|
||||
path: /metrics
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: radarr-exporter
|
||||
namespace: monitoring
|
||||
labels:
|
||||
app.kubernetes.io/name: radarr-exporter
|
||||
app.kubernetes.io/instance: radarr-exporter
|
||||
annotations:
|
||||
fluxcd.io/ignore: "false"
|
||||
fluxcd.io/automated: "true"
|
||||
fluxcd.io/tag.radarr-exporter: semver:~v2.2
|
||||
spec:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: radarr-exporter
|
||||
app.kubernetes.io/instance: radarr-exporter
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: radarr-exporter
|
||||
app.kubernetes.io/instance: radarr-exporter
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "monitoring"
|
||||
spec:
|
||||
containers:
|
||||
- name: radarr-exporter
|
||||
image: onedr0p/radarr-exporter:v2.2.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: RADARR_URL
|
||||
value: "http://radarr.default.svc.cluster.local:7878"
|
||||
- name: RADARR_APIKEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: radarr-exporter
|
||||
key: api-key
|
||||
ports:
|
||||
- name: monitoring
|
||||
containerPort: 9707
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: monitoring
|
||||
failureThreshold: 5
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: monitoring
|
||||
failureThreshold: 5
|
||||
periodSeconds: 10
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 256Mi
|
||||
12
go.mod
Normal file
12
go.mod
Normal file
@ -0,0 +1,12 @@
|
||||
module github.com/onedr0p/radarr-exporter
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/prometheus/client_golang v1.5.1
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/urfave/cli/v2 v2.2.0
|
||||
gitlab.com/onedr0p/radarr-exporter v1.0.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
|
||||
gopkg.in/yaml.v2 v2.2.7 // indirect
|
||||
)
|
||||
351
go.sum
Normal file
351
go.sum
Normal file
@ -0,0 +1,351 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
|
||||
github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
||||
github.com/SAP/go-hdb v0.14.1/go.mod h1:7fdQLVC2lER3urZLjZCm0AuMQfApof92n3aylBPEkMo=
|
||||
github.com/SermoDigital/jose v0.9.1/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.3+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20190423183735-731ef375ac02/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/frankban/quicktest v1.5.0/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gocql/gocql v0.0.0-20190423091413-b99afaf3b163/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.8.6/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||
github.com/hashicorp/go-hclog v0.9.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-memdb v1.0.1/go.mod h1:I6dKdmYhZqU0RJSheVEWgTNWdVQH5QvTgIUQ0t/t32M=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-plugin v1.0.0/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-math-big v0.0.0-20180316142257-561262b71329/go.mod h1:eBwVNKMPVQvPzsL2kU1sgH+Wf3xcmgFCvFSyGDEUSgc=
|
||||
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hashicorp/vault v0.9.6/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/heetch/confita v0.9.0/go.mod h1:PQQ3Rx11s2c3+6hB/HIUpD/dZPCRtkXAULzM5w3xeNk=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jefferai/jsonx v1.0.0/go.mod h1:OGmqmi2tTeI/PS+qQfBDToLHHJIy/RMp24fPo8vFvoQ=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/keybase/go-crypto v0.0.0-20190416182011-b785b22cc757/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/mgutz/logxi v0.0.0-20161027140823-aebf8a7d67ab/go.mod h1:y1pL58r5z2VvAjeG1VLGc8zOQgSOzbKN7kMHPvFXJ+8=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA=
|
||||
github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U=
|
||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/go-glob v0.0.0-20160226084822-572520ed46db/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sethgrid/pester v0.0.0-20180227223404-ed9870dad317/go.mod h1:Ad7IjTpvzZO8Fl0vh9AzQ+j/jYZfyp2diGwI8m5q+ns=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4=
|
||||
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
gitlab.com/onedr0p/radarr-exporter v1.0.0 h1:/La6UkpQNoTEZZLq6Kz2I8PvWqq+ez9DHANAgnwAn0o=
|
||||
gitlab.com/onedr0p/radarr-exporter v1.0.0/go.mod h1:h+GBCNBRakBxCJV0MBieD9s1taZOIE9oukmJyMZtBRg=
|
||||
gitlab.com/onedr0p/sonarr-exporter v1.0.0/go.mod h1:8YLpw4jl63MaM6xnYdZd8rCB/ybeeZc3XiRN8SGMnJU=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190508220229-2d0786266e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/ory-am/dockertest.v3 v3.3.4/go.mod h1:s9mmoLkaGeAh97qygnNj4xWkiN7e1SKekYC6CovU+ek=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
63
internal/client/client.go
Normal file
63
internal/client/client.go
Normal file
@ -0,0 +1,63 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Client struct is a Radarr client to request an instance of a Radarr
|
||||
type Client struct {
|
||||
config *cli.Context
|
||||
httpClient http.Client
|
||||
}
|
||||
|
||||
// NewClient method initializes a new Radarr client.
|
||||
func NewClient(c *cli.Context) *Client {
|
||||
return &Client{
|
||||
config: c,
|
||||
httpClient: http.Client{
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// DoRequest - Take a HTTP Request and return Unmarshaled data
|
||||
func (c *Client) DoRequest(endpoint string, target interface{}) error {
|
||||
url := fmt.Sprintf("%s/api/v3/%s", c.config.String("url"), endpoint)
|
||||
|
||||
log.Infof("Sending HTTP request to %s", url)
|
||||
|
||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: c.config.Bool("disable-ssl-verify")}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if c.config.Bool("basic-auth-enabled") && c.config.String("basic-auth-username") != "" && c.config.String("basic-auth-password") != "" {
|
||||
req.Header.Add("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(c.config.String("basic-auth-username")+":"+c.config.String("basic-auth-password"))))
|
||||
}
|
||||
req.Header.Add("X-Api-Key", c.config.String("api-key"))
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("An error has occurred when creating HTTP request %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
log.Fatalf("An error has occurred during retrieving statistics %v", err)
|
||||
return err
|
||||
}
|
||||
if !(resp.StatusCode >= 200 && resp.StatusCode < 300) {
|
||||
errMsg := fmt.Sprintf("An error has occurred during retrieving statistics HTTP statuscode %d", resp.StatusCode)
|
||||
log.Fatal(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return json.NewDecoder(resp.Body).Decode(target)
|
||||
}
|
||||
136
internal/collector/radarr/movie.go
Normal file
136
internal/collector/radarr/movie.go
Normal file
@ -0,0 +1,136 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/onedr0p/exportarr/internal/client"
|
||||
"github.com/onedr0p/exportarr/internal/model"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type movieCollector struct {
|
||||
config *cli.Context
|
||||
movieMetric *prometheus.Desc
|
||||
downloadedMetric *prometheus.Desc
|
||||
monitoredMetric *prometheus.Desc
|
||||
unmonitoredMetric *prometheus.Desc
|
||||
wantedMetric *prometheus.Desc
|
||||
missingMetric *prometheus.Desc
|
||||
filesizeMetric *prometheus.Desc
|
||||
qualitiesMetric *prometheus.Desc
|
||||
}
|
||||
|
||||
func NewMovieCollector(c *cli.Context) *movieCollector {
|
||||
return &movieCollector{
|
||||
config: c,
|
||||
movieMetric: prometheus.NewDesc(
|
||||
"radarr_movie_total",
|
||||
"Total number of movies",
|
||||
nil,
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
downloadedMetric: prometheus.NewDesc(
|
||||
"radarr_movie_download_total",
|
||||
"Total number of downloaded movies",
|
||||
nil,
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
monitoredMetric: prometheus.NewDesc(
|
||||
"radarr_movie_monitored_total",
|
||||
"Total number of monitored movies",
|
||||
nil,
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
unmonitoredMetric: prometheus.NewDesc(
|
||||
"radarr_movie_unmonitored_total",
|
||||
"Total number of unmonitored movies",
|
||||
nil,
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
wantedMetric: prometheus.NewDesc(
|
||||
"radarr_movie_wanted_total",
|
||||
"Total number of wanted movies",
|
||||
nil,
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
missingMetric: prometheus.NewDesc(
|
||||
"radarr_movie_missing_total",
|
||||
"Total number of missing movies",
|
||||
nil,
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
filesizeMetric: prometheus.NewDesc(
|
||||
"radarr_movie_filesize_total",
|
||||
"Total filesize of all movies",
|
||||
nil,
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
qualitiesMetric: prometheus.NewDesc(
|
||||
"radarr_movie_quality_total",
|
||||
"Total number of downloaded movies by quality",
|
||||
[]string{"quality"},
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (collector *movieCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- collector.movieMetric
|
||||
ch <- collector.downloadedMetric
|
||||
ch <- collector.monitoredMetric
|
||||
ch <- collector.unmonitoredMetric
|
||||
ch <- collector.wantedMetric
|
||||
ch <- collector.missingMetric
|
||||
ch <- collector.filesizeMetric
|
||||
ch <- collector.qualitiesMetric
|
||||
}
|
||||
|
||||
func (collector *movieCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
c := client.NewClient(collector.config)
|
||||
var fileSize int64
|
||||
var (
|
||||
downloaded = 0
|
||||
monitored = 0
|
||||
unmonitored = 0
|
||||
missing = 0
|
||||
wanted = 0
|
||||
qualities = map[string]int{}
|
||||
)
|
||||
movies := model.Movie{}
|
||||
if err := c.DoRequest("movie", &movies); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for _, s := range movies {
|
||||
if s.HasFile {
|
||||
downloaded++
|
||||
}
|
||||
if s.Monitored {
|
||||
monitored++
|
||||
if !s.HasFile && s.Status == "released" {
|
||||
missing++
|
||||
} else if !s.HasFile {
|
||||
wanted++
|
||||
}
|
||||
} else {
|
||||
unmonitored++
|
||||
}
|
||||
if s.MovieFile.Quality.Quality.Name != "" {
|
||||
qualities[s.MovieFile.Quality.Quality.Name]++
|
||||
}
|
||||
if s.MovieFile.Size != 0 {
|
||||
fileSize += s.MovieFile.Size
|
||||
}
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(collector.movieMetric, prometheus.GaugeValue, float64(len(movies)))
|
||||
ch <- prometheus.MustNewConstMetric(collector.downloadedMetric, prometheus.GaugeValue, float64(downloaded))
|
||||
ch <- prometheus.MustNewConstMetric(collector.monitoredMetric, prometheus.GaugeValue, float64(monitored))
|
||||
ch <- prometheus.MustNewConstMetric(collector.unmonitoredMetric, prometheus.GaugeValue, float64(unmonitored))
|
||||
ch <- prometheus.MustNewConstMetric(collector.wantedMetric, prometheus.GaugeValue, float64(wanted))
|
||||
ch <- prometheus.MustNewConstMetric(collector.missingMetric, prometheus.GaugeValue, float64(missing))
|
||||
ch <- prometheus.MustNewConstMetric(collector.filesizeMetric, prometheus.GaugeValue, float64(fileSize))
|
||||
for qualityName, count := range qualities {
|
||||
ch <- prometheus.MustNewConstMetric(collector.qualitiesMetric, prometheus.GaugeValue, float64(count),
|
||||
qualityName,
|
||||
)
|
||||
}
|
||||
}
|
||||
46
internal/collector/shared/health.go
Normal file
46
internal/collector/shared/health.go
Normal file
@ -0,0 +1,46 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/onedr0p/exportarr/internal/client"
|
||||
"github.com/onedr0p/exportarr/internal/model"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type systemHealthCollector struct {
|
||||
config *cli.Context
|
||||
systemHealthMetric *prometheus.Desc
|
||||
}
|
||||
|
||||
func NewSystemHealthCollector(c *cli.Context) *systemHealthCollector {
|
||||
return &systemHealthCollector{
|
||||
config: c,
|
||||
systemHealthMetric: prometheus.NewDesc(
|
||||
"radarr_system_health_issues",
|
||||
"Total number of movies in the queue by status",
|
||||
[]string{"source", "type", "message", "wikiurl"},
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (collector *systemHealthCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- collector.systemHealthMetric
|
||||
}
|
||||
|
||||
func (collector *systemHealthCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
c := client.NewClient(collector.config)
|
||||
systemHealth := model.SystemHealth{}
|
||||
if err := c.DoRequest("health", &systemHealth); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Group metrics by source, type, message and wikiurl
|
||||
if len(systemHealth) > 0 {
|
||||
for _, s := range systemHealth {
|
||||
ch <- prometheus.MustNewConstMetric(collector.systemHealthMetric, prometheus.GaugeValue, float64(1),
|
||||
s.Source, s.Type, s.Message, s.WikiURL,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
39
internal/collector/shared/history.go
Normal file
39
internal/collector/shared/history.go
Normal file
@ -0,0 +1,39 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/onedr0p/exportarr/internal/client"
|
||||
"github.com/onedr0p/exportarr/internal/model"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type historyCollector struct {
|
||||
config *cli.Context
|
||||
historyMetric *prometheus.Desc
|
||||
}
|
||||
|
||||
func NewHistoryCollector(c *cli.Context) *historyCollector {
|
||||
return &historyCollector{
|
||||
config: c,
|
||||
historyMetric: prometheus.NewDesc(
|
||||
"radarr_history_total",
|
||||
"Total number of records in history",
|
||||
nil,
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (collector *historyCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- collector.historyMetric
|
||||
}
|
||||
|
||||
func (collector *historyCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
c := client.NewClient(collector.config)
|
||||
history := model.History{}
|
||||
if err := c.DoRequest("history", &history); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(collector.historyMetric, prometheus.GaugeValue, float64(history.TotalRecords))
|
||||
}
|
||||
63
internal/collector/shared/queue.go
Normal file
63
internal/collector/shared/queue.go
Normal file
@ -0,0 +1,63 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onedr0p/exportarr/internal/client"
|
||||
"github.com/onedr0p/exportarr/internal/model"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type queueCollector struct {
|
||||
config *cli.Context
|
||||
queueMetric *prometheus.Desc
|
||||
}
|
||||
|
||||
func NewQueueCollector(c *cli.Context) *queueCollector {
|
||||
return &queueCollector{
|
||||
config: c,
|
||||
queueMetric: prometheus.NewDesc(
|
||||
"radarr_queue_total",
|
||||
"Total number of movies in the queue by status",
|
||||
[]string{"status", "download_status", "download_state"},
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (collector *queueCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- collector.queueMetric
|
||||
}
|
||||
|
||||
func (collector *queueCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
c := client.NewClient(collector.config)
|
||||
queue := model.Queue{}
|
||||
if err := c.DoRequest("queue?page=1&includeUnknownMovieItems=true", &queue); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Calculate total pages
|
||||
var totalPages = (queue.TotalRecords + queue.PageSize - 1) / queue.PageSize
|
||||
// Paginate
|
||||
var queueStatusAll = make([]model.QueueRecords, 0, queue.TotalRecords)
|
||||
queueStatusAll = append(queueStatusAll, queue.Records...)
|
||||
if totalPages > 1 {
|
||||
for page := 2; page <= totalPages; page++ {
|
||||
if err := client.DoRequest(fmt.Sprintf("%s?page=%d&includeUnknownMovieItems=true", "queue", page), &queue); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
queueStatusAll = append(queueStatusAll, queue.Records...)
|
||||
}
|
||||
}
|
||||
// Group metrics by status, download_status and download_state
|
||||
if len(queueStatusAll) > 0 {
|
||||
var queueMetrics prometheus.Metric
|
||||
for i, s := range queueStatusAll {
|
||||
queueMetrics = prometheus.MustNewConstMetric(collector.queueMetric, prometheus.GaugeValue, float64(i+1),
|
||||
s.Status, s.TrackedDownloadStatus, s.TrackedDownloadState,
|
||||
)
|
||||
}
|
||||
ch <- queueMetrics
|
||||
}
|
||||
}
|
||||
46
internal/collector/shared/rootfolder.go
Normal file
46
internal/collector/shared/rootfolder.go
Normal file
@ -0,0 +1,46 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/onedr0p/exportarr/internal/client"
|
||||
"github.com/onedr0p/exportarr/internal/model"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type rootFolderCollector struct {
|
||||
config *cli.Context
|
||||
rootFolderMetric *prometheus.Desc
|
||||
}
|
||||
|
||||
func NewRootFolderCollector(c *cli.Context) *rootFolderCollector {
|
||||
return &rootFolderCollector{
|
||||
config: c,
|
||||
rootFolderMetric: prometheus.NewDesc(
|
||||
"radarr_rootfolder_freespace_bytes",
|
||||
"Root folder space in bytes",
|
||||
[]string{"path"},
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (collector *rootFolderCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- collector.rootFolderMetric
|
||||
}
|
||||
|
||||
func (collector *rootFolderCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
c := client.NewClient(collector.config)
|
||||
rootFolders := model.RootFolder{}
|
||||
if err := c.DoRequest("rootfolder", &rootFolders); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Group metrics by path
|
||||
if len(rootFolders) > 0 {
|
||||
for _, rootFolder := range rootFolders {
|
||||
ch <- prometheus.MustNewConstMetric(collector.rootFolderMetric, prometheus.GaugeValue, float64(rootFolder.FreeSpace),
|
||||
rootFolder.Path,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
41
internal/collector/shared/status.go
Normal file
41
internal/collector/shared/status.go
Normal file
@ -0,0 +1,41 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/onedr0p/exportarr/internal/client"
|
||||
"github.com/onedr0p/exportarr/internal/model"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type systemStatusCollector struct {
|
||||
config *cli.Context
|
||||
systemStatus *prometheus.Desc
|
||||
}
|
||||
|
||||
func NewSystemStatusCollector(c *cli.Context) *systemStatusCollector {
|
||||
return &systemStatusCollector{
|
||||
config: c,
|
||||
systemStatus: prometheus.NewDesc(
|
||||
"radarr_system_status",
|
||||
"System Status",
|
||||
nil,
|
||||
prometheus.Labels{"url": c.String("url")},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (collector *systemStatusCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- collector.systemStatus
|
||||
}
|
||||
|
||||
func (collector *systemStatusCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
c := client.NewClient(collector.config)
|
||||
systemStatus := model.SystemStatus{}
|
||||
if err := client.DoRequest("system/status", &systemStatus); err != nil {
|
||||
ch <- prometheus.MustNewConstMetric(collector.systemStatus, prometheus.GaugeValue, float64(0.0))
|
||||
} else if (model.SystemStatus{}) == systemStatus {
|
||||
ch <- prometheus.MustNewConstMetric(collector.systemStatus, prometheus.GaugeValue, float64(0.0))
|
||||
} else {
|
||||
ch <- prometheus.MustNewConstMetric(collector.systemStatus, prometheus.GaugeValue, float64(1.0))
|
||||
}
|
||||
}
|
||||
12
internal/handlers/healthz.go
Normal file
12
internal/handlers/healthz.go
Normal file
@ -0,0 +1,12 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func HealthzHandler(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("OK"))
|
||||
fmt.Fprint(w)
|
||||
}
|
||||
11
internal/handlers/index.go
Normal file
11
internal/handlers/index.go
Normal file
@ -0,0 +1,11 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func IndexHandler(w http.ResponseWriter, _ *http.Request) {
|
||||
response := `<h1>Radarr Exporter</h1><p><a href='/metrics'>metrics</a></p>`
|
||||
fmt.Fprintf(w, response)
|
||||
}
|
||||
17
internal/model/radarr.go
Normal file
17
internal/model/radarr.go
Normal file
@ -0,0 +1,17 @@
|
||||
package model
|
||||
|
||||
// Movie - Stores struct of JSON response
|
||||
type Movie []struct {
|
||||
Status string `json:"status"`
|
||||
HasFile bool `json:"hasFile"`
|
||||
Monitored bool `json:"monitored"`
|
||||
MovieFile struct {
|
||||
Size int64 `json:"size"`
|
||||
Quality struct {
|
||||
Quality struct {
|
||||
Name string `json:"name"`
|
||||
} `json:"quality"`
|
||||
} `json:"quality"`
|
||||
} `json:"movieFile"`
|
||||
QualityProfileID int `json:"qualityProfileId"`
|
||||
}
|
||||
51
internal/model/shared.go
Normal file
51
internal/model/shared.go
Normal file
@ -0,0 +1,51 @@
|
||||
package model
|
||||
|
||||
// RootFolder - Stores struct of JSON response
|
||||
type RootFolder []struct {
|
||||
Path string `json:"path"`
|
||||
FreeSpace int64 `json:"freeSpace"`
|
||||
}
|
||||
|
||||
// SystemStatus - Stores struct of JSON response
|
||||
type SystemStatus struct {
|
||||
Version string `json:"version"`
|
||||
AppData string `json:"appData"`
|
||||
Branch string `json:"branch"`
|
||||
}
|
||||
|
||||
// Queue - Stores struct of JSON response
|
||||
type Queue struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"pageSize"`
|
||||
SortKey string `json:"sortKey"`
|
||||
SortDirection string `json:"sortDirection"`
|
||||
TotalRecords int `json:"totalRecords"`
|
||||
Records []QueueRecords `json:"records"`
|
||||
}
|
||||
|
||||
// QueueRecords - Stores struct of JSON response
|
||||
type QueueRecords struct {
|
||||
Size float64 `json:"size"`
|
||||
Title string `json:"title"`
|
||||
Status string `json:"status"`
|
||||
TrackedDownloadStatus string `json:"trackedDownloadStatus"`
|
||||
TrackedDownloadState string `json:"trackedDownloadState"`
|
||||
StatusMessages []struct {
|
||||
Title string `json:"title"`
|
||||
Messages []string `json:"messages"`
|
||||
} `json:"statusMessages"`
|
||||
ErrorMessage string `json:"errorMessage"`
|
||||
}
|
||||
|
||||
// History - Stores struct of JSON response
|
||||
type History struct {
|
||||
TotalRecords int `json:"totalRecords"`
|
||||
}
|
||||
|
||||
// SystemHealth - Stores struct of JSON response
|
||||
type SystemHealth []struct {
|
||||
Source string `json:"source"`
|
||||
Type string `json:"type"`
|
||||
Message string `json:"message"`
|
||||
WikiURL string `json:"wikiUrl"`
|
||||
}
|
||||
21
internal/utils/utils.go
Normal file
21
internal/utils/utils.go
Normal file
@ -0,0 +1,21 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// IsValidApikey - Check if the API Key is 32 characters and only a-z0-9
|
||||
func IsValidApikey(str string) bool {
|
||||
found, err := regexp.MatchString("([a-z0-9]{32})", str)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
// IsValidUrl - Checks if the URL is valid
|
||||
func IsValidUrl(str string) bool {
|
||||
u, err := url.Parse(str)
|
||||
return err == nil && u.Scheme != "" && u.Host != ""
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user