{"id":26296431,"url":"https://github.com/charliedigital/hekaton","last_synced_at":"2025-03-15T04:18:23.667Z","repository":{"id":185994001,"uuid":"674445860","full_name":"CharlieDigital/hekaton","owner":"CharlieDigital","description":"A YAML driven performance testing tool in .NET","archived":false,"fork":false,"pushed_at":"2023-08-09T16:47:39.000Z","size":96,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-08-09T18:29:31.511Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CharlieDigital.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-08-04T01:20:04.000Z","updated_at":"2023-08-04T01:20:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"e9852637-a05e-489c-b5e3-84aaaa1ba963","html_url":"https://github.com/CharlieDigital/hekaton","commit_stats":null,"previous_names":["charliedigital/hekaton"],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CharlieDigital%2Fhekaton","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CharlieDigital%2Fhekaton/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CharlieDigital%2Fhekaton/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CharlieDigital%2Fhekaton/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CharlieDigital","download_url":"https://codeload.github.com/CharlieDigital/hekaton/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243681189,"owners_count":20330179,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-15T04:18:23.120Z","updated_at":"2025-03-15T04:18:23.659Z","avatar_url":"https://github.com/CharlieDigital.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hekaton (WIP)\n\n\u003e [T]he [Hecatoncheires](https://en.wikipedia.org/wiki/Hecatoncheires) were three monstrous giants, of enormous size and strength, each with fifty heads and one hundred arms\n\n## Intro\n\n\u003e ℹ️ This project is a work in progress.  I plan on working on it on and off!\n\nHekaton is a CLI performance testing tool that uses scenarios defined in YAML.\n\nAfter searching for easy to use, lightweight open source tools for performance testing, I found that most tools fell into two categories:\n\n1. **Too basic**; focused on raw *load testing* and do not simulate real user flows\n2. **Too complex**; designed for dedicated performance testing teams and difficult to adopt for small to medium sized teams\n\nHekaton is designed for the middle ground with a focus on simplicity (define test scenarios in a YAML file) while being more than just a simple load testing tool (model user journeys).\n\nIt is built around the concept of `Scenario`s  which represent the actions in a typical user journey through a system.  Rather than focusing on raw RPS, it's designed to allow teams to model real-world user journeys.\n\n## Sample YAML\n\n```yaml\nname: Basic Performance Test\n# Base URL to simplify downstream URLs\nbaseUrl: https://www.example.com\n\n# A series of independent scenarios.  Each scenario represents a logical flow\n# or user journey through the system.\nscenarios:\n\n# First scenario is an external user browsing the page. Up to 100 users.\n- name: User Browsing Landing Page\n\n  vusers:\n    initial: 5                          # Start the scenario with 5 users\n    max: 100                            # And create up to a total of 100 users\n    ramp:\n      every: 10s                        # Every 10 seconds\n      variation: 0.25                   # With a variation of up to 25%\n      add: 1                            # Add 1 user until reaching 10 total\n\n  pause:\n    duration: 7s                        # By default, pause 7 seconds after each step\n    variation: 0.25                     # With a variation of up to 25%\n\n  steps:\n\n  - name: Load Page\n    type: HttpGet                       # The type of the step; default is HttpGet\n    url: https://www.example.com        # Browse this URL\n    sla:\n      p90: 1500                         # Target p90 SLA\n      p95: 1600                         # Target P95 SLA\n    generates:                          # Generate these additional requests.\n    - \"/images/logo.png\"                # Uses base URL\n    - \"http://cdn.example.com/static/app.js\"\n\n  - name: Navigate Product Detail Page\n    type: HttpGet\n    url: https://www.example.com/p/123456\n\n# Second scenario is an admin user logging into the back-end.  Up to 5 users.\n- name: Admin User Scenario\n\n  delay: 100s                           # Delay the start of this scenario 100 seconds\n\n  vusers:\n    initial: 1                          # Start the scenario wit1 user\n    max: 5                              # And create up to a total of 5 users\n    ramp:\n      every: 1m                         # Every 1 minute\n      variation: 0.10                   # With a variation of up to 10%\n      add: 2                            # Add 2 users until reaching 5\n\n  rows:\n    source: \"./users.csv\"               # Read this CSV as input to each user\n    read: InOrder                       # Read the rows in order\n    columns:                            # With these columns\n    - username\n    - password\n\n  pause:\n    duration: 5s                        # By default, pause 5 seconds after each step\n    variation: 0.15                     # With a variation of up to 15%\n\n  steps:\n  - name: Admin User Login\n    type: HttpPost\n    url: /login\n\n    headers:\n      Content-type: application/json    # Include these headers\n\n    # Include this body with variable substitution with the column values from the\n    # CSV that contains the rows.\n    body: \"{ username: ___username, password: ___password }\"\n\n    pause:                              # Override the default 5s pause\n      duration: 10s\n      variation: 0.05\n\n    # Extract values from the response and assign to variables that can be used\n    # in subsequent steps in the scope of this virtual user.\n    response:\n      headers:\n        ___auth: Authorization           # Assign the Authorization header to __auth\n      cookies:\n        ___all: ''                       # A special assignment that contains all cookies\n        ___someVar: cookieName           # Assigned a specific cookie\n\n  - name: API Call Post Login\n    type: HttpGet\n    url: /api/load-user-data?page=0\u0026size=25\n\n    headers:\n      Authorization: ___auth             # Include these headers\n```\n\n## Sample Output\n\nThis screenshot shows a sample of the output.\n\n![Screenshot of console](Assets/console-screenshot.png)\n\nNote that the `user_browsing_landing_page.load_page` p90 is rendered in red.  This indicates that the value is above the specified p90 SLA for this request set a 1900ms.\n\n## Objectives\n\n- Easy to model user journeys using simple YAML manifests\n- Test definition stored as part of source control and executed remotely triggered from CI\n- Support running multi-step test scenarios representing user journeys in parallel\n- Support complex scenarios including performing authentication and processing of HTTP responses to extract parameters (headers, cookies)\n- Concurrent processing of requests, responses, and results\n- Pluggable output architecture to allow publishing results to console, S3, GitHub issue (as comment), etc.\n- Support comparison of performance metrics over time to identify deviations\n- Distributed processing of requests to simulate traffic from different origins\n\n## Status\n\n||Feature|\n|--|--|\n|✓|Parse YAML test manifest|\n|✓|Streaming calculation of mean, p90, p95, min, max|\n|✓|Write to live console output|\n|𐄂|Perform basic HTTP actions|\n|𐄂|Configure steps with CSV|\n|𐄂|Variable replacement in strings|\n|𐄂|Capture headers from HTTP response|\n|𐄂|Support scripting using JavaScript and JINT|\n|𐄂|Write results to collectors|\n|𐄂|Write errors to collectors|\n|𐄂|Distributed execution|\n|𐄂|Distributed results collection|\n|𐄂|Remote execution (send manifest to remote executor)|\n\n## Concepts\n\n|Term|Definition|\n|--|--|\n|`Test`|A test defines a set of `Scenario`s that model user journeys|\n|`Scenario`|A scenario encapsulates a series of steps to execute that represent actions that a user takes through a system.  For example, a scenario in e-commerce might be `browse landing page` → `add to cart` → `log in` → `checkout`|\n|`Step`|Each `Scenario` is a collection of `Step`s which represent individual substantive HTTP requests that are generated by the user.  This does not include downloading static assets like images, JS files, CSS files, etc. (unless you want to!)|\n|`VUser`|A virtual user represents one user performing the `Scenario`.|\n|`Row`|`VUser`s can be generated dynamically or defined in an input CSV file (e.g. usernames, email, passwords, etc.)|\n|`Pause`|Simulates how real users behave when interacting with the system.  Users will pause, read, scroll, and make decisions before acting.|\n\n## Why Scenarios\n\nIn most applications, there are actions performed by multiple roles within the system.  These different roles perform different actions that have an effect on the performance profile of a system.\n\nFor example, a content management system (CMS) will have publishers creating new content and consumers reading the published content.  These users will operate on different frequencies.  Ideally, we can easily model the load where 10% of the users are performing a publish operation while 90% of the users are reading the published content to simulate our actual traffic distribution.\n\n## Statistics\n\nThe statistics are computed using [T-Digest](https://www.sciencedirect.com/science/article/pii/S2665963820300403).  [The C# implementation](https://github.com/Cyral/t-digest-csharp) is a port of a reference Java implementation.  This approach provides an approximation of the P-90 without actually storing all of the values required to produce an exact P-90.\n\n## Development\n\n```shell\n# Run tests from root\ndotnet test\n\n# Run samples\ndotnet run -- -f samples/basic.yaml\n\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcharliedigital%2Fhekaton","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcharliedigital%2Fhekaton","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcharliedigital%2Fhekaton/lists"}