-
Notifications
You must be signed in to change notification settings - Fork 2
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
Showing
9 changed files
with
801 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,26 @@ | ||
name: release | ||
on: | ||
push: | ||
tags: | ||
- 'v*' | ||
|
||
jobs: | ||
test: | ||
name: Build and package | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 0 | ||
- name: Setup Go | ||
uses: actions/setup-go@v2 | ||
with: | ||
go-version: '~1.16.3' | ||
- name: Run GoReleaser | ||
uses: goreleaser/goreleaser-action@v2 | ||
with: | ||
version: latest | ||
args: release --rm-dist | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
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,34 @@ | ||
project_name: vattenfall | ||
builds: | ||
- id: vattenfall | ||
binary: vattenfall | ||
mod_timestamp: '{{ .CommitTimestamp }}' | ||
flags: | ||
- -trimpath | ||
ldflags: | ||
- -s | ||
- -w | ||
- -X main.version={{.Version}} -X main.commit={{.FullCommit}} -X main.date={{.CommitDate}} -X main.repository={{.GitURL}} | ||
goos: | ||
- windows | ||
- darwin | ||
- linux | ||
goarch: | ||
- amd64 | ||
- arm64 | ||
- arm | ||
goarm: | ||
- 7 | ||
archives: | ||
- id: vattenfall | ||
builds: | ||
- vattenfall | ||
wrap_in_directory: true | ||
files: | ||
- LICENSE | ||
- README.md | ||
replacements: | ||
darwin: macOS | ||
format_overrides: | ||
- goos: windows | ||
format: zip |
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,50 @@ | ||
# Vattenfall | ||
|
||
This is a very basic Prometheus exporter for the Vattenfall electricity spot | ||
prices in Sweden. It'll export one metric, `energy_price_per_kwh` for each | ||
region: | ||
|
||
``` | ||
# HELP energy_price_per_kwh Energy price per kWh for a region | ||
# TYPE energy_price_per_kwh gauge | ||
energy_price_per_kwh{country="SE",currency="SEK",region="SN1"} 0.4707 | ||
energy_price_per_kwh{country="SE",currency="SEK",region="SN2"} 0.4707 | ||
energy_price_per_kwh{country="SE",currency="SEK",region="SN3"} 0.4707 | ||
energy_price_per_kwh{country="SE",currency="SEK",region="SN4"} 0.4707 | ||
``` | ||
|
||
Data is cached for 30min in memory to not hammer Vattenfall each time you | ||
scrape the collector (and their API is slow), but still catch any price | ||
adjustments that might occur. | ||
|
||
## Usage | ||
|
||
``` | ||
-output.file string | ||
write metrics to specified file (must have .prom extension) | ||
-output.http string | ||
host:port to listen on for HTTP scrapes | ||
-region value | ||
region to query for, SN1-4, can be passed multiple times | ||
``` | ||
|
||
To run it as a Prometheus exporter that you can query over HTTP: | ||
|
||
```sh | ||
$ vattenfall -output.http=":9000" -region SN1 -region SN2 -region SN3 -region SN4 | ||
``` | ||
|
||
Please note that there's 2 endpoints `/metrics` which instruments the | ||
collector itself, and `/prices` with the pricing info. | ||
|
||
If you want to use it with the textfile collector, for example in an hourly cron: | ||
|
||
```sh | ||
$ vattenfall -output.file="/etc/prometheus/textfile/electricity.prom" -region SN1 -region SN2 -region SN3 -region SN4 | ||
``` | ||
|
||
Or to just get the values on the console: | ||
|
||
```sh | ||
$ vattenfall -region SN1 -region SN2 -region SN3 -region SN4 | ||
``` |
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,109 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"io/ioutil" | ||
"net/http" | ||
"sync" | ||
"time" | ||
) | ||
|
||
const ( | ||
source = "https://www.vattenfall.se/api/price/spot/pricearea/%s/%s/%s" | ||
) | ||
|
||
type Data struct { | ||
Timestamp time.Time | ||
Region string | ||
Value float64 | ||
Currency string | ||
} | ||
|
||
var ( | ||
info = map[string][]Data{} | ||
lastFetch = map[string]time.Time{} | ||
lock = sync.RWMutex{} | ||
) | ||
|
||
func (d *Data) UnmarshalJSON(data []byte) error { | ||
type internal struct { | ||
Timestamp string `json:"TimeStamp"` | ||
Value float64 `json:"Value"` | ||
PriceArea string `json:"PriceArea"` | ||
} | ||
|
||
var v internal | ||
if err := json.Unmarshal(data, &v); err != nil { | ||
return err | ||
} | ||
|
||
parsed, err := time.Parse("2006-01-02T15:04:05", v.Timestamp) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
d.Timestamp = parsed | ||
d.Region = v.PriceArea | ||
d.Value = (v.Value * 100) / 10000 | ||
d.Currency = "SEK" | ||
|
||
return nil | ||
} | ||
|
||
func fetch(date time.Time, region string) ([]Data, error) { | ||
lock.RLock() | ||
lf := lastFetch[region] | ||
lock.RUnlock() | ||
|
||
if lf.Add(30 * time.Minute).Before(date) { | ||
b, err := fetchFromURL(date, region) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
data := []Data{} | ||
err = json.Unmarshal(b, &data) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
lock.Lock() | ||
lastFetch[region] = date | ||
info[region] = data | ||
lock.Unlock() | ||
|
||
return data, nil | ||
} | ||
|
||
return info[region], nil | ||
} | ||
|
||
func fetchFromURL(date time.Time, region string) ([]byte, error) { | ||
res := fmt.Sprintf( | ||
source, | ||
date.Format("2006-01-02"), | ||
date.Format("2006-01-02"), | ||
region, | ||
) | ||
resp, err := http.Get(res) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to fetch %s: %w", res, err) | ||
} | ||
defer func() { | ||
io.Copy(ioutil.Discard, resp.Body) | ||
resp.Body.Close() | ||
}() | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
return nil, fmt.Errorf("expected 200 OK when fetching: %s, got: %d", res, resp.StatusCode) | ||
} | ||
|
||
data, err := io.ReadAll(resp.Body) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read response body: %w", err) | ||
} | ||
|
||
return data, nil | ||
} |
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,8 @@ | ||
module github.com/daenney/vattenfall | ||
|
||
go 1.16 | ||
|
||
require ( | ||
github.com/prometheus/client_golang v1.10.0 | ||
github.com/prometheus/common v0.18.0 | ||
) |
Oops, something went wrong.