Skip to content
This repository has been archived by the owner on Dec 22, 2022. It is now read-only.

Commit

Permalink
[Currency support] Adding a debug endpoint (prebid#822)
Browse files Browse the repository at this point in the history
This CL introduces a new admin endpoint exposing current currency rate
converter internals such as:
- Sync source URL
- Internal rates
- Update frequency
- Last update

It will help for the future rollout of currencies support.

More details: prebid#280
  • Loading branch information
benjaminch authored and hhhjort committed Mar 13, 2019
1 parent 22c788a commit 41ecc4f
Show file tree
Hide file tree
Showing 11 changed files with 499 additions and 7 deletions.
5 changes: 5 additions & 0 deletions currencies/constant_rates.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,8 @@ func (r *ConstantRates) GetRate(from string, to string) (float64, error) {

return 1, nil
}

// GetRates returns current rates
func (r *ConstantRates) GetRates() *map[string]map[string]float64 {
return nil
}
45 changes: 45 additions & 0 deletions currencies/converter_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package currencies

import "time"

// ConverterInfo holds information about converter setup
type ConverterInfo interface {
Source() string
FetchingInterval() time.Duration
LastUpdated() time.Time
Rates() *map[string]map[string]float64
AdditionalInfo() interface{}
}

type converterInfo struct {
source string
fetchingInterval time.Duration
lastUpdated time.Time
rates *map[string]map[string]float64
additionalInfo interface{}
}

// Source returns converter's URL source
func (ci converterInfo) Source() string {
return ci.source
}

// FetchingInterval returns converter's fetching interval in nanoseconds
func (ci converterInfo) FetchingInterval() time.Duration {
return ci.fetchingInterval
}

// LastUpdated returns converter's last updated time
func (ci converterInfo) LastUpdated() time.Time {
return ci.lastUpdated
}

// Rates returns converter's internal rates
func (ci converterInfo) Rates() *map[string]map[string]float64 {
return ci.rates
}

// AdditionalInfo returns converter's additional infos
func (ci converterInfo) AdditionalInfo() interface{} {
return ci.additionalInfo
}
11 changes: 11 additions & 0 deletions currencies/rate_converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,16 @@ func (rc *RateConverter) Rates() Conversions {
return nil
}

// GetInfo returns setup information about the converter
func (rc *RateConverter) GetInfo() ConverterInfo {
return converterInfo{
source: rc.syncSourceURL,
fetchingInterval: rc.fetchingInterval,
lastUpdated: rc.LastUpdated(),
rates: rc.Rates().GetRates(),
}
}

type httpClient interface {
Do(req *http.Request) (*http.Response, error)
}
Expand All @@ -179,4 +189,5 @@ type httpClient interface {
// currencies, then an err is returned and rate is 0.
type Conversions interface {
GetRate(from string, to string) (float64, error)
GetRates() *map[string]map[string]float64
}
5 changes: 5 additions & 0 deletions currencies/rates.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,8 @@ func (r *Rates) GetRate(from string, to string) (float64, error) {
}
return 0, errors.New("rates are nil")
}

// GetRates returns current rates
func (r *Rates) GetRates() *map[string]map[string]float64 {
return &r.Conversions
}
7 changes: 6 additions & 1 deletion docs/developers/currency-converter.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,9 @@ This configuration can be changed:
| 1 | USD | 1 | NO | 1 | YES |
| 1 | EUR | 1.13 | YES | 1.13 | YES |
| 1 | EUR | N/A | YES | N/A | NO |
| 1 | EUR | 1.13 | NO | N/A | NO |
| 1 | EUR | 1.13 | NO | N/A | NO |

## Debug

A dedicated endpoint will allow you to see what's happening within the currency converter.
See [currency rates endpoint](../endpoints/currency_rates.md) for more details.
111 changes: 111 additions & 0 deletions docs/endpoints/currency_rates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
## `GET /currency/rates`

This endpoint exposes active currency rate converter information in the server.
Information are:
- `info.active`: true if currency converter is active
- `info.source`: URL from which rates are fetched
- `info.fetchingIntervalNs`: Fetching interval from source in nanoseconds
- `info.lastUpdated`: Datetime when the rates where updated
- `info.rates`: Internal rates values

### Sample responses
#### Rate converter active
```json
{
"active": true,
"info": {
"source": "https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json",
"fetchingIntervalNs": 60000000000,
"lastUpdated": "2019-03-02T14:18:41.221063+01:00",
"rates": {
"GBP": {
"AUD": 1.8611576401,
"BGN": 2.2750325703,
"BRL": 5.0061650847,
"CAD": 1.7414619393,
"CHF": 1.3217708915,
"CNY": 8.8791178113,
"CZK": 29.8203982877,
"DKK": 8.6791596873,
"EUR": 1.163223525,
"GBP": 1,
"HKD": 10.3927042621,
"HRK": 8.645077238,
"HUF": 367.6484273218,
"IDR": 18689.5123766983,
"ILS": 4.8077191513,
"INR": 93.8663223525,
"ISK": 158.0820770519,
"JPY": 148.1365159129,
"KRW": 1491.3921459148,
"MXN": 25.5839382096,
"MYR": 5.394332775,
"NOK": 11.3144425833,
"NZD": 1.9374651033,
"PHP": 68.6139028476,
"PLN": 5.0130281035,
"RON": 5.5172855016,
"RUB": 87.2333891681,
"SEK": 12.2141959799,
"SGD": 1.7908989391,
"THB": 42.0074911595,
"TRY": 7.1224176438,
"USD": 1.3240973385,
"ZAR": 18.7774520752
},
"USD": {
"AUD": 1.4056048493,
"BGN": 1.7181762277,
"BRL": 3.7808134938,
"CAD": 1.3152068875,
"CHF": 0.9982429939,
"CNY": 6.705789335,
"CZK": 22.5213036985,
"DKK": 6.554774664,
"EUR": 0.8785030308,
"GBP": 0.7552314855,
"HKD": 7.8488974787,
"HRK": 6.5290345252,
"HUF": 277.6596679259,
"IDR": 14114.9081964333,
"ILS": 3.6309408767,
"INR": 70.8908020733,
"ISK": 119.3885618905,
"JPY": 111.8773609769,
"KRW": 1126.3463058948,
"MXN": 19.3217956602,
"MYR": 4.0739699552,
"NOK": 8.5450232803,
"NZD": 1.4632346482,
"PHP": 51.8193797769,
"PLN": 3.7859966617,
"RON": 4.1668277256,
"RUB": 65.8814020908,
"SEK": 9.2245453747,
"SGD": 1.3525432663,
"THB": 31.7253799526,
"TRY": 5.3790740578,
"USD": 1,
"ZAR": 14.1813230256
}
}
}
}
```

#### Rate converter set with constant rates
```json
{
"active": true,
"source": "",
"fetchingIntervalNs": 0,
"lastUpdated": "0001-01-01T00:00:00Z"
}
```

#### Rate converter not set
```json
{
"active": false
}
```
74 changes: 74 additions & 0 deletions endpoints/currency_rates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package endpoints

import (
"encoding/json"
"net/http"
"time"

"github.com/golang/glog"
"github.com/prebid/prebid-server/currencies"
)

// currencyRatesInfo holds currency rates information.
type currencyRatesInfo struct {
Active bool `json:"active"`
Source *string `json:"source,omitempty"`
FetchingInterval *time.Duration `json:"fetchingIntervalNs,omitempty"`
LastUpdated *time.Time `json:"lastUpdated,omitempty"`
Rates *map[string]map[string]float64 `json:"rates,omitempty"`
AdditionalInfo interface{} `json:"additionalInfo,omitempty"`
}

type rateConverter interface {
GetInfo() currencies.ConverterInfo
}

// newCurrencyRatesInfo creates a new CurrencyRatesInfo instance.
func newCurrencyRatesInfo(rateConverter rateConverter) currencyRatesInfo {

currencyRatesInfo := currencyRatesInfo{
Active: false,
}

if rateConverter == nil {
return currencyRatesInfo
}

currencyRatesInfo.Active = true

infos := rateConverter.GetInfo()
if infos == nil {
return currencyRatesInfo
}

source := infos.Source()
currencyRatesInfo.Source = &source

fetchingInterval := infos.FetchingInterval()
currencyRatesInfo.FetchingInterval = &fetchingInterval

lastUpdated := infos.LastUpdated()
currencyRatesInfo.LastUpdated = &lastUpdated

currencyRatesInfo.Rates = infos.Rates()
currencyRatesInfo.AdditionalInfo = infos.AdditionalInfo()

return currencyRatesInfo
}

// NewCurrencyRatesEndpoint returns current currency rates applied by the PBS server.
func NewCurrencyRatesEndpoint(rateConverter rateConverter) func(w http.ResponseWriter, r *http.Request) {
currencyRateInfo := newCurrencyRatesInfo(rateConverter)

return func(w http.ResponseWriter, r *http.Request) {
jsonOutput, err := json.Marshal(currencyRateInfo)
if err != nil {
glog.Errorf("/currency/rates Critical error when trying to marshal currencyRateInfo: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
w.Write(jsonOutput)
}
}
Loading

0 comments on commit 41ecc4f

Please sign in to comment.