{"id":13413589,"url":"https://github.com/fortio/fortio","last_synced_at":"2025-05-13T22:04:05.155Z","repository":{"id":37382473,"uuid":"106351459","full_name":"fortio/fortio","owner":"fortio","description":"Fortio load testing library, command line tool, advanced echo server and web UI in go (golang). Allows to specify a set query-per-second load and record latency histograms and other useful stats.","archived":false,"fork":false,"pushed_at":"2025-05-08T13:07:35.000Z","size":2844,"stargazers_count":3518,"open_issues_count":82,"forks_count":260,"subscribers_count":51,"default_branch":"master","last_synced_at":"2025-05-13T17:09:23.029Z","etag":null,"topics":["go","golang","golang-application","golang-library","grpc","http","performance","performance-testing","performance-visualization","proxy"],"latest_commit_sha":null,"homepage":"https://fortio.org","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fortio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-10-10T01:01:39.000Z","updated_at":"2025-05-12T14:57:55.000Z","dependencies_parsed_at":"2023-07-14T01:30:06.609Z","dependency_job_id":"b029c8c5-0471-4477-8974-19bceb0ffbd2","html_url":"https://github.com/fortio/fortio","commit_stats":{"total_commits":595,"total_committers":39,"mean_commits":"15.256410256410257","dds":"0.38991596638655457","last_synced_commit":"a4db2fe0cefec5d006c48add67bfe16c77af21d0"},"previous_names":["istio/fortio"],"tags_count":286,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fortio%2Ffortio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fortio%2Ffortio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fortio%2Ffortio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fortio%2Ffortio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fortio","download_url":"https://codeload.github.com/fortio/fortio/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254036813,"owners_count":22003653,"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":["go","golang","golang-application","golang-library","grpc","http","performance","performance-testing","performance-visualization","proxy"],"created_at":"2024-07-30T20:01:43.925Z","updated_at":"2025-05-13T22:04:05.077Z","avatar_url":"https://github.com/fortio.png","language":"Go","funding_links":[],"categories":["Go","网络","Networking","Tools","网络相关库","golang","Repositories","Relational Databases"],"sub_categories":["音译","Strings","Testing","交流","Advanced Console UIs","暂未分类","Transliteration","Uncategorized","暂未分类这些库被放在这里是因为其他类别似乎都不适合。"],"readme":"\u003c!-- 1.69.4 --\u003e\n# Fortio\n\n[![Awesome Go](https://fortio.org/mentioned-badge.svg)](https://github.com/avelino/awesome-go#networking)\n[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6054/badge)](https://bestpractices.coreinfrastructure.org/projects/6054)\n[![Go Report Card](https://goreportcard.com/badge/fortio.org/fortio)](https://goreportcard.com/report/fortio.org/fortio)\n[![GoDoc](https://godoc.org/fortio.org/fortio?status.svg)](https://godoc.org/fortio.org/fortio)\n[![codecov](https://codecov.io/gh/fortio/fortio/branch/master/graph/badge.svg)](https://codecov.io/gh/fortio/fortio)\n[![CircleCI](https://circleci.com/gh/fortio/fortio.svg?style=shield)](https://circleci.com/gh/fortio/fortio)\n[![Docker Pulls](https://img.shields.io/docker/pulls/fortio/fortio.svg)](https://hub.docker.com/r/fortio/fortio)\n\u003cimg src=\"./ui/static/img/fortio-logo-gradient-no-bg.svg\" height=109 width=167 align=right /\u003e\n\nFortio (Φορτίο) started as, and is, [Istio](https://istio.io/)'s load testing tool and later (2018) graduated to be its own project.\n\nFortio runs at a specified query per second (qps) and records a histogram of execution time\nand calculates percentiles (e.g., p99 i.e., the response time such as 99% of the requests take less than that number (in seconds, SI unit)).\nIt can run for a set duration, for a fixed number of calls, or until interrupted (at a constant target QPS, or max speed/load per connection/thread).\n\nThe name fortio comes from Greek [φορτίο](https://fortio.org/fortio.mp3) which means load/burden.\n\nFortio is a fast, small (less than 6Mb Docker image download, minimal dependencies), reusable, embeddable go library as well as a command line tool and server process,\nthe server includes a simple web UI and REST API to trigger run and see graphical representation of the results (both a single latency graph and a multiple results comparative min, max, avg, qps and percentiles graphs).\n\nFortio also includes a set of server side features (similar to httpbin) to help debugging and testing: request echo back including headers, adding latency or error codes with a probability distribution, TCP echoing, TCP proxying, HTTP fan out/scatter and gather proxy server, gRPC echo/health in addition to HTTP, etc...\n\nFortio is quite mature and very stable with no known major bugs (lots of possible improvements if you want to contribute though!),\nand when bugs are found they are fixed quickly, so after 1 year of development and 42 incremental releases, we reached 1.0 in June 2018.\n\nFortio components can be used a library even for unrelated projects, for instance the `stats`, or `fhttp` utilities both client and server.\nA recent addition is the new `jrpc` JSON Remote Procedure Calls library package ([docs](https://pkg.go.dev/fortio.org/fortio/jrpc)).\n\nWe also have moved some of the library to their own toplevel package, like:\n- Dynamic flags: [fortio.org/dflag](https://github.com/fortio/dflag#fortio-dynamic-flags)\n- Logger: [fortio.org/log](https://github.com/fortio/log#log) - now using structured JSON logs for servers (vs text for CLIs) since fortio 1.55 / log 1.4. In color since fortio 1.57 / log 1.6.\n- Version helper: [fortio.org/version](https://github.com/fortio/version#version)\n- CLI helpers integrating the above to reduce toil making new tools [fortio.org/cli](https://github.com/fortio/cli#cli) and servers [fortio.org/scli](https://github.com/fortio/scli#scli) for arguments, flags, usage, dynamic config, etc...\n\nIf you want to connect to fortio using HTTPS and fortio to provide real TLS certificates, or to multiplex gRPC and regular HTTP behind a single port, check out [Fortio Proxy](https://github.com/fortio/proxy#fortio-proxy).\n\nIf you want fortio to generate detailed Open Telemetry traces use [Fortiotel](https://github.com/fortio/fortiotel#fortiotel).\n\nFortio now embeds the [grol scripting language](https://grol.io/), available using `fortio script`.\n## Installation\n\nWe publish a multi architecture Docker image (linux/amd64, linux/arm64, linux/ppc64le, linux/s390x) `fortio/fortio`.\n\nFor instance:\n```shell\ndocker run -p 8080:8080 -p 8079:8079 fortio/fortio server \u0026 # For the server\ndocker run fortio/fortio load -logger-force-color http://www.google.com/ # For a test run, forcing color instead of JSON log output\n```\n\nYou can install from source:\n\n1. [Install go](https://golang.org/doc/install) (golang 1.18 or later)\n2. `go install fortio.org/fortio@latest`\n3. you can now run `fortio` (from your gopath bin/ directory, usually `~/go/bin`)\n\nThe [releases](https://github.com/fortio/fortio/releases) page has binaries for many OS/architecture combinations (see assets):\n\n```shell\ncurl -L https://github.com/fortio/fortio/releases/download/v1.69.4/fortio-linux_amd64-1.69.4.tgz \\\n | sudo tar -C / -xvzpf -\n# or the debian package\nwget https://github.com/fortio/fortio/releases/download/v1.69.4/fortio_1.69.4_amd64.deb\ndpkg -i fortio_1.69.4_amd64.deb\n# or the rpm\nrpm -i https://github.com/fortio/fortio/releases/download/v1.69.4/fortio-1.69.4-1.x86_64.rpm\n# and more, see assets in release page\n```\n\nOn macOS you can also install Fortio using [Homebrew](https://brew.sh/):\n\n```shell\nbrew install fortio\n```\n\nOn Windows, download https://github.com/fortio/fortio/releases/download/v1.69.4/fortio_win_1.69.4.zip and extract `fortio.exe` to any location, then using the Windows Command Prompt:\n```\nfortio.exe server\n```\n(at the prompt, allow the Windows firewall to let connections in)\n\nOnce `fortio server` is running, you can visit its web UI at [http://localhost:8080/fortio/](http://localhost:8080/fortio/)\n\nYou can get a preview of the reporting/graphing UI at [https://demo.fortio.org](https://demo.fortio.org)\n\u003c!--\nand on [istio.io/docs/performance-and-scalability/synthetic-benchmarks/](https://istio.io/docs/performance-and-scalability/synthetic-benchmarks/)\n--\u003e\n\n## Command line arguments\n\nFortio can be a HTTP or gRPC load generator, gathering statistics using the `load` subcommand,\nor start simple HTTP and gRPC ping servers, as well as a basic web UI, result graphing, TCP/UDP echo, proxies, https redirector,\nwith the `server` command or issue gRPC ping messages using the `grpcping` command.\nIt can also fetch a single URL's for debugging when using the `curl` command (or the `-curl` flag to the load command).\nLikewise you can establish a single TCP (or Unix domain or UDP (use `udp://` prefix)) connection using the `nc` command (like the standalone netcat package).\nYou can run just the redirector with `redirect` or just the TCP echo with `tcp-echo`.\nIf you saved JSON results (using the web UI or directly from the command line), you can browse and graph those results using the `report` command.\n\nYou can run interactive fortio.load() scripts using `script` or already written [grol scripts](https://grol.io/), a simplified go like language, from a file, like\n```\nfortio script -init 'url=\"http://localhost:8080/\"' scripting_example.gr\n...\n---- 🎉 Ramp up to 8000 qps done without error, actual qps 7993.678998 ----\n---- 🎉 Ramp up to 9000 qps done without error, actual qps 8994.693886 ----\n---- 🎉 Ramp up to 10000 qps done without error, actual qps 9996.013250 ----\n```\nSee [scripting_example.gr](scripting_example.gr) or the tests in [cli_tests.txtar](cli_test.txtar).\n\nThe `version` command will print the short print version. `fortio buildinfo` will print the full\nbuild information.\n\nLastly, you can learn which flags are available using `help` command.\n\nMost important flags for HTTP load generation:\n\n| Flag         | Description, example |\n| -------------|----------------------|\n| `-qps rate` | Total Queries Per Seconds across all connections/threads or 0 for no wait/max qps |\n| `-nocatchup` | Do not try to reach the target qps by going faster when the service falls behind and then recovers. Makes QPS an absolute ceiling even if the service has some spikes in latency, fortio will not compensate (but also won't stress the target more than the set qps). Recommended to use jointly with `-uniform`. |\n| `-c connections` | Number of parallel simultaneous connections (and matching go routine) |\n| `-t duration` | How long to run the test (for instance `-t 30m` for 30 minutes) or 0 to run until ^C, example (default 5s) |\n| `-n numcalls` | Run for exactly this number of calls instead of duration. Default (0) is to use duration (-t). |\n| `-payload str` or `-payload-file fname` | Switch to using POST with the given payload (see also `-payload-size` for random payload)|\n| `-uniform` | Spread the calls in time across threads for a more uniform call distribution. Works even better in conjunction with `-nocatchup`. |\n| `-r resolution` | Resolution of the histogram lowest buckets in seconds (default 0.001 i.e, 1ms), use 1/10th of your expected typical latency |\n| `-H \"header: value\"` | Can be specified multiple times to add headers (including Host:) |\n| `-a`     |  Automatically save JSON result with filename based on labels and timestamp |\n| `-json filename` | Filename or `-` for stdout to output JSON result (relative to `-data-dir` by default, should end with .json if you want `fortio report` to show them; using `-a` is typically a better option)|\n| `-labels \"l1 l2 ...\"` |  Additional config data/labels to add to the resulting JSON, defaults to target URL and hostname|\n| `-h2` |  Client calls will attempt to negotiate HTTP/2 instead of HTTP/1.1, implies `-stdclient`|\n| `-X method` | Change HTTP method to the one specified instead of automatic HTTP GET or POST based on `-payload-*` or `-content-type`|\n| `-logger-force-color` | For interactive runs for color instead of JSON output|\n| `-logger-no-color` | Force JSON output even when run from terminal|\n\nChanging the HTTP options like the TLS options `-cert`, `-key`, `-cacert` when launching an echo/UI/rapi server will make these options the default for runs initiated from that server (or fetches/proxies etc.).\n\nFull list of command line flags (`fortio help`):\n\u003cdetails\u003e\n\u003c!-- use release/updateFlags.sh to update this section --\u003e\n\u003cpre\u003e\n\u003c!-- USAGE_START --\u003e\nΦορτίο 1.69.4 usage:\n        fortio command [flags] target\nwhere command is one of: load (load testing), server (starts ui, rest api,\n http-echo, redirect, proxies, tcp-echo, udp-echo and grpc ping servers),\n tcp-echo (only the tcp-echo server), udp-echo (only udp-echo server),\n report (report only UI server), redirect (only the redirect server),\n proxies (only the -M and -P configured proxies), grpcping (gRPC client),\n or curl (single URL debug), or nc (single tcp or udp:// connection),\n or script (interactive grol script mode or script file),\n or version (prints the full version and build details).\nwhere target is a URL (http load tests) or host:port (grpc health test),\n or tcp://host:port (tcp load test), or udp://host:port (udp load test).\nor 1 of the special arguments\n        fortio {help|envhelp|version|buildinfo}\nflags:\n  -H key:value\n        Additional HTTP header(s) or gRPC metadata. Multiple key:value pairs can be\npassed using multiple -H.\n  -L    Follow redirects (implies -std-client) - do not use for load test\n  -M value\n        HTTP multi proxy to run, e.g -M \"localport1 baseDestURL1 baseDestURL2\" -M ...\n  -P value\n        TCP proxies to run, e.g -P \"localport1 dest_host1:dest_port1\" -P \"[::1]:0\nwww.google.com:443\" ...\n  -X string\n        HTTP method to use instead of GET/POST depending on payload/content-type\n  -a    Automatically save JSON result with filename based on labels \u0026 timestamp\n  -abort-on int\n        HTTP status code that if encountered aborts the run. e.g., 503 or -1 for socket\nerrors.\n  -access-log-file path\n        file path to log all requests to. Maybe have performance impacts\n  -access-log-format format\n        format for access log. Supported values: [json, influx] (default \"json\")\n  -allow-initial-errors\n        Allow and don't abort on initial warmup errors\n  -base-url URL\n        base URL used as prefix for data/index.tsv generation. (when empty, the URL from\nthe first request is used)\n  -c int\n        Number of connections/goroutine/threads (default 4)\n  -cacert Path\n        Path to a custom CA certificate file to be used for the TLS client connections,\nif empty, use https:// prefix for standard internet/system CAs\n  -calc-qps\n        Calculate the qps based on number of requests (-n) and duration (-t)\n  -cert Path\n        Path to the certificate file to be used for client or server TLS\n  -compression\n        Enable HTTP compression\n  -config-dir directory\n        Config directory to watch for dynamic flag changes\n  -config-port port\n        Config port to open for dynamic flag UI/api\n  -connection-reuse min:max\n        Range min:max for the max number of connections to reuse for each thread, default\nto unlimited. e.g. 10:30 means randomly choose a max connection reuse threshold between\n10 and 30 requests.\n  -content-type string\n        Sets HTTP content type. Setting this value switches the request method from GET\nto POST.\n  -curl\n        Just fetch the content once\n  -curl-stdout-headers\n        Restore pre 1.22 behavior where HTTP headers of the fast client are output to\nstdout in curl mode. now stderr by default.\n  -data-dir Directory\n        Directory where JSON results are stored/read (default \".\")\n  -dns-method method\n        When a name resolves to multiple ip, which method to pick: cached-rr for cached\nround-robin, rnd for random, first for first answer (pre 1.30 behavior), rr for\nround-robin. (default cached-rr)\n  -echo-debug-path URI\n        http echo server URI for debug, empty turns off that part (more secure) (default\n\"/debug\")\n  -echo-server-default-params value\n        Default parameters/querystring to use if there isn't one provided explicitly. E.g\n\"status=404\u0026delay=3s\"\n  -gomaxprocs int\n        Setting for runtime.GOMAXPROCS, \u0026lt; 1 doesn't change the default\n  -grpc\n        Use gRPC (health check by default, add -ping for ping) for load testing\n  -grpc-compression\n        Enable gRPC compression\n  -grpc-max-streams uint\n        MaxConcurrentStreams for the gRPC server. Default (0) is to leave the option\nunset.\n  -grpc-ping-delay duration\n        gRPC ping delay in response\n  -grpc-port port\n        grpc server port. Can be in the form of host:port, ip:port or port or\n/unix/domain/path or \"disabled\" to not start the gRPC server. (default \"8079\")\n  -h2\n        Attempt to use HTTP/2.0 / h2 (instead of HTTP/1.1) for both TLS and h2c\n  -halfclose\n        When not keepalive, whether to half close the connection (only for fast http)\n  -health\n        gRPC ping client mode: use health instead of ping\n  -healthservice string\n        which service string to pass to health check\n  -http-port port\n        http-echo server port. Can be in the form of host:port, ip:port, port or\n/unix/domain/path or \"disabled\". (default \"8080\")\n  -http1.0\n        Use HTTP/1.0 (instead of HTTP/1.1)\n  -httpbufferkb kbytes\n        Size of the buffer (max data size) for the optimized HTTP client in kbytes\n(default 128)\n  -httpccch\n        Check for Connection: Close Header\n  -https-insecure\n        Long form of the -k flag\n  -init code\n        grol code to run before the script (for instance to set some arguments)\n  -jitter\n        set to true to de-synchronize parallel clients' by 10%\n  -json path\n        JSON output to provided file path or '-' for stdout (empty = no json output,\nunless -a is used)\n  -k    Do not verify certs in HTTPS/TLS/gRPC connections\n  -keepalive\n        Keep connection alive (only for fast HTTP/1.1) (default true)\n  -key Path\n        Path to the key file matching the -cert\n  -labels string\n        Additional config data/labels to add to the resulting JSON, defaults to target\nURL and hostname\n  -log-errors\n        Log HTTP non-2xx/418 status codes as they occur (default true)\n  -logger-file-line\n        Filename and line numbers emitted in JSON logs, use -logger-file-line=false to\ndisable (default true)\n  -logger-force-color\n        Force color output even if stderr isn't a terminal\n  -logger-goroutine\n        GoroutineID emitted in JSON/color logs, use -logger-goroutine=false to disable\n(default true)\n  -logger-json\n        Log in JSON format, use -logger-json=false to disable (default true)\n  -logger-no-color\n        Prevent colorized output even if stderr is a terminal\n  -logger-timestamp\n        Timestamps emitted in JSON logs, use -logger-timestamp=false to disable (default\ntrue)\n  -loglevel level\n        log level, one of [Debug Verbose Info Warning Error Critical Fatal] (default Info)\n  -max-echo-delay value\n        Maximum sleep time for delay= echo server parameter. dynamic flag. (default 1.5s)\n  -maxpayloadsizekb Kbytes\n        MaxPayloadSize is the maximum size of payload to be generated by the EchoHandler\nsize= argument. In Kbytes. (default 256)\n  -mtls\n        Require client certificate signed by -cacert for client connections\n  -multi-mirror-origin\n        Mirror the request URL to the target for multi proxies (-M) (default true)\n  -multi-serial-mode\n        Multi server (-M) requests one at a time instead of parallel mode\n  -n int\n        Run for exactly this number of calls instead of duration. Default (0) is to use\nduration (-t). Default is 1 when used as gRPC ping count.\n  -nc-dont-stop-on-eof\n        in netcat (nc) mode, don't abort as soon as remote side closes\n  -no-reresolve\n        Keep the initial DNS resolution and don't re-resolve when making new connections\n(because of error or reuse limit reached)\n  -nocatchup\n        set to exact fixed qps and prevent fortio from trying to catchup when the target\nfails to keep up temporarily\n  -offset duration\n        Offset of the histogram data\n  -p string\n        List of pXX to calculate (default \"50,75,90,99,99.9\")\n  -payload string\n        Payload string to send along\n  -payload-file path\n        File path to be use as payload (POST for HTTP), replaces -payload when set.\n  -payload-size int\n        Additional random payload size, replaces -payload when set \u003e 0, must be smaller\nthan -maxpayloadsizekb. Setting this switches HTTP to POST.\n  -ping\n        gRPC load test: use ping instead of health\n  -pprof\n        Enable pprof HTTP endpoint in the Web UI handler server\n  -profile file\n        write .cpu and .mem profiles to file\n  -proxy-all-headers\n        Determines if only tracing or all headers (and cookies) are copied from request\non the fetch2 ui/server endpoint (default true)\n  -qps float\n        Queries Per Seconds or 0 for no wait/max qps (default 8)\n  -quiet\n        Quiet mode, sets loglevel to Error (quietly) to reduces the output\n  -r float\n        Resolution of the histogram lowest buckets in seconds (default 0.001)\n  -redirect-port port\n        Redirect all incoming traffic to https:// URL (need ingress to work properly).\nCan be in the form of host:port, ip:port, port or \"disabled\" to disable the feature.\n(default \"8081\")\n  -resolve IP\n        Resolve host name to this IP\n  -resolve-ip-type type\n        Resolve type: ip4 for ipv4, ip6 for ipv6 only, use ip for both (default ip4)\n  -runid int\n        Optional RunID to add to JSON result and auto save filename, to match server mode\n  -s int\n        Number of streams per gRPC connection (default 1)\n  -sequential-warmup\n        http(s) runner warmup done sequentially instead of parallel. When set, restores\npre 1.21 behavior\n  -server-idle-timeout value\n        Default IdleTimeout for servers (default 30s)\n  -static-dir path\n        Deprecated/unused path.\n  -stdclient\n        Use the slower net/http standard client (slower but supports h2/h2c)\n  -stream\n        Stream payload from stdin (only for fortio curl mode)\n  -sync URL\n        index.tsv or s3/gcs bucket XML URL to fetch at startup for server modes.\n  -sync-interval duration\n        Refresh the URL every given interval (default, no refresh)\n  -t duration\n        How long to run the test or 0 to run until ^C (default 5s)\n  -tcp-port port\n        tcp-echo server port. Can be in the form of host:port, ip:port, port or\n/unix/domain/path or \"disabled\". (default \"8078\")\n  -timeout duration\n        Connection and read timeout value (for HTTP) (default 3s)\n  -udp-async\n        if true, udp echo server will use separate go routine to reply\n  -udp-port port\n        udp-echo server port. Can be in the form of host:port, ip:port, port or\n\"disabled\". (default \"8078\")\n  -udp-timeout duration\n        Udp timeout (default 750ms)\n  -ui-path URI\n        HTTP server URI for UI, empty turns off that part (more secure) (default\n\"/fortio/\")\n  -uniform\n        set to true to de-synchronize parallel clients' requests uniformly\n  -unix-socket path\n        Unix domain socket path to use for physical connection\n  -user user:password\n        User credentials for basic authentication (for HTTP). Input data format should be\nuser:password\n\u003c!-- USAGE_END --\u003e\n\u003c/pre\u003e\n\u003c/details\u003e\n\nSee also the FAQ entry about [fortio flags for best results](https://github.com/fortio/fortio/wiki/FAQ#i-want-to-get-the-best-results-what-flags-should-i-pass).\n\n## Server URLs and features\n\nFortio `server` has the following feature for the HTTP listening on 8080 (all paths and ports are configurable through flags above):\n\n* A simple echo server which will echo back posted data (for any path not mentioned below).\n\n  For instance `curl -d abcdef http://localhost:8080/` returns `abcdef` back. It supports the following optional query argument parameters:\n\n| Parameter | Usage, example |\n|-----------|----------------|\n| delay     | duration to delay the response by. Can be a single value or a comma separated list of probabilities, e.g, `delay=150us:10,2ms:5,0.5s:1` for 10% of chance of a 150 us delay, 5% of a 2ms delay and 1% of a 1/2 second delay |\n| status    | HTTP status to return instead of 200. Can be a single value or a comma separated list of probabilities, e.g, `status=404:10,503:5,429:1` for 10% of chance of a 404 status, 5% of a 503 status and 1% of a 429 status |\n| size      | size of the payload to reply instead of echoing input. Also works as probabilities list. `size=1024:10,512:5` 10% of response will be 1k and 5% will be 512 bytes payload and the REST defaults to echoing back. |\n| close     | close the socket after answering e.g, `close=true` to close after all requests or `close=5.3` to close after approximately 5.3% of requests|\n| header    | header(s) to add to the reply e.g., `\u0026header=Foo:Bar\u0026header=X:Y` |\n| gzip      | If `Accept-Encoding: gzip` is passed in headers by the caller/client; and `gzip=true` is in the query args, all response will be gzipped; or if `gzip=42.7` is passed, approximately 42.7% will|\n\n`delay`, `close` and `header` query arguments are also supported for the `debug` endpoint which echoes back the request (gzip is always done if `Accept-Encoding: gzip` is present, status is always 200, and the payload is the echo back debug information).\n\nYou can set a default value for all these by passing `-echo-server-default-params` to the server command line, for instance:\n`fortio server -echo-server-default-params=\"delay=0.5s:50,1s:40\u0026status=418\"` will make the server respond with HTTP 418 and a delay of either 0.5s half of the time, 1s 40% and no delay in 10% of the calls; unless any `?` query args is passed by the client. Note that the quotes (\u0026quot;) are for the shell to escape the ampersand (\u0026amp;) but should not be put in a YAML nor the dynamic flag URL for instance.\n\n* `/debug` will echo back the request in plain text for human debugging.\n\n* `/fortio/` A UI to\n  * Run/Trigger tests and graph the results.\n  * A UI to browse saved results and single graph or multi graph them (comparative graph of min, avg, median, p75, p99, p99.9 and max).\n  * Proxy/fetch other URLs.\n  * `/fortio/data/index.tsv` a tab separated value file conforming to Google cloud storage [URL list data transfer format](https://cloud.google.com/storage/transfer/create-url-list) so you can export/backup local results to the cloud.\n  * Download/sync peer to peer JSON results files from other Fortio servers (using their `index.tsv` URLs).\n  * Download/sync from an Amazon S3 or Google Cloud compatible bucket listings [XML URLs](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html).\n\n* API to trigger and cancel runs from the running server (like the form UI, but more directly and with `async=on` option)\n  * `/fortio/rest/run` starts a run; the arguments are either from the command line or from POSTed JSON; `jsonPath` can be provided to look for in a subset of the JSON object, for instance `jsonPath=metadata` allows using the flagger webhook metadata for fortio run parameters (see [Remote Triggered load test section below](#remote-triggered-load-test-server-mode-rest-api)).\n  * `/fortio/rest/stop` stops all current run or by run ID (passing `runid=` query argument).\n  * `/fortio/rest/status` lists the current runs (or the options of a single one if `runid` is passed).\n\n* DNS API for troubleshooting latency based records / view of the DNS where fortio server is running. `/fortio/rest/dns?name=x` resolves all the IPs for `x`.\n\nThe `report` mode is a read-only subset of the above directly on `/`.\n\nThere is also the gRPC health and ping servers, as well as the HTTP-\u003eHTTPS redirector.\n\n## Example use and output\n\nNote that recent versions of fortio, when run on the console, have colorized output (and JSON when ran in server environment). What's below is plain text from older versions.\n\n### Start the internal servers\n\n```Shell\n$ fortio server \u0026\nFortio X.Y.Z tcp-echo server listening on tcp [::]:8078\nFortio X.Y.Z udp-echo server listening on udp [::]:8078\nFortio X.Y.Z grpc 'ping' server listening on tcp [::]:8079\nFortio X.Y.Z https redirector server listening on tcp [::]:8081\nFortio X.Y.Z http-echo server listening on tcp [::]:8080\nData directory is /Users/ldemailly/dev/fortio\nREST API on /fortio/rest/run, /fortio/rest/status, /fortio/rest/stop, /fortio/rest/dns\nDebug endpoint on /debug, Additional Echo on /debug/echo/, Flags on /fortio/flags, and Metrics on /debug/metrics\n\t UI started - visit:\n\t\thttp://localhost:8080/fortio/\n\t (or any host/ip reachable on this server)\nI fortio_main.go:285\u003e Note: not using dynamic flag watching (use -config to set watch directory)\nI fortio_main.go:293\u003e All fortio X.Y.Z  goM.m.p arm64 darwin servers started!\n```\n\n### Sample of the graphing UI\n\nWith the 2 histograms - total and errors overlaid:\n\n![Graphical result](https://user-images.githubusercontent.com/3664595/165001248-33e180d5-fd6b-4389-b73e-79a21e76d5b0.png)\n\n\n### Change the port / binding address\n\nBy default, Fortio's web/echo servers listen on port 8080 on all interfaces.\nUse the `-http-port` flag to change this behavior:\n\n```Shell\n$ fortio server -http-port 10.10.10.10:8088\nUI starting - visit:\nhttp://10.10.10.10:8088/fortio/\nhttps redirector running on :8081\nFortio X.Y.Z grpc ping server listening on port :8079\nFortio X.Y.Z echo server listening on port 10.10.10.10:8088\n```\n\n### Unix domain sockets\n\nYou can use Unix domain socket for any server/client:\n\n```Shell\n$ fortio server --http-port /tmp/fortio-uds-http \u0026\nFortio X.Y.Z grpc 'ping' server listening on [::]:8079\nFortio X.Y.Z https redirector server listening on [::]:8081\nFortio X.Y.Z echo server listening on /tmp/fortio-uds-http\nUI started - visit:\nfortio curl -unix-socket=/tmp/fortio-uds-http http://localhost/fortio/\n14:58:45 I fortio_main.go:217\u003e All fortio X.Y.Z unknown goM.m.p servers started!\n$ fortio curl -unix-socket=/tmp/fortio-uds-http http://foo.bar/debug\n15:00:48 I http_client.go:428\u003e Using unix domain socket /tmp/fortio-uds-http instead of foo.bar http\nHTTP/1.1 200 OK\nContent-Type: text/plain; charset=UTF-8\nDate: Wed, 08 Aug 2018 22:00:48 GMT\nContent-Length: 231\n\nΦορτίο version X.Y.Z unknown goM.m.p echo debug server up for 2m3.4s on ldemailly-macbookpro - request from\n\nGET /debug HTTP/1.1\n\nheaders:\n\nHost: foo.bar\nUser-Agent: fortio.org/fortio-X.Y.Z\n\nbody:\n```\n\n### TCP\nStart the echo-server alone and run a load (use `tcp://` prefix for the load test to be for tcp echo server):\n```Shell\n$ fortio tcp-echo \u0026\nFortio X.Y.Z tcp-echo TCP server listening on [::]:8078\n19:45:30 I fortio_main.go:238\u003e All fortio X.Y.Z release goM.m.p servers started!\n$ fortio load -qps -1 -n 100000 tcp://localhost:8078\nFortio X.Y.Z running at -1 queries per second, 16-\u003e16 procs, for 100000 calls: tcp://localhost:8078\n20:01:31 I tcprunner.go:218\u003e Starting tcp test for tcp://localhost:8078 with 4 threads at -1.0 qps\nStarting at max qps with 4 thread(s) [gomax 16] for exactly 100000 calls (25000 per thread + 0)\n20:01:32 I periodic.go:558\u003e T003 ended after 1.240585427s : 25000 calls. qps=20151.77629520873\n20:01:32 I periodic.go:558\u003e T002 ended after 1.241141084s : 25000 calls. qps=20142.75437521493\n20:01:32 I periodic.go:558\u003e T001 ended after 1.242066385s : 25000 calls. qps=20127.7486468648\n20:01:32 I periodic.go:558\u003e T000 ended after 1.24227731s : 25000 calls. qps=20124.331176909283\nEnded after 1.242312567s : 100000 calls. qps=80495\nAggregated Function Time : count 100000 avg 4.9404876e-05 +/- 1.145e-05 min 2.7697e-05 max 0.000887051 sum 4.94048763\n# range, mid point, percentile, count\n\u003e= 2.7697e-05 \u003c= 0.000887051 , 0.000457374 , 100.00, 100000\n# target 50% 0.00045737\n# target 75% 0.00067221\n# target 90% 0.000801115\n# target 99% 0.000878457\n# target 99.9% 0.000886192\nSockets used: 4 (for perfect no error run, would be 4)\nTotal Bytes sent: 2400000, received: 2400000\ntcp OK : 100000 (100.0 %)\nAll done 100000 calls (plus 0 warmup) 0.049 ms avg, 80495.0 qps\n```\n\n### UDP\nStart the udp-echo server alone and run a load (use `udp://` prefix for the load test to be for udp echo server):\n```\n$ fortio udp-echo \u0026\nFortio X.Y.Z udp-echo UDP server listening on [::]:8078\n21:54:52 I fortio_main.go:273\u003e Note: not using dynamic flag watching (use -config to set watch directory)\n21:54:52 I fortio_main.go:281\u003e All fortio X.Y.Z release goM.m.p servers started!\n$ fortio load -qps -1 -n 100000 udp://localhost:8078/\nFortio X.Y.Z running at -1 queries per second, 16-\u003e16 procs, for 100000 calls: udp://localhost:8078/\n21:56:48 I udprunner.go:222\u003e Starting udp test for udp://localhost:8078/ with 4 threads at -1.0 qps\nStarting at max qps with 4 thread(s) [gomax 16] for exactly 100000 calls (25000 per thread + 0)\n21:56:49 I periodic.go:558\u003e T003 ended after 969.635695ms : 25000 calls. qps=25782.879208051432\n21:56:49 I periodic.go:558\u003e T000 ended after 969.906228ms : 25000 calls. qps=25775.687667818544\n21:56:49 I periodic.go:558\u003e T002 ended after 970.543935ms : 25000 calls. qps=25758.751457243405\n21:56:49 I periodic.go:558\u003e T001 ended after 970.737665ms : 25000 calls. qps=25753.610786287973\nEnded after 970.755702ms : 100000 calls. qps=1.0301e+05\nAggregated Function Time : count 100000 avg 3.8532238e-05 +/- 1.7e-05 min 2.0053e-05 max 0.000881827 sum 3.85322376\n# range, mid point, percentile, count\n\u003e= 2.0053e-05 \u003c= 0.000881827 , 0.00045094 , 100.00, 100000\n# target 50% 0.000450936\n# target 75% 0.000666381\n# target 90% 0.000795649\n# target 99% 0.000873209\n# target 99.9% 0.000880965\nSockets used: 4 (for perfect no error run, would be 4)\nTotal Bytes sent: 2400000, received: 2400000\nudp OK : 100000 (100.0 %)\nAll done 100000 calls (plus 0 warmup) 0.039 ms avg, 103012.5 qps\n```\n\n### gRPC\n\n#### Simple gRPC ping\n\n```Shell\n$ fortio grpcping -n 5 localhost\n22:36:55 I pingsrv.go:150\u003e Ping RTT 212000 (avg of 259000, 217000, 160000 ns) clock skew -10500\n22:36:55 I pingsrv.go:150\u003e Ping RTT 134333 (avg of 170000, 124000, 109000 ns) clock skew 5000\n22:36:55 I pingsrv.go:150\u003e Ping RTT 112000 (avg of 111000, 122000, 103000 ns) clock skew 5000\n22:36:55 I pingsrv.go:150\u003e Ping RTT 157000 (avg of 136000, 158000, 177000 ns) clock skew 6000\n22:36:55 I pingsrv.go:150\u003e Ping RTT 108333 (avg of 118000, 106000, 101000 ns) clock skew 1000\nClock skew histogram usec : count 5 avg 1.3 +/- 6.145 min -10.5 max 6 sum 6.5\n# range, mid point, percentile, count\n\u003e= -10.5 \u003c= -10 , -10.25 , 20.00, 1\n\u003e 0 \u003c= 2 , 1 , 40.00, 1\n\u003e 4 \u003c= 6 , 5 , 100.00, 3\n# target 50% 4.33333\nRTT histogram usec : count 15 avg 144.73333 +/- 44.48 min 101 max 259 sum 2171\n# range, mid point, percentile, count\n\u003e= 101 \u003c= 110 , 105.5 , 26.67, 4\n\u003e 110 \u003c= 120 , 115 , 40.00, 2\n\u003e 120 \u003c= 140 , 130 , 60.00, 3\n\u003e 140 \u003c= 160 , 150 , 73.33, 2\n\u003e 160 \u003c= 180 , 170 , 86.67, 2\n\u003e 200 \u003c= 250 , 225 , 93.33, 1\n\u003e 250 \u003c= 259 , 254.5 , 100.00, 1\n# target 50% 130\n```\n\n#### Change the target port for gRPC\n\nThe value of `-grpc-port` (default 8079) is used when specifying a hostname or an IP address in `grpcping`. Add `:port` to the `grpcping` destination to\nchange this behavior:\n\n```Shell\n$ fortio grpcping 10.10.10.100:8078 # Connects to gRPC server 10.10.10.100 listening on port 8078\n02:29:27 I pingsrv.go:116\u003e Ping RTT 305334 (avg of 342970, 293515, 279517 ns) clock skew -2137\nClock skew histogram usec : count 1 avg -2.137 +/- 0 min -2.137 max -2.137 sum -2.137\n# range, mid point, percentile, count\n\u003e= -4 \u003c -2 , -3 , 100.00, 1\n# target 50% -2.137\nRTT histogram usec : count 3 avg 305.334 +/- 27.22 min 279.517 max 342.97 sum 916.002\n# range, mid point, percentile, count\n\u003e= 250 \u003c 300 , 275 , 66.67, 2\n\u003e= 300 \u003c 350 , 325 , 100.00, 1\n# target 50% 294.879\n```\n\n#### `grpcping` using TLS\n\nNote that since 1.40 the same applies to the main HTTP server port, it will listen on TLS if `-cert` and `-key` flags are provided.\n\nFor testing use `make certs` to generate self signed test certificates.\n\n* First, start Fortio server with the `-cert` and `-key` flags:\n\n`/path/to/fortio/server.crt` and `/path/to/fortio/server.key` are paths to the TLS certificate and key that\nyou must provide:\n\n```Shell\n$ fortio server -cert /path/to/fortio/server.crt -key /path/to/fortio/server.key\nUI starting - visit:\nhttp://localhost:8080/fortio/\nhttps redirector running on :8081\nFortio X.Y.Z grpc ping server listening on port :8079\nFortio X.Y.Z echo server listening on port localhost:8080\nUsing server certificate /path/to/fortio/server.crt to construct TLS credentials\nUsing server key /path/to/fortio/server.key to construct TLS credentials\n```\n\n* Next, use `grpcping` with the `-cacert` flag:\n\n`/path/to/fortio/ca.crt` is the path to the CA certificate\nthat issued the server certificate for `localhost`. In our example, the server certificate is\n`/path/to/fortio/server.crt`:\n\n```Shell\n$ fortio grpcping -cacert /path/to/fortio/ca.crt localhost\nUsing server certificate /path/to/fortio/ca.crt to construct TLS credentials\n16:00:10 I pingsrv.go:129\u003e Ping RTT 501452 (avg of 595441, 537088, 371828 ns) clock skew 31094\nClock skew histogram usec : count 1 avg 31.094 +/- 0 min 31.094 max 31.094 sum 31.094\n# range, mid point, percentile, count\n\u003e= 31.094 \u003c= 31.094 , 31.094 , 100.00, 1\n# target 50% 31.094\nRTT histogram usec : count 3 avg 501.45233 +/- 94.7 min 371.828 max 595.441 sum 1504.357\n# range, mid point, percentile, count\n\u003e= 371.828 \u003c= 400 , 385.914 , 33.33, 1\n\u003e 500 \u003c= 595.441 , 547.721 , 100.00, 2\n# target 50% 523.86\n```\n\n#### gRPC to standard HTTPS service\n\n`grpcping` can connect to a non-fortio TLS server by prefacing the destination with `https://`:\n\n```Shell\n$ fortio grpcping https://grpc.fortio.org\n13:48:20 I grpcrunner.go:276\u003e stripping https scheme. grpc destination: grpc.fortio.org. grpc port: 443\n13:48:26 I pingsrv.go:152\u003e Ping RTT 63101562 (avg of 63577000, 63192688, 62535000 ns) clock skew 32021375\nClock skew histogram usec : count 1 avg 32021.375 +/- 0 min 32021.375 max 32021.375 sum 32021.375\n# range, mid point, percentile, count\n\u003e= 32021.4 \u003c= 32021.4 , 32021.4 , 100.00, 1\n# target 50% 32021.4\nRTT histogram usec : count 3 avg 63101.563 +/- 430.2 min 62535 max 63577 sum 189304.688\n# range, mid point, percentile, count\n\u003e= 62535 \u003c= 63577 , 63056 , 100.00, 3\n# target 50% 62795.5\n```\n\n### Simple load test\n\nLoad (low default qps/threading) test:\n\n```Shell\n$ fortio load http://www.google.com\nFortio X.Y.Z running at 8 queries per second, 8-\u003e8 procs, for 5s: http://www.google.com\n19:10:33 I httprunner.go:84\u003e Starting http test for http://www.google.com with 4 threads at 8.0 qps\nStarting at 8 qps with 4 thread(s) [gomax 8] for 5s : 10 calls each (total 40)\n19:10:39 I periodic.go:314\u003e T002 ended after 5.056753279s : 10 calls. qps=1.9775534712220633\n19:10:39 I periodic.go:314\u003e T001 ended after 5.058085991s : 10 calls. qps=1.9770324224999916\n19:10:39 I periodic.go:314\u003e T000 ended after 5.058796046s : 10 calls. qps=1.9767549252963101\n19:10:39 I periodic.go:314\u003e T003 ended after 5.059557593s : 10 calls. qps=1.9764573910247019\nEnded after 5.059691387s : 40 calls. qps=7.9056\nSleep times : count 36 avg 0.49175757 +/- 0.007217 min 0.463508712 max 0.502087879 sum 17.7032725\nAggregated Function Time : count 40 avg 0.060587641 +/- 0.006564 min 0.052549016 max 0.089893269 sum 2.42350566\n# range, mid point, percentile, count\n\u003e= 0.052549 \u003c 0.06 , 0.0562745 , 47.50, 19\n\u003e= 0.06 \u003c 0.07 , 0.065 , 92.50, 18\n\u003e= 0.07 \u003c 0.08 , 0.075 , 97.50, 2\n\u003e= 0.08 \u003c= 0.0898933 , 0.0849466 , 100.00, 1\n# target 50% 0.0605556\n# target 75% 0.0661111\n# target 99% 0.085936\n# target 99.9% 0.0894975\nCode 200 : 40\nResponse Header Sizes : count 40 avg 690.475 +/- 15.77 min 592 max 693 sum 27619\nResponse Body/Total Sizes : count 40 avg 12565.2 +/- 301.9 min 12319 max 13665 sum 502608\nAll done 40 calls (plus 4 warmup) 60.588 ms avg, 7.9 qps\n```\n\n\n### Remote triggered load test (server mode REST API)\n\nNew since 1.18 the server has a `fortio/rest/run` endpoint similar to what the form UI submit in `fortio/` to start a run.\n  - plus `async` query arg or JSON value `\"on\"` will make the run asynchronous (returns just the runid of the run instead of waiting for the result);\n  - plus read all the run configuration from either query args or JSONPath POSTed info;\n  - compatible with [flagger](https://github.com/fluxcd/flagger) and other webhooks;\n  - New in 1.22: use `headers` JSON array to send headers (or multiple `\u0026H=` query args).\n\nExamples:\n\n```shell\n$ curl -v -d '{\"metadata\": {\"url\":\"localhost:8080\", \"c\":\"1\", \"n\":\"1\", \"async\":\"on\", \"save\":\"on\"}}' \\\n     \"localhost:8080/fortio/rest/run?jsonPath=.metadata\"\n{\"started\": 3}\n```\nmakes a 1 connection 1 query run for localhost:8080 URL asynchronously and saves results\n\nor minimally:\n```shell\ncurl -s -d '{\"url\":\"localhost:8080\"}' \"localhost:8080/fortio/rest/run\" | jq\n```\n\nMore complete example:\n\nWith sample.json (all values must be strings, even the numbers):\n```json\n{\n    \"metadata\": {\n        \"url\": \"localhost:8080\",\n        \"payload\": \"foo\",\n        \"qps\": \"40\",\n        \"c\": \"2\",\n        \"t\": \"0.1s\",\n        \"headers\": [\n            \"Foo:Bar\",\n            \"X-Blah: Something else\"\n        ],\n        \"save\": \"on\"\n    }\n}\n```\nYou can run:\n```shell\n$ fortio curl -stdclient -payload-file sample.json \"http://localhost:8080/fortio/rest/run?jsonPath=.metadata\" \u003e result.json\n```\nwhich makes requests like this:\n```\nPOST / HTTP/1.1\nHost: localhost:8080\nContent-Length: 3\nContent-Type: application/octet-stream\nFoo: Bar\nX-Blah: Something else\nX-On-Behalf-Of: [::1]:62629\n\nfoo\n```\n\nand you get in result.json:\n```json\n{\n  \"RunType\": \"HTTP\",\n  \"Labels\": \"\",\n  \"StartTime\": \"2022-03-19T15:34:23.279389-07:00\",\n  \"RequestedQPS\": \"40\",\n  \"RequestedDuration\": \"100ms\",\n  \"ActualQPS\": 38.44836361217263,\n  \"ActualDuration\": 104035637,\n  \"NumThreads\": 2,\n  \"Version\": \"X.Y.Z\",\n  \"DurationHistogram\": {\n    \"Count\": 4,\n    \"Min\": 0.00027292,\n    \"Max\": 0.000930407,\n    \"Sum\": 0.002332047,\n    \"Avg\": 0.00058301175,\n    \"StdDev\": 0.00028491034912527755,\n    \"Data\": [\n      {\n        \"Start\": 0.00027292,\n        \"End\": 0.000930407,\n        \"Percent\": 100,\n        \"Count\": 4\n      }\n    ],\n    \"Percentiles\": [\n      {\n        \"Percentile\": 50,\n        \"Value\": 0.0004920823333333334\n      },\n      {\n        \"Percentile\": 75,\n        \"Value\": 0.0007112446666666667\n      },\n      {\n        \"Percentile\": 90,\n        \"Value\": 0.0008427420666666666\n      },\n      {\n        \"Percentile\": 99,\n        \"Value\": 0.0009216405066666668\n      },\n      {\n        \"Percentile\": 99.9,\n        \"Value\": 0.0009295303506666667\n      }\n    ]\n  },\n  \"Exactly\": 0,\n  \"Jitter\": false,\n  \"Uniform\": false,\n  \"RunID\": 7,\n  \"AccessLoggerInfo\": \"\",\n  \"RetCodes\": {\n    \"200\": 4\n  },\n  \"URL\": \"http://localhost:8080\",\n  \"NumConnections\": 1,\n  \"Compression\": false,\n  \"DisableFastClient\": false,\n  \"HTTP10\": false,\n  \"DisableKeepAlive\": false,\n  \"AllowHalfClose\": false,\n  \"Insecure\": false,\n  \"FollowRedirects\": false,\n  \"CACert\": \"\",\n  \"Cert\": \"\",\n  \"Key\": \"\",\n  \"Resolve\": \"\",\n  \"HTTPReqTimeOut\": 3000000000,\n  \"UserCredentials\": \"\",\n  \"ContentType\": \"\",\n  \"Payload\": \"Zm9v\",\n  \"UnixDomainSocket\": \"\",\n  \"LogErrors\": false,\n  \"ID\": 0,\n  \"SequentialWarmup\": false,\n  \"Sizes\": {\n    \"Count\": 4,\n    \"Min\": 118,\n    \"Max\": 118,\n    \"Sum\": 472,\n    \"Avg\": 118,\n    \"StdDev\": 0,\n    \"Data\": [\n      {\n        \"Start\": 118,\n        \"End\": 118,\n        \"Percent\": 100,\n        \"Count\": 4\n      }\n    ],\n    \"Percentiles\": null\n  },\n  \"HeaderSizes\": {\n    \"Count\": 4,\n    \"Min\": 115,\n    \"Max\": 115,\n    \"Sum\": 460,\n    \"Avg\": 115,\n    \"StdDev\": 0,\n    \"Data\": [\n      {\n        \"Start\": 115,\n        \"End\": 115,\n        \"Percent\": 100,\n        \"Count\": 4\n      }\n    ],\n    \"Percentiles\": null\n  },\n  \"SocketCount\": 2,\n  \"AbortOn\": 0\n}\n```\n\n- There is also the `fortio/rest/stop` endpoint to stop a run by its id or all runs if not specified.\n\n### DNS REST API example\n\n```bash\n$ curl -s localhost:8080/fortio/rest/dns?name=debug.fortio.org | jq\n```\nReturns\n```json\n{\n  \"Name\": \"debug.fortio.org\",\n  \"IPv4\": [\n    \"18.222.136.83\",\n    \"192.9.142.5\",\n    \"192.9.227.83\"\n  ],\n  \"IPv6\": [\n    \"2600:1f16:9c6:b400:282c:a766:6cab:4e82\",\n    \"2603:c024:c00a:d144:7cd0:4951:7106:96b8\",\n    \"2603:c024:c00a:d144:6663:5896:7efb:fbf3\"\n  ]\n}\n```\n\n### GRPC load test\n\nUses `-s` to use multiple (h2/gRPC) streams per connection (`-c`), request to hit the fortio ping gRPC endpoint with a delay in replies of 0.25s and an extra payload for 10 bytes and auto save the JSON result:\n\n```bash\n$ fortio load -a -grpc -ping -grpc-ping-delay 0.25s -payload \"01234567890\" -c 2 -s 4 https://fortio-stage.istio.io\nFortio X.Y.Z running at 8 queries per second, 8-\u003e8 procs, for 5s: https://fortio-stage.istio.io\n16:32:56 I grpcrunner.go:139\u003e Starting GRPC Ping Delay=250ms PayloadLength=11 test for https://fortio-stage.istio.io with 4*2 threads at 8.0 qps\n16:32:56 I grpcrunner.go:261\u003e stripping https scheme. grpc destination: fortio-stage.istio.io. grpc port: 443\n16:32:57 I grpcrunner.go:261\u003e stripping https scheme. grpc destination: fortio-stage.istio.io. grpc port: 443\nStarting at 8 qps with 8 thread(s) [gomax 8] for 5s : 5 calls each (total 40)\n16:33:04 I periodic.go:533\u003e T005 ended after 5.283227589s : 5 calls. qps=0.9463911814835126\n[...]\nEnded after 5.28514474s : 40 calls. qps=7.5684\nSleep times : count 32 avg 0.97034752 +/- 0.002338 min 0.967323561 max 0.974838789 sum 31.0511206\nAggregated Function Time : count 40 avg 0.27731944 +/- 0.001606 min 0.2741372 max 0.280604967 sum 11.0927778\n# range, mid point, percentile, count\n\u003e= 0.274137 \u003c= 0.280605 , 0.277371 , 100.00, 40\n# target 50% 0.277288\n# target 75% 0.278947\n# target 90% 0.279942\n# target 99% 0.280539\n# target 99.9% 0.280598\nPing SERVING : 40\nAll done 40 calls (plus 2 warmup) 277.319 ms avg, 7.6 qps\nSuccessfully wrote 1210 bytes of Json data to 2018-04-03-163258_fortio_stage_istio_io_ldemailly_macbookpro.json\n```\n\nAnd the JSON saved is\n\u003cdetails\u003e\n\u003cpre\u003e\n{\n  \"RunType\": \"GRPC Ping Delay=250ms PayloadLength=11\",\n  \"Labels\": \"fortio-stage.istio.io , ldemailly-macbookpro\",\n  \"StartTime\": \"2018-04-03T16:32:58.895472681-07:00\",\n  \"RequestedQPS\": \"8\",\n  \"RequestedDuration\": \"5s\",\n  \"ActualQPS\": 7.568383075162479,\n  \"ActualDuration\": 5285144740,\n  \"NumThreads\": 8,\n  \"Version\": \"0.9.0\",\n  \"DurationHistogram\": {\n    \"Count\": 40,\n    \"Min\": 0.2741372,\n    \"Max\": 0.280604967,\n    \"Sum\": 11.092777797,\n    \"Avg\": 0.277319444925,\n    \"StdDev\": 0.0016060870789948905,\n    \"Data\": [\n      {\n        \"Start\": 0.2741372,\n        \"End\": 0.280604967,\n        \"Percent\": 100,\n        \"Count\": 40\n      }\n    ],\n    \"Percentiles\": [\n      {\n        \"Percentile\": 50,\n        \"Value\": 0.2772881634102564\n      },\n      {\n        \"Percentile\": 75,\n        \"Value\": 0.27894656520512817\n      },\n      {\n        \"Percentile\": 90,\n        \"Value\": 0.2799416062820513\n      },\n      {\n        \"Percentile\": 99,\n        \"Value\": 0.28053863092820513\n      },\n      {\n        \"Percentile\": 99.9,\n        \"Value\": 0.2805983333928205\n      }\n    ]\n  },\n  \"Exactly\": 0,\n  \"RetCodes\": {\n    \"1\": 40\n  },\n  \"Destination\": \"https://fortio-stage.istio.io\",\n  \"Streams\": 4,\n  \"Ping\": true\n}\n\u003c/pre\u003e\u003c/details\u003e\n\n* Load test using gRPC and TLS security. First, start Fortio server with the `-cert` and `-key` flags:\n\n```Shell\nfortio server -cert /etc/ssl/certs/server.crt -key /etc/ssl/certs/server.key\n```\n\nNext, run the `load` command with the `-cacert` flag:\n\n```Shell\nfortio load -cacert /etc/ssl/certs/ca.crt -grpc localhost:8079\n```\n\n### cURL like (single request) mode\n\n```Shell\n$ fortio load -curl -H Foo:Bar http://localhost:8080/debug\n14:26:26 I http.go:133\u003e Setting regular extra header Foo: Bar\nHTTP/1.1 200 OK\nContent-Type: text/plain; charset=UTF-8\nDate: Mon, 08 Jan 2018 22:26:26 GMT\nContent-Length: 230\n\nΦορτίο version X.Y.Z echo debug server up for 39s on ldemailly-macbookpro - request from [::1]:65055\n\nGET /debug HTTP/1.1\n\nheaders:\n\nHost: localhost:8080\nUser-Agent: fortio.org/fortio-X.Y.Z\nFoo: Bar\n\nbody:\n\n```\n\nNote: if you do not want the default fortio User-Agent to be sent pass `-H user-agent:`. If you want to send a present yet empty User-Agent: header, pass `-H \"user-agent: \"` (i.e., only whitespace sends empty one, empty value doesn't send any).\n\n### Report only UI\n\nIf you have JSON files saved from running the full UI or downloaded, using the `-sync` option, from an Amazon or Google Cloud storage bucket or from a peer fortio server (to synchronize from a peer fortio, use `http://`_peer_`:8080/data/index.tsv` as the sync URL). You can then serve just the reports:\n\n```Shell\n$ fortio report -sync-interval 15m -sync \"https://storage.googleapis.com/fortio-data?prefix=fortio.istio.io/\"\nBrowse only UI starting - visit:\nhttp://localhost:8080/\nhttps redirector running on :8081\n```\n\n### Using the HTTP fan out / multi proxy feature\n\nExample listen on 1 extra port and every request sent to that 1 port is forward to 2:\n```Shell\n# in one window or \u0026\n$ fortio server -M \"5554 http://localhost:8080 http://localhost:8080\"\n[...]\nFortio X.Y.Z Multi on 5554 server listening on [::]:5554\n10:09:56 I http_forwarder.go:152\u003e Multi-server on [::]:5554 running with \u0026{Targets:[{Destination:http://localhost:8080 MirrorOrigin:true} {Destination:http://localhost:8080 MirrorOrigin:true}] Name:Multi on [::]:5554 client:0xc0001ccc00}\n```\nCall the debug endpoint on both:\n```Shell\n# in new window\n$ fortio curl -payload \"a test\" http://localhost:5554/debug\nHTTP/1.1 200 OK\nDate: Wed, 07 Oct 2020 17:11:06 GMT\nContent-Length: 684\nContent-Type: text/plain; charset=utf-8\n\nΦορτίο version X.Y.Z unknown goM.m.p echo debug server up for 1m9.3s on C02C77BHMD6R - request from [::1]:51020\n\nPOST /debug HTTP/1.1\n\nheaders:\n\nHost: localhost:8080\nAccept-Encoding: gzip\nContent-Type: application/octet-stream\nUser-Agent: fortio.org/fortio-X.Y.Z\nX-Fortio-Multi-Id: 1\nX-On-Behalf-Of: [::1]:51019\n\nbody:\n\na test\nΦορτίο version X.Y.Z unknown goM.m.p echo debug server up for 1m9.3s on C02C77BHMD6R - request from [::1]:51020\n\nPOST /debug HTTP/1.1\n\nheaders:\n\nHost: localhost:8080\nAccept-Encoding: gzip\nContent-Type: application/octet-stream\nUser-Agent: fortio.org/fortio-X.Y.Z\nX-Fortio-Multi-Id: 2\nX-On-Behalf-Of: [::1]:51019\n\nbody:\n\na test\n```\nThere are 2 flags to further control the behavior of the multi-server proxies:\n\n- pass `-mirrorOriginFlag=false` to not mirror all headers and request type to targets.\n- pass `-multi-serial-mode` to stream request response serially instead of fetching in parallel and writing combined data after completion.\n\nAlso remember you can pass multiple `-M`.\n\n### Using the TCP proxy server(s) feature\n\nExample: open 2 additional listening ports and forward all requests received on 8888 and 8889 (IPv6) to 8080 (regular HTTP server)\n\n```Shell\n$ fortio server -P \"8888 [::1]:8080\" -P \"[::1]:8889 [::1]:8080\"\nFortio X.Y.Z grpc 'ping' server listening on [::]:8079\nFortio X.Y.Z https redirector server listening on [::]:8081\nFortio X.Y.Z echo server listening on [::]:8080\nData directory is /home/dl\nUI started - visit:\nhttp://localhost:8080/fortio/\n(or any host/ip reachable on this server)\nFortio X.Y.Z proxy for [::1]:8080 server listening on [::]:8888\nFortio X.Y.Z proxy for [::1]:8080 server listening on [::1]:8889\n```\n\n## Implementation details\n\nFortio is written in the [Go](https://golang.org) language and includes a scalable semi log histogram in [stats.go](stats/stats.go) and a periodic runner engine in [periodic.go](periodic/periodic.go) with specializations for [HTTP](fhttp/httprunner.go) and [gRPC](fgrpc/grpcrunner.go).\nThe [fhttp/](fhttp/) package includes a very high performance specialized HTTP 1.1 client.\nYou may find fortio's [logger](log/logger.go) useful as well.\n\nYou can run the histogram code standalone as a command line in [histogram/](histogram/), a basic echo HTTP server in [echosrv/](echosrv/), or both the HTTP echo and gRPC ping server through `fortio server`, the fortio command line interface lives in this top level directory [main.go](main.go)\n\nThere is also [fcurl/](fcurl/) which is the `fortio curl` part of the code (if you need a light HTTP client without gRPC or server side).\nA matching tiny (2Mb compressed) Docker image is [fortio/fortio.fcurl](https://hub.docker.com/r/fortio/fortio.fcurl/tags/).\n\n## More examples\n\nYou can get the data on the console, for instance, with 5k qps: (includes envoy and mixer in the calls)\n\u003cdetails\u003e\u003cpre\u003e\n$ time fortio load -qps 5000 -t 60s -c 8 -r 0.0001 -H \"Host: perf-cluster\" http://benchmark-2:9090/echo\n2017/07/09 02:31:05 Will be setting special Host header to perf-cluster\nFortio running at 5000 queries per second for 1m0s: http://benchmark-2:9090/echo\nStarting at 5000 qps with 8 thread(s) [gomax 4] for 1m0s : 37500 calls each (total 300000)\n2017/07/09 02:32:05 T004 ended after 1m0.000907812s : 37500 calls. qps=624.9905437680746\n2017/07/09 02:32:05 T000 ended after 1m0.000922222s : 37500 calls. qps=624.9903936684861\n2017/07/09 02:32:05 T005 ended after 1m0.00094454s : 37500 calls. qps=624.9901611965524\n2017/07/09 02:32:05 T006 ended after 1m0.000944816s : 37500 calls. qps=624.9901583216429\n2017/07/09 02:32:05 T001 ended after 1m0.00102094s : 37500 calls. qps=624.9893653892883\n2017/07/09 02:32:05 T007 ended after 1m0.001096292s : 37500 calls. qps=624.9885805003184\n2017/07/09 02:32:05 T003 ended after 1m0.001045342s : 37500 calls. qps=624.9891112105419\n2017/07/09 02:32:05 T002 ended after 1m0.001044416s : 37500 calls. qps=624.9891208560392\nEnded after 1m0.00112695s : 300000 calls. qps=4999.9\nAggregated Sleep Time : count 299992 avg 8.8889218e-05 +/- 0.002326 min -0.03490402 max 0.001006041 sum 26.6660543\n# range, mid point, percentile, count\n\u003c 0 , 0 , 8.58, 25726\n\u003e= 0 \u003c 0.001 , 0.0005 , 100.00, 274265\n\u003e= 0.001 \u003c 0.002 , 0.0015 , 100.00, 1\n# target 50% 0.000453102\nWARNING 8.58% of sleep were falling behind\nAggregated Function Time : count 300000 avg 0.00094608764 +/- 0.0007901 min 0.000510522 max 0.029267604 sum 283.826292\n# range, mid point, percentile, count\n\u003e= 0.0005 \u003c 0.0006 , 0.00055 , 0.15, 456\n\u003e= 0.0006 \u003c 0.0007 , 0.00065 , 3.25, 9295\n\u003e= 0.0007 \u003c 0.0008 , 0.00075 , 24.23, 62926\n\u003e= 0.0008 \u003c 0.0009 , 0.00085 , 62.73, 115519\n\u003e= 0.0009 \u003c 0.001 , 0.00095 , 85.68, 68854\n\u003e= 0.001 \u003c 0.0011 , 0.00105 , 93.11, 22293\n\u003e= 0.0011 \u003c 0.0012 , 0.00115 , 95.38, 6792\n\u003e= 0.0012 \u003c 0.0014 , 0.0013 , 97.18, 5404\n\u003e= 0.0014 \u003c 0.0016 , 0.0015 , 97.94, 2275\n\u003e= 0.0016 \u003c 0.0018 , 0.0017 , 98.34, 1198\n\u003e= 0.0018 \u003c 0.002 , 0.0019 , 98.60, 775\n\u003e= 0.002 \u003c 0.0025 , 0.00225 , 98.98, 1161\n\u003e= 0.0025 \u003c 0.003 , 0.00275 , 99.21, 671\n\u003e= 0.003 \u003c 0.0035 , 0.00325 , 99.36, 449\n\u003e= 0.0035 \u003c 0.004 , 0.00375 , 99.47, 351\n\u003e= 0.004 \u003c 0.0045 , 0.00425 , 99.57, 290\n\u003e= 0.0045 \u003c 0.005 , 0.00475 , 99.66, 280\n\u003e= 0.005 \u003c 0.006 , 0.0055 , 99.79, 380\n\u003e= 0.006 \u003c 0.007 , 0.0065 , 99.82, 92\n\u003e= 0.007 \u003c 0.008 , 0.0075 , 99.83, 15\n\u003e= 0.008 \u003c 0.009 , 0.0085 , 99.83, 5\n\u003e= 0.009 \u003c 0.01 , 0.0095 , 99.83, 1\n\u003e= 0.01 \u003c 0.012 , 0.011 , 99.83, 8\n\u003e= 0.012 \u003c 0.014 , 0.013 , 99.84, 35\n\u003e= 0.014 \u003c 0.016 , 0.015 , 99.92, 231\n\u003e= 0.016 \u003c 0.018 , 0.017 , 99.94, 65\n\u003e= 0.018 \u003c 0.02 , 0.019 , 99.95, 26\n\u003e= 0.02 \u003c 0.025 , 0.0225 , 100.00, 139\n\u003e= 0.025 \u003c 0.03 , 0.0275 , 100.00, 14\n# target 50% 0.000866935\n# target 75% 0.000953452\n# target 99% 0.00253875\n# target 99.9% 0.0155152\nCode 200 : 300000\nResponse Body Sizes : count 300000 avg 0 +/- 0 min 0 max 0 sum 0\n\u003c/pre\u003e\u003c/details\u003e\n\nOr you can get the data in [JSON format](https://github.com/fortio/fortio/wiki/Sample-JSON-output) (using `-json result.json`).\n\n### Web/Graphical UI\n\nOr graphically (through the [http://localhost:8080/fortio/](http://localhost:8080/fortio/) web UI):\n\nSimple form/UI:\n\nSample requests with responses delayed by 250us and 0.5% of 503 and 1.5% of 429 simulated HTTP errors:\n\n![Web UI form screenshot](https://user-images.githubusercontent.com/3664595/41430618-53d911d4-6fc5-11e8-8e35-d4f5fea4426a.png)\n\nRun result:\n\n![Graphical result](https://user-images.githubusercontent.com/3664595/41430735-bb95eb3a-6fc5-11e8-8174-be4a6251058f.png)\n\n```Shell\nCode 200 : 2929 (97.6 %)\nCode 429 : 56 (1.9 %)\nCode 503 : 15 (0.5 %)\n```\n\nThere are live examples on [https://demo.fortio.org](https://demo.fortio.org/)\n\n## Contributing\n\nContributions whether through issues, documentation, bug fixes, or new features\nare most welcome !\n\nPlease also see [Contributing to Istio](https://github.com/istio/community/blob/master/CONTRIBUTING.md#contributing-to-istio)\nand [Getting started contributing to Fortio](https://github.com/fortio/fortio/wiki/FAQ#how-do-i-get-started-contributing-to-fortio) in the FAQ.\n\nIf you are not using the binary releases, please do `make pull` to pull/update to the latest of the current branch.\n\nAnd make sure to go strict format (`go get mvdan.cc/gofumpt` and `gofumpt -w *.go`) and run those commands successfully before sending your PRs:\n\n```Shell\nmake test\nmake lint\nmake release-test\n```\n\nWhen modifying JavaScript, check with [standard](https://github.com/standard/standard):\n\n```Shell\nstandard --fix ui/static/js/fortio_chart.js\n```\n\nNew features and bug fixes should include a test.\n\n## See also\n\nOur wiki and the [Fortio FAQ](https://github.com/fortio/fortio/wiki/FAQ) (including for instance differences between `fortio` and `wrk` or `httpbin`).\n\nFortio is also used by, among others, [Meshery](https://docs.meshery.io/extensibility/load-generators).\n\n## Disclaimer\n\nThis is not an officially supported Google product.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffortio%2Ffortio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffortio%2Ffortio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffortio%2Ffortio/lists"}