Skip to content

Instantly share code, notes, and snippets.

@diegolovison
Last active April 17, 2025 14:46
Show Gist options
  • Save diegolovison/568e1614830b5bcad97527dfe832dd3f to your computer and use it in GitHub Desktop.
Save diegolovison/568e1614830b5bcad97527dfe832dd3f to your computer and use it in GitHub Desktop.
Collect Hyperfoil data from Jenkins and plot
import os
import requests
from requests.auth import HTTPBasicAuth
import pandas as pd
import json
import matplotlib.pyplot as plt


class DownloadJenkinsHyperfoilData:
    def __init__(self, all_json_urls):
        self.all_json_urls = all_json_urls
        self.username = os.environ['JENKINS_USERNAME']
        self.token = os.environ['JENKINS_TOKEN']

    def download_all_json_hyperfoil_data(self, all_json_url):
        os.makedirs('/tmp/hyperfoil-notebook/', exist_ok=True)
        hash_key = hash(all_json_url)
        output_file = f'/tmp/hyperfoil-notebook/{hash_key}'
        if not os.path.exists(output_file):
            response = requests.get(all_json_url, auth=HTTPBasicAuth(self.username, self.token), verify=False)
            if response.status_code == 200:
                with open(output_file, 'w', encoding='utf-8') as f:
                    for chunk in response.iter_content(chunk_size=8192, decode_unicode=True):
                        if chunk:
                            f.write(chunk)
            else:
                raise Exception(f'Failed to download {all_json_url}')
        with open(output_file) as f:
            json_data = json.load(f)
        return hash_key, json_data

    def get_stats(self, hyperfoil_phase, metric):
        output_data = []
        for all_json_url in self.all_json_urls:
            hash_key, json_data = self.download_all_json_hyperfoil_data(all_json_url)
            df_stats = pd.DataFrame([
                {k: v for k, v in d.items()} for d in json_data['stats']
            ])
            filter_df = df_stats[(df_stats['phase'] == hyperfoil_phase) & (df_stats['metric'] == metric)]
            output_data.append({
                'all_json_url': all_json_url,
                'hash_key': hash_key,
                'df_stats': df_stats,
                'filter_df': filter_df,
            })
        return output_data

    def access_nested_dict(self, serie, key_string):
        keys = key_string.split(',')
        value = serie
        for key in keys:
            value = value[key]
        return value

    def plot(self, k, request_counts, stats_list):
        s = 20
        fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4), sharex=False)
        for i in range(len(request_counts)):
            ax1.scatter(i, request_counts[i], c='blue', s=s)
            ax2.scatter(i, stats_list[i], c='blue', s=s)
        ax1.set_title('Requests')
        ax1.set_ylabel('n Requests')
        ax2.set_title(k)
        ax2.set_ylabel('Latency')
        plt.tight_layout()
        plt.show()

    def run(self, hyperfoil_phase, metric):

        output_data = self.get_stats(hyperfoil_phase, metric)
        key_string = 'percentileResponseTime,50.0'
        for data in output_data:
            filter_df = data['filter_df']
            for index, row in filter_df.iterrows():
                k = f'{row["name"]} - {row["metric"]}'
                request_counts = []
                stats_list = []
                for serie in row['series']:
                    request_counts.append(serie['requestCount'])
                    stats_list.append(self.access_nested_dict(serie, key_string))
                self.plot(k, request_counts, stats_list)
%env JENKINS_USERNAME=......
%env JENKINS_TOKEN=......
%env JENKINS_EXAMPLE_URL=......

if __name__ == '__main__':
    DownloadJenkinsHyperfoilData(all_json_urls=[os.environ['JENKINS_EXAMPLE_URL']]).run('steadyState', 'getPolicyHolder')
env: JENKINS_USERNAME=......
env: JENKINS_TOKEN=......
env: JENKINS_EXAMPLE_URL=......

plot-hyperfoil-data_1_1

plot-hyperfoil-data_1_2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment