-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #162 from fastly/extend-metric-blocklist
Fix metric-blocklist for datacenter_info, service_info, and last_successful_response
- Loading branch information
Showing
10 changed files
with
245 additions
and
19 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
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
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
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
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
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,88 @@ | ||
package api | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/prometheus/client_golang/prometheus" | ||
) | ||
|
||
// TokenRecorder requests api.fastly.com/tokens/self once and sets a gauge metric | ||
type TokenRecorder struct { | ||
client HTTPClient | ||
token string | ||
metric *prometheus.GaugeVec | ||
} | ||
|
||
// NewTokenRecorder returns an empty token recorder. Use the | ||
// Set method to get token data and set the gauge metric. | ||
func NewTokenRecorder(client HTTPClient, token string) *TokenRecorder { | ||
return &TokenRecorder{ | ||
client: client, | ||
token: token, | ||
} | ||
} | ||
|
||
// Gatherer returns a Prometheus gatherer which will yield current | ||
// token expiration as a gauge metric. | ||
func (t *TokenRecorder) Gatherer(namespace, subsystem string) (prometheus.Gatherer, error) { | ||
registry := prometheus.NewRegistry() | ||
tokenExpiration := prometheus.NewGaugeVec(prometheus.GaugeOpts{Namespace: namespace, Subsystem: subsystem, Name: "token_expiration", Help: "Unix timestamp of the expiration time of the Fastly API Token"}, []string{"token_id", "user_id"}) | ||
err := registry.Register(tokenExpiration) | ||
if err != nil { | ||
return nil, fmt.Errorf("registering token collector: %w", err) | ||
} | ||
t.metric = tokenExpiration | ||
return registry, nil | ||
} | ||
|
||
// Set retreives token metadata from the Fastly API and sets the gauge metric | ||
func (t *TokenRecorder) Set(ctx context.Context) error { | ||
token, err := t.getToken(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if !token.Expiration.IsZero() { | ||
t.metric.WithLabelValues(token.ID, token.UserID).Set(float64(token.Expiration.Unix())) | ||
} | ||
return nil | ||
} | ||
|
||
type token struct { | ||
ID string `json:"id"` | ||
UserID string `json:"user_id"` | ||
Expiration time.Time `json:"expires_at,omitempty"` | ||
} | ||
|
||
func (t *TokenRecorder) getToken(ctx context.Context) (*token, error) { | ||
uri := "https://api.fastly.com/tokens/self" | ||
|
||
req, err := http.NewRequestWithContext(ctx, "GET", uri, nil) | ||
if err != nil { | ||
return nil, fmt.Errorf("error constructing API tokens request: %w", err) | ||
} | ||
|
||
req.Header.Set("Fastly-Key", t.token) | ||
req.Header.Set("Accept", "application/json") | ||
resp, err := t.client.Do(req) | ||
if err != nil { | ||
return nil, fmt.Errorf("error executing API tokens request: %w", err) | ||
} | ||
defer resp.Body.Close() | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
return nil, NewError(resp) | ||
} | ||
|
||
var response token | ||
|
||
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { | ||
return nil, fmt.Errorf("error decoding API Tokens response: %w", err) | ||
} | ||
|
||
return &response, 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,72 @@ | ||
package api_test | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/fastly/fastly-exporter/pkg/api" | ||
"github.com/prometheus/client_golang/prometheus/testutil" | ||
) | ||
|
||
func TestTokenMetric(t *testing.T) { | ||
var ( | ||
namespace = "fastly" | ||
subsystem = "rt" | ||
) | ||
client := api.NewTokenRecorder(fixedResponseClient{code: http.StatusOK, response: tokenReponseExpiresAt}, "") | ||
gatherer, _ := client.Gatherer(namespace, subsystem) | ||
client.Set(context.Background()) | ||
|
||
expected := ` | ||
# HELP fastly_rt_token_expiration Unix timestamp of the expiration time of the Fastly API Token | ||
# TYPE fastly_rt_token_expiration gauge | ||
fastly_rt_token_expiration{token_id="id1234",user_id="user456"} 1.7764704e+09 | ||
` | ||
err := testutil.GatherAndCompare(gatherer, strings.NewReader(expected), "fastly_rt_token_expiration") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
} | ||
|
||
func TestTokenMetricWithoutExpiration(t *testing.T) { | ||
var ( | ||
namespace = "fastly" | ||
subsystem = "rt" | ||
) | ||
client := api.NewTokenRecorder(fixedResponseClient{code: http.StatusOK, response: tokenReponseNoExpiry}, "") | ||
gatherer, _ := client.Gatherer(namespace, subsystem) | ||
client.Set(context.Background()) | ||
|
||
expected := ` | ||
# HELP fastly_rt_token_expiration Unix timestamp of the expiration time of the Fastly API Token | ||
# TYPE fastly_rt_token_expiration gauge | ||
` | ||
err := testutil.GatherAndCompare(gatherer, strings.NewReader(expected), "fastly_rt_token_expiration") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
} | ||
|
||
const tokenReponseExpiresAt = ` | ||
{ | ||
"id": "id1234", | ||
"user_id": "user456", | ||
"customer_id": "customer987", | ||
"name": "Fastly API Token", | ||
"last_used_at": "2024-04-18T13:37:06Z", | ||
"created_at": "2016-10-11T18:36:35Z", | ||
"expires_at": "2026-04-18T00:00:00Z" | ||
}` | ||
|
||
const tokenReponseNoExpiry = ` | ||
{ | ||
"id": "id1234", | ||
"user_id": "user456", | ||
"customer_id": "customer987", | ||
"name": "Fastly API Token", | ||
"last_used_at": "2024-04-18T13:37:06Z", | ||
"created_at": "2016-10-11T18:36:35Z", | ||
"expires_at": null | ||
}` |
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
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
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