Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/develop' into featu…
Browse files Browse the repository at this point in the history
…re/htmlquery
  • Loading branch information
bastoscorp committed Nov 13, 2023
2 parents c25180f + e53ba2d commit 0d16767
Show file tree
Hide file tree
Showing 16 changed files with 230 additions and 74 deletions.
8 changes: 1 addition & 7 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,7 @@ builds:
goarch: arm
goarm: 5
archives:
- replacements:
darwin: macos
linux: linux
windows: windows
386: 386
amd64: amd64
format_overrides:
- format_overrides:
- goos: windows
format: zip
files:
Expand Down
71 changes: 49 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<h1 align="center">
<div align="center">
<img src="https://raw.githubusercontent.com/ddosify/ddosify/master/assets/ddosify-logo-db.svg#gh-dark-mode-only" alt="Ddosify logo dark" width="336px" /><br />
<img src="https://raw.githubusercontent.com/ddosify/ddosify/master/assets/ddosify-logo-wb.svg#gh-light-mode-only" alt="Ddosify logo light" width="336px" /><br />
Distributed Performance Testing Platform
</h1>
</div>

<h1 align="center">Ddosify: "Canva" of Observability</h1>

<p align="center">
<a href="https://github.com/ddosify/ddosify/releases" target="_blank"><img src="https://img.shields.io/github/v/release/ddosify/ddosify?style=for-the-badge&logo=github&color=orange" alt="ddosify latest version" /></a>&nbsp;
Expand All @@ -15,55 +16,81 @@
<a href="https://hub.docker.com/r/ddosify/ddosify" target="_blank"><img src="https://img.shields.io/docker/v/ddosify/ddosify?style=for-the-badge&logo=docker&label=docker&sort=semver" alt="ddosify docker image" /></a>
</p>

## Ddosify Self-Hosted (Distributed, No-code UI): [More →](./selfhosted/README.md)
<p align="center">
<img src="https://imagedelivery.net/jnIqn6NB1gbMLXIvlYKo5A/c6f26a7b-b878-4af7-774e-b0d65935df00/public" alt="Ddosify - Self-Hosted" />
<img src="https://imagedelivery.net/jnIqn6NB1gbMLXIvlYKo5A/5ed79d96-aef4-467d-f5d0-e17cc5c3e700/public" alt="Ddosify - Self-Hosted" />
</p>

### Quick Start

```bash
curl -sSL https://raw.githubusercontent.com/ddosify/ddosify/master/selfhosted/install.sh | bash
```

## Ddosify Engine (Single node, usage on CLI): [More →](./engine_docs/README.md)
<p align="center">
<img src="https://imagedelivery.net/jnIqn6NB1gbMLXIvlYKo5A/68e07b5f-22a5-4244-5dc2-9d02bd2c9e00/public" alt="Ddosify - Engine" />
<a href="https://aws.amazon.com/marketplace/pp/prodview-mwvnujtgjedjy" target="_blank"><img src="https://img.shields.io/badge/Available_on_aws_marketplace-FF9900?style=for-the-badge&logo=amazonaws&logoColor=white" height="40" alt="Available on aws marketplace" /></a>&nbsp;
</p>

### Quick Start
## What is Ddosify?
Ddosify is a magic wand that instantly spots glitches and guarantees the smooth performance of your infrastructure and application while saving you time and money. Ddosify Platform includes Performance Testing and Kubernetes Observability capabilities. It uniquely integrates these two parts and effortlessly spots the performance issues.

```bash
docker run -it --rm ddosify/ddosify ddosify -t https://app.servdown.com
```
Ddosify Stack consists of 4 parts. Those are **Ddosify Engine, Ddosify eBPF Agent (Alaz), Ddosify Self-Hosted, and Ddosify Cloud**.

## What is Ddosify?
Ddosify is a comprehensive performance testing platform, designed specifically to evaluate backend load and latency. It offers three distinct deployment options to cater to various needs: Ddosify Engine, Ddosify Self-Hosted, and Ddosify Cloud.
<p align="center">
<img src="https://imagedelivery.net/jnIqn6NB1gbMLXIvlYKo5A/3f995c37-10fb-4b37-c74f-db1685d0df00/public" alt="Ddosify Stack" />
</p>

### :rocket: Ddosify Engine
This is the load engine of Ddosify, written in Golang. It is fully open-source and can be used on the CLI. Ddosify Engine is available via Docker, Docker Extension, Homebrew Tap, and downloadable pre-compiled binaries from the releases page for macOS, Linux, and Windows.
This is the load engine of Ddosify, written in Golang. Ddosify Self-Hosted and Ddosify Cloud use it on load generation. It is fully open-source and can be used on the CLI as a standalone tool. Ddosify Engine is available via [Docker](https://hub.docker.com/r/ddosify/ddosify), [Docker Extension](https://hub.docker.com/extensions/ddosify/ddosify-docker-extension), [Homebrew Tap](https://github.com/ddosify/ddosify#homebrew-tap-macos-and-linux), and downloadable pre-compiled binaries from the [releases page](https://github.com/ddosify/ddosify/releases/latest) for macOS, Linux, and Windows.

Check out the [Engine Docs](https://github.com/ddosify/ddosify/tree/master/engine_docs) page for more information and usage.

### 🐝 Ddosify eBPF Agent (Alaz)
[Alaz](https://github.com/ddosify/alaz) is an open-source Ddosify eBPF agent that can inspect and collect Kubernetes (K8s) service traffic without the need for code instrumentation, sidecars, or service restarts. Alaz is deployed as a DaemonSet on your Kubernetes cluster. It collects metrics and sends them to Ddosify Cloud or Ddosify Self-Hosted. It also embeds prometheus node-exporter inside. So that you will have visibility on your cluster nodes also.

Check out the [Alaz](https://github.com/ddosify/alaz) repository for more information and usage.

### 🏠 Ddosify Self-Hosted
In contrast to the Engine version, Ddosify Self-Hosted features a web-based user interface and distributed load generation capabilities. While it shares many of the same functionalities as Ddosify Cloud, the Self-Hosted version is designed to be deployed within your own infrastructure for enhanced control and customization. And it's completely Free!
Ddosify Self-Hosted features a web-based user interface, distributed load generation, and Kubernetes Monitoring capabilities. While it shares many of the same functionalities as Ddosify Cloud, the Self-Hosted version is designed to be deployed within your own infrastructure for enhanced control and customization. There are two versions of it, **Community Edition (CE)** and **Enterprise Edition (EE)**. You can see the differences in the below comparison table.

Check out the [Self-Hosted](https://github.com/ddosify/ddosify/tree/master/selfhosted) page for more information and usage.

### ☁️ Ddosify Cloud
Ddosify Cloud enables users to assess backend endpoints' performance through load and latency testing, offering a user-friendly interface, comprehensive charts, extensive geographic targeting options, and additional features for an improved testing experience.
With Ddosify Cloud, anyone can test the performance of backend endpoints, monitor Kubernetes Clusters, and find the bottlenecks in the system. It has a No code UI, insightful charts, service maps, and more features!

Check out [Ddosify Cloud](https://ddosify.com) to start effortless testing.
Check out [Ddosify Cloud](https://app.ddosify.com/) to instantly find the performance issues on your system.

### ☁️ Ddosify Cloud vs 🏠 Ddosify Self-Hosted vs :rocket: Ddosify Engine
### ☁️ Ddosify Cloud vs 🏠 Ddosify Self-Hosted EE vs 🏡 Ddosify Self-Hosted CE
<p align="center">
<img src="https://imagedelivery.net/jnIqn6NB1gbMLXIvlYKo5A/7d6b9778-1367-426e-b6e9-5fc8f0d34200/public" alt="Ddosify versus" />
<img src="https://imagedelivery.net/jnIqn6NB1gbMLXIvlYKo5A/b539346a-171d-4acd-e57e-482947c10300/public" alt="Ddosify versus" />

*CE: Community Edition, EE: Enterprise Edition*
</p>

## Observability Features
#### ✅ Service Map
Easily get insights about what is going on in your cluster. <a href="https://docs.ddosify.com/cloud/observability/service-map" target="_blank">More →</a>
<p align="left">
<img src="https://imagedelivery.net/jnIqn6NB1gbMLXIvlYKo5A/891d68ac-554f-4828-a0fe-25ce935d1100/public" alt="Ddosify - Service Map Feature" />
</p>

#### ✅ Detailed Insights
Inspect incoming, outgoing traffic, SQL queries, and more. <a href="https://docs.ddosify.com/cloud/observability/service-map" target="_blank">More →</a>
<p align="left">
<img src="https://imagedelivery.net/jnIqn6NB1gbMLXIvlYKo5A/38760abe-8090-47b9-23e6-4cfb2db17000/public" alt="Ddosify - Detailed Insights Feature" />
</p>

#### ✅ Metrics Dashboard
The Metric Dashboard provides a straightforward way to observe Node Metrics. <a href="https://docs.ddosify.com/cloud/observability/metrics" target="_blank">More →</a>
<p align="left">
<img src="https://imagedelivery.net/jnIqn6NB1gbMLXIvlYKo5A/e736b581-7269-4ec4-9d77-7d375a5e3a00/public" alt="Ddosify - Metrics Dashboard Feature" />
</p>

## Features
#### ✅ Find Bottlenecks
Start a load test and monitor your system all within the same UI.
<p align="left">
<img src="https://imagedelivery.net/jnIqn6NB1gbMLXIvlYKo5A/32697752-ba0c-4c7b-8f59-f34095d6ef00/public" alt="Ddosify - Find Bottlenecks Feature" />
</p>

## Load Testing Features
#### ✅ Parametrization
Use built-in random data generators. <a href="https://docs.ddosify.com/concepts/parameterization" target="_blank">More →</a>
<p align="left">
Expand Down Expand Up @@ -112,7 +139,7 @@ Import Postman collections with ease and transform them into load testing scenar

This repository includes the source code for the Ddosify Engine. You can access Docker Images for the Ddosify Engine and Self Hosted on <a href="https://hub.docker.com/u/ddosify" target="_blank">Docker Hub</a>.

The [Engine Docs](https://github.com/ddosify/ddosify/tree/master/engine_docs) folder provides information on the installation, usage, and features of the Ddosify Engine. The [Self-Hosted](https://github.com/ddosify/ddosify/tree/master/selfhosted) folder contains installation instructions for the Self-Hosted version. To learn about the usage of both Self-Hosted and Cloud versions, please refer to the [this documentation](https://docs.ddosify.com/concepts/test-suite).
The [Engine Docs](https://github.com/ddosify/ddosify/tree/master/engine_docs) folder provides information on the installation, usage, and features of the Ddosify Engine. The [Self-Hosted](https://github.com/ddosify/ddosify/tree/master/selfhosted) folder contains installation instructions for the Self-Hosted version. [Ddosify eBPF agent (Alaz)](https://github.com/ddosify/alaz) has its own repository. To learn about the usage of both Self-Hosted and Cloud versions, please refer to the [this documentation](https://docs.ddosify.com/concepts/test-suite).

## Communication

Expand Down
2 changes: 1 addition & 1 deletion assets/ddosify.profile
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ cat<<ddosify

ddosify

printf "Simple usage:${NC} ddosify -t targetsite.com\n\n"
printf "Simple usage:${NC} ddosify -t https://testserver.ddosify.com\n\n"
12 changes: 6 additions & 6 deletions core/report/stdout.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func (s *stdout) printInDebugMode(input chan *types.ScenarioResult) {
color.Cyan("\n\nSTEP (%d) %-5s\n", verboseInfo.StepId, verboseInfo.StepName)
color.Cyan("-------------------------------------")
if len(verboseInfo.Envs) > 0 {
fmt.Fprintf(w, "%s\n", blue(fmt.Sprintf("- Environment Variables")))
fmt.Fprintf(w, "%s\n", blue("- Environment Variables"))
for eKey, eVal := range verboseInfo.Envs {
switch eVal.(type) {
case map[string]interface{}:
Expand All @@ -228,7 +228,7 @@ func (s *stdout) printInDebugMode(input chan *types.ScenarioResult) {
fmt.Fprintf(w, "\n")
}
if len(verboseInfo.TestData) > 0 {
fmt.Fprintf(w, "%s\n", blue(fmt.Sprintf("- Test Data")))
fmt.Fprintf(w, "%s\n", blue("- Test Data"))

for eKey, eVal := range verboseInfo.TestData {
switch eVal.(type) {
Expand Down Expand Up @@ -260,7 +260,7 @@ func (s *stdout) printInDebugMode(input chan *types.ScenarioResult) {
fmt.Fprint(out, b.String())
break
}
fmt.Fprintf(w, "%s\n", blue(fmt.Sprintf("- Request")))
fmt.Fprintf(w, "%s\n", blue("- Request"))
fmt.Fprintf(w, "\tTarget: \t%s \n", verboseInfo.Request.Url)
fmt.Fprintf(w, "\tMethod: \t%s \n", verboseInfo.Request.Method)

Expand All @@ -276,7 +276,7 @@ func (s *stdout) printInDebugMode(input chan *types.ScenarioResult) {

if verboseInfo.Error == "" {
// response
fmt.Fprintf(w, "\n%s\n", blue(fmt.Sprintf("- Response")))
fmt.Fprintf(w, "\n%s\n", blue("- Response"))
fmt.Fprintf(w, "\tStatusCode:\t%-5d \n", verboseInfo.Response.StatusCode)
fmt.Fprintf(w, "\tResponseTime:\t%-5d(ms) \n", verboseInfo.Response.ResponseTime)
fmt.Fprintf(w, "\t%s\n", "Headers: ")
Expand All @@ -291,14 +291,14 @@ func (s *stdout) printInDebugMode(input chan *types.ScenarioResult) {
}

if len(verboseInfo.FailedCaptures) > 0 {
fmt.Fprintf(w, "%s\n", yellow(fmt.Sprintf("- Failed Captures")))
fmt.Fprintf(w, "%s\n", yellow("- Failed Captures"))
for wKey, wVal := range verboseInfo.FailedCaptures {
fmt.Fprintf(w, "\t\t%s: \t%s \n", wKey, wVal)
}
}

if len(verboseInfo.FailedAssertions) > 0 {
fmt.Fprintf(w, "%s", yellow(fmt.Sprintf("- Failed Assertions")))
fmt.Fprintf(w, "%s", yellow("- Failed Assertions"))
for _, failAssertion := range verboseInfo.FailedAssertions {
fmt.Fprintf(w, "\n\t\tRule: %s\n", failAssertion.Rule)
prettyReceived, _ := json.MarshalIndent(failAssertion.Received, "\t\t", "\t")
Expand Down
14 changes: 11 additions & 3 deletions core/scenario/requester/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,12 @@ func (h *HttpRequester) prepareReq(envs map[string]interface{}, trace *httptrace
if errURL != nil {
return nil, errURL
}
httpReq.Host = httpReq.URL.Host

// If Host is not given in the header, set it from the original URL
// Note that a temporary url used in initRequest
if httpReq.Header.Get("Host") == "" {
httpReq.Host = httpReq.URL.Host
}

// header
if h.containsDynamicField["header"] {
Expand Down Expand Up @@ -619,10 +624,13 @@ func (h *HttpRequester) initRequestInstance() (err error) {
// Headers
header := make(http.Header)
for k, v := range h.packet.Headers {
header.Set(k, v)
// Since we use a temp url, we need to override the request.Host either
// it will be app.ddosify.com
// or it will be the host from the headers
// later on prepareReq, we will override the host if it is set in the headers
if strings.EqualFold(k, "Host") {
h.request.Host = v
} else {
header.Set(k, v)
}
}

Expand Down
1 change: 1 addition & 0 deletions core/scenario/requester/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ func TestInitRequest(t *testing.T) {
expectedWithHeaders.Header.Set("Header1", "Value1")
expectedWithHeaders.Header.Set("Header2", "Value2")
expectedWithHeaders.Header.Set("User-Agent", "Firefox")
expectedWithHeaders.Header.Set("Host", "test.com")
expectedWithHeaders.Host = "test.com"
expectedWithHeaders.SetBasicAuth(sWithHeaders.Auth.Username, sWithHeaders.Auth.Password)

Expand Down
12 changes: 12 additions & 0 deletions core/scenario/scripting/assertion/assert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,13 @@ func TestAssert(t *testing.T) {
},
expected: true,
},
{
input: "p98(iteration_duration) == 99",
envs: &evaluator.AssertEnv{
TotalTime: []int64{34, 37, 39, 44, 45, 55, 66, 67, 72, 75, 77, 89, 92, 98, 99},
},
expected: true,
},
{
input: "p95(iteration_duration) == 99",
envs: &evaluator.AssertEnv{
Expand Down Expand Up @@ -810,6 +817,11 @@ func TestAssert(t *testing.T) {
expected: false,
expectedError: "ArgumentError",
},
{
input: "p98(23)", // arg must be array
expected: false,
expectedError: "ArgumentError",
},
{
input: "p95(23)", // arg must be array
expected: false,
Expand Down
9 changes: 9 additions & 0 deletions core/scenario/scripting/assertion/evaluator/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,15 @@ func Eval(node ast.Node, env *AssertEnv, receivedMap map[string]interface{}) (in
}
}
return percentile(arr, 99)
case P98:
arr, ok := args[0].([]int64)
if !ok {
return false, ArgumentError{
msg: "argument of percentile funcs must be an int64 array",
wrappedErr: nil,
}
}
return percentile(arr, 98)
case P95:
arr, ok := args[0].([]int64)
if !ok {
Expand Down
2 changes: 2 additions & 0 deletions core/scenario/scripting/assertion/evaluator/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ var assertionFuncMap = map[string]struct{}{
MAX: {},
AVG: {},
P99: {},
P98: {},
P95: {},
P90: {},
P80: {},
Expand All @@ -234,6 +235,7 @@ const (
MAX = "max"
AVG = "avg"
P99 = "p99"
P98 = "p98"
P95 = "p95"
P90 = "p90"
P80 = "p80"
Expand Down
6 changes: 3 additions & 3 deletions core/types/scenario.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (s *Scenario) validate() error {

// add global envs
for key := range s.Envs {
if !envVarNameRegexp.Match([]byte(key)) { // not a valid env definition
if !envVarNameRegexp.MatchString(key) { // not a valid env definition
return fmt.Errorf("env key is not valid: %s", key)
}
definedEnvs[key] = struct{}{} // exist
Expand All @@ -98,7 +98,7 @@ func (s *Scenario) validate() error {
return fmt.Errorf("csv key can not have dot in it: %s", key)
}
for _, s := range splitted {
if !envVarNameRegexp.Match([]byte(s)) { // not a valid env definition
if !envVarNameRegexp.MatchString(s) { // not a valid env definition
return fmt.Errorf("csv key is not valid: %s", key)
}
}
Expand All @@ -112,7 +112,7 @@ func (s *Scenario) validate() error {

// enrich Envs map with captured envs from each step
for _, ce := range st.EnvsToCapture {
if !envVarNameRegexp.Match([]byte(ce.Name)) { // not a valid env definition
if !envVarNameRegexp.MatchString(ce.Name) { // not a valid env definition
return fmt.Errorf("captured env key is not valid: %s", ce.Name)
}
definedEnvs[ce.Name] = struct{}{}
Expand Down
34 changes: 31 additions & 3 deletions engine_docs/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<h1 align="center">
<div align="center">
<img src="https://raw.githubusercontent.com/ddosify/ddosify/master/assets/ddosify-logo-db.svg#gh-dark-mode-only" alt="Ddosify logo dark" width="336px" /><br />
<img src="https://raw.githubusercontent.com/ddosify/ddosify/master/assets/ddosify-logo-wb.svg#gh-light-mode-only" alt="Ddosify logo light" width="336px" /><br />
Ddosify - High-performance load testing tool
</h1>
</div>

<h1 align="center">Ddosify Engine: High-performance load testing tool</h1>

<p align="center">
<a href="https://github.com/ddosify/ddosify/releases" target="_blank"><img src="https://img.shields.io/github/v/release/ddosify/ddosify?style=for-the-badge&logo=github&color=orange" alt="ddosify latest version" /></a>&nbsp;
Expand Down Expand Up @@ -746,6 +747,7 @@ Unlike assertions focused on individual steps, which determine the success or fa
| Function | Parameters | Description |
| ---------- | ---------------------- | ------------------------------------------------- |
| `p99` | ( arr `int array` ) | 99th percentile, use as `p99(iteration_duration)` |
| `p98` | ( arr `int array` ) | 98th percentile, use as `p98(iteration_duration)` |
| `p95` | ( arr `int array`) | 95th percentile, use as `p95(iteration_duration)` |
| `p90` | ( arr `int array`) | 90th percentile, use as `p90(iteration_duration)` |
| `p80` | ( arr `int array`) | 80th percentile, use as `p80(iteration_duration)` |
Expand Down Expand Up @@ -1055,6 +1057,32 @@ Following fields are available for cookie assertion:
- Select Open
- Close the opened terminal

### OS Limit - Too Many Open Files

If you create large load tests, you may encounter the following errors:

```
Server Error Distribution (Count:Reason):
199 :Get "https://example.ddosify.com": dial tcp 188.114.96.3:443: socket: too many open files
159 :Get "https://example.ddosify.com": dial tcp 188.114.97.3:443: socket: too many open files
```

This is because the OS limits the number of open files. You can check the current limit by running `ulimit -n` command. You can increase this limit to 50000 by running the following command on both Linux and macOS.

```bash
ulimit -n 50000
```

But this will only increase the limit for the current session. To increase the limit permanently, you can change the shell configuration file. For example, if you are using bash, you can add the following lines to `~/.bashrc` file. If you are using zsh, you can add the following lines to `~/.zshrc` file.

```bash
# For .bashrc
echo "ulimit -n 50000" >> ~/.bashrc

# For .zshrc
echo "ulimit -n 50000" >> ~/.zshrc
```

## Communication

You can join our [Discord Server](https://discord.gg/9KdnrSUZQg) for issues, feature requests, feedbacks or anything else.
Expand Down
Loading

0 comments on commit 0d16767

Please sign in to comment.