Skip to content

Commit

Permalink
Add base action functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
LukoJy3D committed Dec 3, 2023
1 parent 13b6bce commit 1e5b509
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 1 deletion.
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Test metricsure
on: [push]
jobs:
metricsure:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Run metricsure
id: metricsure
uses: ./
with:
endpoint: 'https://prometheus.demo.do.prometheus.io'
metric: 'prometheus_remote_storage_exemplars_in_total'
label: 'instance'
values: 'demo.do.prometheus.io:9100,demo.do.prometheus.io:9090,http://localhost:9100'

- name: send message
uses: appleboy/[email protected]
with:
webhook_id: ${{ secrets.WEBHOOK_ID }}
webhook_token: ${{ secrets.WEBHOOK_TOKEN }}
message: "Metrics are not available for\n${{steps.metricsure.outputs.invalid_values}}"
7 changes: 7 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM python:3.9-slim

COPY * .

RUN pip install --no-cache-dir -r requirements.txt

CMD ["python", "validate.py"]
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,17 @@
[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://stand-with-ukraine.pp.ua)
[![Star on GitHub](https://img.shields.io/github/stars/LukoJy3D/metricsure.svg?style=social)](https://github.com/LukoJy3D/metricsure/stargazers)

# metricsure
Boost data integrity with a tool for validating metrics' existence for specified instances.

Simple github action to validate metric existence with specific labels and values against prometheus like endpoint.

## Inputs

`endpoint` - Prometheus like endpoint to query metrics from.
`metric` - Metric name to query. (Currently only supports single metric)
`label` - Label name to query. (Currently only supports single label)
`values` - Label values to query.

## Outputs

`invalid_values` - List of values that did not return any metrics from the endpoint.
32 changes: 32 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: "Metric existence check"
description: "Validate metric existence using python script quering against prometheus endpoint"
branding:
color: blue
icon: check-circle

inputs:
endpoint:
description: "Prometheus endpoint URL"
required: true
metric:
description: "Prometheus metric to check"
required: true
label:
description: "Label associated with the metric"
required: true
values:
description: "Comma seperated list of values to check against"
required: false

outputs:
invalid_values:
description: "Values that were not present in the metric check"

runs:
using: "docker"
image: "Dockerfile"
env:
ENDPOINT: ${{ inputs.endpoint }}
METRIC: ${{ inputs.metric }}
LABEL: ${{ inputs.label }}
VALUES: ${{ inputs.values }}
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
requests==2.26.0
42 changes: 42 additions & 0 deletions validate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import requests
from datetime import datetime, timedelta
import logging
import os

endpoint = os.environ.get('ENDPOINT')
metric = os.environ.get('METRIC')
label = os.environ.get('LABEL')
values = os.environ.get('VALUES', '')

def query_prometheus(endpoint, metric, label, label_value):
end_time = datetime.utcnow()
start_time = end_time - timedelta(days=1)

start_str = start_time.strftime('%Y-%m-%dT%H:%M:%SZ')
end_str = end_time.strftime('%Y-%m-%dT%H:%M:%SZ')

query = f'{metric}{{{label}="{label_value}"}}'
url = f'{endpoint}/api/v1/query_range?query={query}&start={start_str}&end={end_str}&step=1m'

response = requests.get(url)

if 'result' in response.json()['data'] and response.json()['data']['result'] and 'values' in response.json()['data']['result'][0]:
logging.info(f'Metric {metric} with {label}="{label_value}" exists in the last 24 hours.')
return True
else:
logging.error(f'Metric {metric} with {label}="{label_value}" not found in the last 24 hours.')
return False

label_values = [value.strip() for value in values.split(',') if value.strip()]
label_value_pair_with_no_metrics = []

for label_value in label_values:
if not query_prometheus(endpoint, metric, label, label_value):
label_value_pair_with_no_metrics.append(label_value)

if label_value_pair_with_no_metrics:
invalid_values = ','.join(label_value_pair_with_no_metrics)
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
print(f'invalid_values={invalid_values}', file=fh)
else:
print("All instances have metrics in the last 24 hours.")

0 comments on commit 1e5b509

Please sign in to comment.