Skip to content

Commit

Permalink
feat(jobs): allow config for metrics labels per address
Browse files Browse the repository at this point in the history
  • Loading branch information
Savid committed Sep 23, 2022
1 parent 44ade8a commit b9ee45a
Show file tree
Hide file tree
Showing 10 changed files with 392 additions and 65 deletions.
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,36 +32,42 @@ Ethereum Address Metrics Exporter relies entirely on a single `yaml` config file
| global.logging | `warn` | Log level (`panic`, `fatal`, `warn`, `info`, `debug`, `trace`) |
| global.metricsAddr | `:9090` | The address the metrics server will listen on |
| global.namespace | `eth_address` | The prefix added to every metric |
| global.labels[] | | Key value pair of labels to add to every metric |
| global.labels[] | | Key value pair of labels to add to every metric (optional) |
| execution.url | `http://localhost:8545` | URL to the execution node |
| execution.timeout | `10s` | Timeout for requests to the execution node |
| execution.headers[] | | Key value pair of headers to add on every request |
| addresses.eoa | | List of ethereum externally owned account addresses |
| addresses.eoa[].name | | Name of the address, will be a label on the metric |
| addresses.eoa[].address | | Ethereum externally owned account address |
| addresses.eoa[].labels[] | | Key value pair of labels to add to this address only (optional) |
| addresses.erc20 | | List of ethereum [ERC20](https://eips.ethereum.org/EIPS/eip-20) addresses |
| addresses.erc20[].name | | Name of the address, will be a label on the metric |
| addresses.erc20[].address | | Ethereum address |
| addresses.erc20[].contract | | Ethereum contract address |
| addresses.erc20[].labels[] | | Key value pair of labels to add to this address only (optional) |
| addresses.erc721 | | List of ethereum [ERC721](https://eips.ethereum.org/EIPS/eip-721) addresses |
| addresses.erc721[].name | | Name of the address, will be a label on the metric |
| addresses.erc721[].address | | Ethereum address |
| addresses.erc721[].contract | | Ethereum contract address |
| addresses.erc721[].labels[] | | Key value pair of labels to add to this address only (optional) |
| addresses.erc1155 | | List of ethereum [ERC1155](https://eips.ethereum.org/EIPS/eip-1155) addresses |
| addresses.erc1155[].name | | Name of the address, will be a label on the metric |
| addresses.erc1155[].address | | Ethereum address |
| addresses.erc1155[].contract | | Ethereum contract address |
| addresses.erc1155[].tokenID | | NFT Token Identifier |
| addresses.erc1155[].labels[] | | Key value pair of labels to add to this address only (optional) |
| addresses.uniswapPair | | List of [uniswap pair](https://v2.info.uniswap.org/pairs) addresses |
| addresses.uniswapPair[].name | | Name of the address, will be a label on the metric |
| addresses.uniswapPair[].from | | First symbol name, will be a label on the metric |
| addresses.uniswapPair[].to | | Second symbol name, will be a label on the metric |
| addresses.uniswapPair[].contract | | Ethereum contract address of the [uniswap pair](https://v2.info.uniswap.org/pairs) |
| addresses.uniswapPair[].labels[] | | Key value pair of labels to add to this address only (optional) |
| addresses.chainlinkDataFeed | | List of [chainlink data feed](https://docs.chain.link/docs/ethereum-addresses/) addresses |
| addresses.chainlinkDataFeed[].name | | Name of the address, will be a label on the metric |
| addresses.chainlinkDataFeed[].from | | First symbol name, will be a label on the metric |
| addresses.chainlinkDataFeed[].to | | Second symbol name, will be a label on the metric |
| addresses.chainlinkDataFeed[].contract | | Ethereum contract address of the [chainlink data feed](https://docs.chain.link/docs/ethereum-addresses/) |
| addresses.chainlinkDataFeed[].labels[] | | Key value pair of labels to add to this address only (optional) |


### Example
Expand All @@ -84,8 +90,13 @@ addresses:
eoa:
- name: John smith
address: 0x4B1D3c9BEf9D097F564DcD6cdF4558CB389bE3d5
labels:
type: friend
- name: Jane Doe
address: 0x4B1Df3549940C56d962F248f211788D66B4aAF39
labels:
type: acquaintance
company: NSA
erc20:
- name: Some ERC20 Contract
contract: 0x4B1DB272F63E03Dd37ea45330266AC9328A66DB6
Expand Down
23 changes: 23 additions & 0 deletions example_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ global:
logging: "debug" # panic,fatal,warm,info,debug,trace
metricsAddr: ":9090"
namespace: eth_address
# optional labels applied to all metrics
labels:
extra: label

Expand All @@ -15,30 +16,52 @@ addresses:
eoa:
- name: John smith
address: 0x4B1D3c9BEf9D097F564DcD6cdF4558CB389bE3d5
# optional metric labels to add to this address
labels:
type: friend
- name: Jane Doe
address: 0x4B1Df3549940C56d962F248f211788D66B4aAF39
# optional metric labels to add to this address
labels:
type: acquaintance
company: NSA
erc20:
- name: Some ERC20 Contract
contract: 0x4B1DB272F63E03Dd37ea45330266AC9328A66DB6
address: 0x4B1D1465b14cA06e72b942F361Fd3352Aa9c5368
# optional metric labels to add to this address
labels:
extra: label
erc721:
- name: Some ERC721 Contract
contract: 0x4B1D23bf5018189fDad68a0E607b6005ccF7E593
address: 0x4B1DB5c493955C8eF6D2a30CFf47495023b85C8d
# optional metric labels to add to this address
labels:
extra: label
erc1155:
- name: Some ERC1155 Contract
contract: 0x4B1D8DC12da8f658FA8BF0cdB18BB7D4dABB2DB3
tokenID: 100
address: 0x4B1D6D35f293AB699Bfc6DE141E031F3E3997BBe
# optional metric labels to add to this address
labels:
extra: label
# https://v2.info.uniswap.org/pairs
uniswapPair:
- name: eth->usdt
from: eth
to: usdt
contract: 0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852
# optional metric labels to add to this address
labels:
extra: label
# https://docs.chain.link/docs/ethereum-addresses/
chainlinkDataFeed:
- name: eth->usd
from: eth
to: usd
contract: 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419
# optional metric labels to add to this address
labels:
extra: label
60 changes: 54 additions & 6 deletions pkg/exporter/jobs/chainlink_data_feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ type ChainlinkDataFeed struct {
log logrus.FieldLogger
ChainlinkDataFeedBalance prometheus.GaugeVec
addresses []*AddressChainlinkDataFeed
labelsMap map[string]int
}

type AddressChainlinkDataFeed struct {
From string `yaml:"from"`
To string `yaml:"to"`
Contract string `yaml:"contract"`
Name string `yaml:"name"`
From string `yaml:"from"`
To string `yaml:"to"`
Contract string `yaml:"contract"`
Name string `yaml:"name"`
Labels map[string]string `yaml:"labels"`
}

const (
Expand All @@ -36,18 +38,39 @@ func (n *ChainlinkDataFeed) Name() string {
func NewChainlinkDataFeed(client api.ExecutionClient, log logrus.FieldLogger, namespace string, constLabels map[string]string, addresses []*AddressChainlinkDataFeed) ChainlinkDataFeed {
namespace += "_" + NameChainlinkDataFeed

labelsMap := map[string]int{
LabelName: 0,
LabelContract: 1,
LabelFrom: 2,
LabelTo: 3,
}

for address := range addresses {
for label := range addresses[address].Labels {
if _, ok := labelsMap[label]; !ok {
labelsMap[label] = len(labelsMap)
}
}
}

labels := make([]string, len(labelsMap))
for label, index := range labelsMap {
labels[index] = label
}

instance := ChainlinkDataFeed{
client: client,
log: log.WithField("module", NameChainlinkDataFeed),
addresses: addresses,
labelsMap: labelsMap,
ChainlinkDataFeedBalance: *prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "balance",
Help: "The balance of a ethereum chainlink data feed contract.",
ConstLabels: constLabels,
},
[]string{"name", "contract", "from", "to"},
labels,
),
}

Expand Down Expand Up @@ -80,6 +103,31 @@ func (n *ChainlinkDataFeed) tick(ctx context.Context) {
}
}

func (n *ChainlinkDataFeed) getLabelValues(address *AddressChainlinkDataFeed) []string {
values := make([]string, len(n.labelsMap))

for label, index := range n.labelsMap {
if address.Labels != nil && address.Labels[label] != "" {
values[index] = address.Labels[label]
} else {
switch label {
case LabelName:
values[index] = address.Name
case LabelContract:
values[index] = address.Contract
case LabelFrom:
values[index] = address.From
case LabelTo:
values[index] = address.To
default:
values[index] = LabelDefaultValue
}
}
}

return values
}

func (n *ChainlinkDataFeed) getBalance(address *AddressChainlinkDataFeed) error {
// call latestAnswer() which is 0x50d25bcd
latestAnswerData := "0x50d25bcd000000000000000000000000"
Expand All @@ -92,7 +140,7 @@ func (n *ChainlinkDataFeed) getBalance(address *AddressChainlinkDataFeed) error
return err
}

n.ChainlinkDataFeedBalance.WithLabelValues(address.Name, address.Contract, address.From, address.To).Set(hexStringToFloat64(balanceStr))
n.ChainlinkDataFeedBalance.WithLabelValues(n.getLabelValues(address)...).Set(hexStringToFloat64(balanceStr))

return nil
}
49 changes: 45 additions & 4 deletions pkg/exporter/jobs/eoa.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ type EOA struct {
log logrus.FieldLogger
EOABalance prometheus.GaugeVec
addresses []*AddressEOA
labelsMap map[string]int
}

type AddressEOA struct {
Address string `yaml:"address"`
Name string `yaml:"name"`
Address string `yaml:"address"`
Name string `yaml:"name"`
Labels map[string]string `yaml:"labels"`
}

const (
Expand All @@ -34,18 +36,36 @@ func (n *EOA) Name() string {
func NewEOA(client api.ExecutionClient, log logrus.FieldLogger, namespace string, constLabels map[string]string, addresses []*AddressEOA) EOA {
namespace += "_" + NameEOA

labelsMap := map[string]int{}
labelsMap[LabelName] = 0
labelsMap[LabelAddress] = 1

for address := range addresses {
for label := range addresses[address].Labels {
if _, ok := labelsMap[label]; !ok {
labelsMap[label] = len(labelsMap)
}
}
}

labels := make([]string, len(labelsMap))
for label, index := range labelsMap {
labels[index] = label
}

instance := EOA{
client: client,
log: log.WithField("module", NameEOA),
addresses: addresses,
labelsMap: labelsMap,
EOABalance: *prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "balance",
Help: "The balance of a ethereum externally owned account address.",
ConstLabels: constLabels,
},
[]string{"name", "address"},
labels,
),
}

Expand Down Expand Up @@ -78,14 +98,35 @@ func (n *EOA) tick(ctx context.Context) {
}
}

func (n *EOA) getLabelValues(address *AddressEOA) []string {
values := make([]string, len(n.labelsMap))

for label, index := range n.labelsMap {
if address.Labels != nil && address.Labels[label] != "" {
values[index] = address.Labels[label]
} else {
switch label {
case LabelName:
values[index] = address.Name
case LabelAddress:
values[index] = address.Address
default:
values[index] = LabelDefaultValue
}
}
}

return values
}

func (n *EOA) getBalance(address *AddressEOA) error {
balance, err := n.client.ETHGetBalance(address.Address, "latest")
if err != nil {
return err
}

balanceFloat64 := hexStringToFloat64(balance)
n.EOABalance.WithLabelValues(address.Name, address.Address).Set(balanceFloat64)
n.EOABalance.WithLabelValues(n.getLabelValues(address)...).Set(balanceFloat64)

return nil
}
Loading

0 comments on commit b9ee45a

Please sign in to comment.