-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9034925
Showing
14 changed files
with
1,586 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Short description | ||
|
||
_Please describe shortly this PR here (for a release, just write "Release x.y.z")_ | ||
|
||
|
||
# Changes | ||
|
||
_Please list here the precise changes_ | ||
|
||
|
||
# Tests | ||
|
||
_Please explain here how you tested your code_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
bin/ | ||
config.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# CHANGELOG | ||
|
||
## 1.0.0 (2022-02-08) | ||
|
||
### Features | ||
- Initial release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Copyright: (c) 2022, Justin Béra (@just1not2) <[email protected]> | ||
# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
|
||
# Build | ||
FROM golang:1.17 AS build | ||
|
||
WORKDIR /app | ||
|
||
COPY go.mod ./ | ||
COPY go.sum ./ | ||
RUN go mod download | ||
|
||
COPY *.go ./ | ||
RUN CGO_ENABLED=0 go build -o /prometheus-exporter-yourls | ||
|
||
|
||
# Install | ||
FROM scratch | ||
LABEL maintainer="[email protected]" | ||
|
||
WORKDIR / | ||
|
||
COPY --from=build /prometheus-exporter-yourls /prometheus-exporter-yourls | ||
COPY config.json.template config.json | ||
|
||
EXPOSE 9923 | ||
|
||
ENTRYPOINT ["/prometheus-exporter-yourls"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Copyright: (c) 2022, Justin Béra (@just1not2) <[email protected]> | ||
# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
|
||
VERSION=1.0.0 | ||
|
||
default: install | ||
|
||
build: | ||
docker build -t just1not2/prometheus-exporter-yourls:test . | ||
|
||
install: build | ||
docker run -p 9923:9923 -v ${shell pwd}/config.json:/config.json just1not2/prometheus-exporter-yourls:test config.json | ||
|
||
local: | ||
go build -o ./bin/prometheus-exporter-yourls | ||
./bin/prometheus-exporter-yourls config.json | ||
|
||
release: build | ||
docker tag just1not2/prometheus-exporter-yourls:test just1not2/prometheus-exporter-yourls:latest | ||
docker tag just1not2/prometheus-exporter-yourls:test just1not2/prometheus-exporter-yourls:${shell echo ${VERSION} | cut -d '.' -f -2} | ||
docker tag just1not2/prometheus-exporter-yourls:test just1not2/prometheus-exporter-yourls:${VERSION} | ||
docker push just1not2/prometheus-exporter-yourls:latest | ||
docker push just1not2/prometheus-exporter-yourls:${shell echo ${VERSION} | cut -d '.' -f -2} | ||
docker push just1not2/prometheus-exporter-yourls:${VERSION} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# YOURLS Prometheus Exporter | ||
|
||
A Prometheus exporter to fetch some metrics from a YOURLS URL-shortener instance. | ||
|
||
## Exported metrics | ||
|
||
### Gauges | ||
Name | Description | ||
--- | --- | ||
`yourls_clicks_total`|Total number of clicks | ||
`yourls_links_total`|Total number of deployed links | ||
|
||
### Go metrics | ||
A variety of Go metrics that describe the exporter are exported as well. | ||
|
||
|
||
## Installation | ||
|
||
### Docker image | ||
The preferred way to use the exporter is by running the provided Docker image. It is currently available on Docker Hub: | ||
|
||
```bash | ||
docker pull just1not2/prometheus-exporter-yourls:latest | ||
``` | ||
|
||
In addition to the `latest` tag which points to the version currently in the `main` branch, tagged versions are also available. | ||
|
||
### From source | ||
You can clone the repository and build the exporter locally. | ||
|
||
```bash | ||
git clone https://github.com/just1not2/prometheus-exporter-yourls.git | ||
cd prometheus-exporter-yourls | ||
make local | ||
``` | ||
|
||
|
||
## Configuration | ||
|
||
### Exporter configuration | ||
There are two ways to configure the exporter: | ||
* Environment variables | ||
* Configuration file | ||
|
||
The first method takes precedence over the second one. | ||
|
||
To use the first one, you just have to declare environment variables while launching the Docker image, a Docker-compose or directly the executable: | ||
```bash | ||
docker run -p 9923:9923 \ | ||
-e YOURLS_URL=http://yourls.example.com \ | ||
-e YOURLS_SIGNATURE=SECRET_API_KEY \ | ||
just1not2/prometheus-exporter-yourls:latest | ||
``` | ||
|
||
If you prefer to configure your provider with the second method, you should copy the [config.json.template](./config.json.template) file and replace the sample values. You can then launch the exporter: | ||
```bash | ||
docker run -p 9923:9923 -v $(pwd)/config.json:/config.json just1not2/prometheus-exporter-yourls:latest config.json | ||
``` | ||
|
||
The configuration parameters that can be declared are summarized in this table: | ||
Parameter | Environment variable | Description | Note | ||
--- | --- | --- | --- | ||
`url`|`YOURLS_URL`|URL of the YOURLS instance|_Required_ | ||
`signature`|`YOURLS_SIGNATURE`|Signature of the YOURLS instance|_Required_ | ||
`exporter_port`|`YOURLS_EXPORTER_PORT`|Port on which the exporter listens|_Default is 9923_ | ||
`exporter_timeout`|`YOURLS_EXPORTER_TIMEOUT`|Timeout of requests to the YOURLS instance|_Default is 10_ | ||
|
||
The `signature` parameter can be found at `http://<your YOURLS instance URL>/admin/tools.php`. | ||
|
||
### Scrape configuration | ||
The exporter will query the YOURLS server every time it is scraped by Prometheus. You can modify the configuration of the exporter to change the scrape interval: | ||
|
||
```yml | ||
scrape_configs: | ||
- job_name: yourls | ||
scrape_interval: 1m | ||
static_configs: | ||
- targets: ['<your YOURLS exporter host>:9923'] | ||
``` | ||
## See also | ||
* [YOURLS official documentation](https://yourls.org) | ||
* [Use Prometheus exporter](https://prometheus.io/docs/instrumenting/exporters/) | ||
## Contributing to this exporter | ||
This exporter started as personal project, but I welcome community contributions to this exporter. If you find problems, please open an issue or create a PR against the [YOURLS exporter repository](https://github.com/just1not2/prometheus-exporter-yourls). | ||
You can also reach me by email at `[email protected]`. | ||
|
||
|
||
## Licensing | ||
|
||
GNU General Public License v3.0 or later. | ||
|
||
See [LICENSE](./LICENSE) to see the full text. | ||
|
||
|
||
## Author information | ||
|
||
This exporter was created in 2022 by Justin Béra. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright: (c) 2022, Justin Béra (@just1not2) <[email protected]> | ||
// GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
|
||
package main | ||
|
||
import ( | ||
"strconv" | ||
"time" | ||
|
||
"github.com/prometheus/client_golang/prometheus" | ||
) | ||
|
||
type YourlsCollector struct { | ||
client *YourlsClient | ||
YourlsClicksTotalDescription *prometheus.Desc | ||
YourlsLinksTotalDescription *prometheus.Desc | ||
} | ||
|
||
func NewYourlsCollector(configuration *YourlsConfiguration) *YourlsCollector { | ||
return &YourlsCollector{ | ||
client: NewYourlsClient(configuration.YourlsURL, configuration.Signature, configuration.HTTPTimeout), | ||
YourlsClicksTotalDescription: prometheus.NewDesc("yourls_clicks_total", | ||
"Total number of clicks.", | ||
nil, nil, | ||
), | ||
YourlsLinksTotalDescription: prometheus.NewDesc("yourls_links_total", | ||
"Total number of deployed links.", | ||
nil, nil, | ||
), | ||
} | ||
} | ||
|
||
func (collector *YourlsCollector) Describe(ch chan<- *prometheus.Desc) { | ||
ch <- collector.YourlsClicksTotalDescription | ||
ch <- collector.YourlsLinksTotalDescription | ||
} | ||
|
||
func (collector *YourlsCollector) Collect(ch chan<- prometheus.Metric) { | ||
// Gathers the specific query parameters | ||
parameters := map[string]string{ | ||
"action": "stats", | ||
} | ||
|
||
body, err := collector.client.Request(parameters) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Converts returned statistics into floats | ||
linksTotalValue, _ := strconv.ParseFloat(body.Stats["total_links"], 64) | ||
clicksTotalValue, _ := strconv.ParseFloat(body.Stats["total_clicks"], 64) | ||
|
||
// Sends metrics to the channel | ||
m1 := prometheus.MustNewConstMetric(collector.YourlsClicksTotalDescription, prometheus.GaugeValue, clicksTotalValue) | ||
m2 := prometheus.MustNewConstMetric(collector.YourlsLinksTotalDescription, prometheus.GaugeValue, linksTotalValue) | ||
m1 = prometheus.NewMetricWithTimestamp(time.Now(), m1) | ||
m2 = prometheus.NewMetricWithTimestamp(time.Now(), m2) | ||
ch <- m1 | ||
ch <- m2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"url": "http://yourls.example.com", | ||
"signature": "SECRET_API_KEY", | ||
"exporter_port": 9923, | ||
"exporter_timeout": 10 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// Copyright: (c) 2022, Justin Béra (@just1not2) <[email protected]> | ||
// GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
|
||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"log" | ||
"os" | ||
"strconv" | ||
"time" | ||
) | ||
|
||
const ( | ||
DEFAULT_HTTP_TIMEOUT = 10 | ||
DEFAULT_PORT = 9923 | ||
) | ||
|
||
type ExporterConfiguration struct { | ||
HTTPTimeout float64 `json:"exporter_timeout"` | ||
Port float64 `json:"exporter_port"` | ||
Signature string `json:"signature"` | ||
YourlsURL string `json:"url"` | ||
} | ||
|
||
type YourlsConfiguration struct { | ||
HTTPTimeout time.Duration | ||
Port float64 | ||
Signature string | ||
YourlsURL string | ||
} | ||
|
||
func NewConfiguration() *YourlsConfiguration { | ||
// Initializes exporter configuration | ||
configuration := &ExporterConfiguration{ | ||
HTTPTimeout: DEFAULT_HTTP_TIMEOUT, | ||
Port: DEFAULT_PORT, | ||
} | ||
|
||
// Uses configuration file if it is passed as a parameter | ||
if len(os.Args) > 1 { | ||
file, err := os.Open(os.Args[1]) | ||
if err != nil { | ||
fmt.Printf("warn: %s, cannot read %s (skipping)\n", err, os.Args[1]) | ||
} else { | ||
if err := json.NewDecoder(file).Decode(configuration); err != nil { | ||
fmt.Printf("warn: %s, cannot read %s (skipping)\n", err, os.Args[1]) | ||
} | ||
} | ||
file.Close() | ||
} | ||
|
||
// Overwrites configuration with existing environment variables | ||
if keyString, defined := os.LookupEnv("YOURLS_URL"); defined { | ||
configuration.YourlsURL = keyString | ||
} | ||
if keyString, defined := os.LookupEnv("YOURLS_SIGNATURE"); defined { | ||
configuration.Signature = keyString | ||
} | ||
if keyString, defined := os.LookupEnv("YOURLS_EXPORTER_PORT"); defined { | ||
if keyFloat, err := strconv.ParseFloat(keyString, 64); err != nil { | ||
fmt.Printf("warn: %s, cannot use YOURLS_EXPORTER_PORT environment variable (skipping)\n", err) | ||
} else { | ||
configuration.Port = keyFloat | ||
} | ||
} | ||
if keyString, defined := os.LookupEnv("YOURLS_EXPORTER_TIMEOUT"); defined { | ||
if keyFloat, err := strconv.ParseFloat(keyString, 64); err != nil { | ||
fmt.Printf("warn: %s, cannot use YOURLS_EXPORTER_TIMEOUT environment variable (skipping)\n", err) | ||
} else { | ||
configuration.HTTPTimeout = keyFloat | ||
} | ||
} | ||
|
||
// Throws error for missing fields | ||
if configuration.YourlsURL == "" { | ||
log.Fatal("error: YOURLS_URL environment variable and 'url' configuration parameter were both undefined") | ||
} else if configuration.Signature == "" { | ||
log.Fatal("error: YOURLS_SIGNATURE environment variable and 'signature' configuration parameter were both undefined") | ||
} | ||
|
||
return &YourlsConfiguration{ | ||
HTTPTimeout: time.Duration(configuration.HTTPTimeout * float64(time.Second)), | ||
YourlsURL: fmt.Sprintf("%s/yourls-api.php?format=json&signature=%s", configuration.YourlsURL, configuration.Signature), | ||
Port: configuration.Port, | ||
Signature: configuration.Signature, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module github.com/just1not2/prometheus-exporter-yourls | ||
|
||
go 1.17 | ||
|
||
require github.com/prometheus/client_golang v1.12.1 | ||
|
||
require ( | ||
github.com/beorn7/perks v1.0.1 // indirect | ||
github.com/cespare/xxhash/v2 v2.1.2 // indirect | ||
github.com/golang/protobuf v1.5.2 // indirect | ||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect | ||
github.com/prometheus/client_model v0.2.0 // indirect | ||
github.com/prometheus/common v0.32.1 // indirect | ||
github.com/prometheus/procfs v0.7.3 // indirect | ||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect | ||
google.golang.org/protobuf v1.26.0 // indirect | ||
) |
Oops, something went wrong.