{"id":35313350,"url":"https://github.com/theztd/troll","last_synced_at":"2026-01-22T11:02:28.923Z","repository":{"id":156613368,"uuid":"543791619","full_name":"theztd/troll","owner":"theztd","description":"Troll is small go webserver usefull for testing. ","archived":false,"fork":false,"pushed_at":"2025-12-30T16:13:07.000Z","size":4120,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-03T10:08:07.043Z","etag":null,"topics":["cicd","devops","golang","nomad"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/theztd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-09-30T21:11:01.000Z","updated_at":"2025-12-30T21:11:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"b71245b1-c9ea-463f-b88f-864c99eed23b","html_url":"https://github.com/theztd/troll","commit_stats":null,"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"purl":"pkg:github/theztd/troll","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theztd%2Ftroll","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theztd%2Ftroll/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theztd%2Ftroll/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theztd%2Ftroll/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theztd","download_url":"https://codeload.github.com/theztd/troll/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theztd%2Ftroll/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28661882,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cicd","devops","golang","nomad"],"created_at":"2025-12-30T18:05:17.084Z","updated_at":"2026-01-22T11:02:28.913Z","avatar_url":"https://github.com/theztd.png","language":"Go","readme":"# Troll\n\n  [![Troll Release](https://github.com/theztd/troll/actions/workflows/release_golang.yml/badge.svg)](https://github.com/theztd/troll/actions/workflows/release_golang.yml)\n  [![Helm Release](https://github.com/theztd/troll/actions/workflows/release_helm.yml/badge.svg)](https://github.com/theztd/troll/actions/workflows/release_helm.yml)\n  [![Docker image Release](https://github.com/theztd/troll/actions/workflows/release_docker.yml/badge.svg)](https://github.com/theztd/troll/actions/workflows/release_docker.yml)\n\n\nTroll is a very simple webserver returning defined response with configurable delay and a few more features.\n\n**INFO**\n\n * Report Issues: **https://github.com/theztd/troll/issues/new**\n * Http listen port: **8080** (changable via **http.ADDR** env)\n * TCP proxy listen port: **9999** (changable via **tcp.ADDR** env)\n * Info endpoint URL: **GET /_healthz/info**\n * Readines URL: **GET /_healthz/ready**\n * Livenes URL: **GET /_healthz/alive**\n * Metrics URL: **GET /_healthz/metrics**\n * Headers debug URL: **GET /v1/headers**\n\n**Quick Links**\n\n * [DEMO application (Try it!!!)](https://troll.check-this.link)\n\n\n\n## Purpouse\n * Testing API endpoint (configurable via YAML).\n * Responding with random predefined delay.\n * Serve static files from FS.\n * Ready to use API backend for FE app prototyping.\n * Demo CI/CD with GOlang application\n\n## Features:\n * Define minimal wait interval for response\n * Define document root for serving static content\n * Aplication name could be defined\n * Listen port could be set via ENV\n * Print received json data to log and respond in json\n * Log with basic request_id\n * 404 page dumping request to log\n * Generate 503 randomly (simulate errors)\n * Fill RAM with each request (simulate mem leaks)\n * Generate CPU load on requests with ?heavy=cpu param\n * Ready delay for testing canary releases and readyness check\n * Tcp Proxy with random delay and random error generator\n * Routes could be defined via YAML config and can do SQL query, redis query and shell commands\n\n## 🧱 Build\n\n```bash\nenv GOOS=target-OS GOARCH=target-architecture go build -o troll cmd/troll/main.go\n```\n\n## 🚀 RUN and Operate\n\n\n### 🛠️ Config\n```bash\ntroll -help\n  -name string\n        Define custom application name. (NAME) (default \"troll\")\n  -log_level string\n        Define LOG_LEVEL (default \"info\")\n  -ready_delay int\n        Simulate long application init [sec]. (READY_DELAY) (default 5)\n  -config string\n        Configure api endpoint. (CONFIG_FILE)\n\n  -http.addr string\n        Define address and port where the application listen. (HTTP_ADDR) (default \":8080\")\n  -http.error_rate int\n        Returns 503. Set 1 - 10, where 10 = 100% error rate. (HTTP_ERROR_RATE)\n  -http.fill_cpu int\n        Generate stress on CPU with each request. It also works as a delay for request [milisecodns]. (HEAVY_CPU)\n  -http.fill_ram int\n        Fill ram with each request [bytes]. (HEAVY_RAM)\n  -http.req_delay int\n        Minimal delay before response on request [miliseconds]. (REQUEST_DELAY)\n  -http.root string\n        Define document root for serving files. (DOC_ROOT) (default \"./public\")\n\n  -tcp.addr string\n        Define address and port where the tcp proxy listens. (TCP_ADDR) (default \":9999\")\n  -tcp.dest_addr string\n        Define address and port where to send tcp proxy requests. (TCP_DEST_ADDR) (default \"127.0.0.1:8080\")\n  -tcp.error_rate int\n        Simulate random error rate.  Set 1 - 10, where 10 = 100% error rate. (TCP_ERROR_RATE)\n  -tcp.max_delay int\n        Simulate long response max delay [miliseconds]. (TCP_MAX_DELAY) (default 5000)\n  -tcp.min_delay int\n        Simulate long response minimal delay [miliseconds]. (TCP_MIN_DELAY) (default 100)\n\n```\n\n### 📦 Helm install\n\n```bash\nhelm repo add troll https://theztd.github.io/troll/\nhelm install troll-test  troll/troll\n```\n\n\n### 🤖 Custom API definition\n\nBy editing config_api.yaml you can change /v2 endpoints and his responses (return code including).\n\nThe default structure is:\n```yaml\n---\nname: Inventory\ndescription: Our company inventory includes employees and equipment\nversion: 2022-09-09\ngame:\n  # Enable and configure GAME UI\n  route: /game\n  templatePath: ./__game_template.html\n  backends:\n  - http://service-a\n  - http://service-b\n  - http://service-c\nendpoints:\n- path: /machines\n  kind: basic\n  method: GET\n  code: 200\n  response: \"We have plenty of machines in our factory as you can see as follows...\"\n- path: /machines/add\n  kind: basic\n  method: POST\n  code: 200\n  response: \"New machine has been added\"\n```\n\n### 🌿 Dependencies\n\n | Name | Url | Notes |\n |---|---|---|\n | FS:  | ./config.yaml | Not required. |\n \n\n### 📈 Monitoring\n\n#### Health check example\n ```json\n# Content-Type: \"application/health+json\"\n{\n      \"notes\":\"Troll is ...\",\n      \"status\":\"pass\",\n      \"version\":\"1.0.0\"\n}\n```\n\n#### Metrics example\n```prometheus\n# HELP gin_request_duration the time server took to handle the request.\n# TYPE gin_request_duration histogram\ngin_request_duration_bucket{uri=\"\",le=\"0.1\"} 300\ngin_request_duration_bucket{uri=\"\",le=\"0.3\"} 300\ngin_request_duration_bucket{uri=\"\",le=\"1.2\"} 300\ngin_request_duration_bucket{uri=\"\",le=\"5\"} 300\ngin_request_duration_bucket{uri=\"\",le=\"10\"} 300\ngin_request_duration_bucket{uri=\"\",le=\"+Inf\"} 300\ngin_request_duration_sum{uri=\"\"} 0.41419708799999966\ngin_request_duration_count{uri=\"\"} 300\ngin_request_duration_bucket{uri=\"/v1/:item/*id\",le=\"0.1\"} 61\ngin_request_duration_bucket{uri=\"/v1/:item/*id\",le=\"0.3\"} 184\ngin_request_duration_bucket{uri=\"/v1/:item/*id\",le=\"1.2\"} 300\ngin_request_duration_bucket{uri=\"/v1/:item/*id\",le=\"5\"} 300\ngin_request_duration_bucket{uri=\"/v1/:item/*id\",le=\"10\"} 300\ngin_request_duration_bucket{uri=\"/v1/:item/*id\",le=\"+Inf\"} 300\ngin_request_duration_sum{uri=\"/v1/:item/*id\"} 72.53894113400001\ngin_request_duration_count{uri=\"/v1/:item/*id\"} 300\ngin_request_duration_bucket{uri=\"/v1/status\",le=\"0.1\"} 100\ngin_request_duration_bucket{uri=\"/v1/status\",le=\"0.3\"} 100\ngin_request_duration_bucket{uri=\"/v1/status\",le=\"1.2\"} 100\ngin_request_duration_bucket{uri=\"/v1/status\",le=\"5\"} 100\ngin_request_duration_bucket{uri=\"/v1/status\",le=\"10\"} 100\ngin_request_duration_bucket{uri=\"/v1/status\",le=\"+Inf\"} 100\ngin_request_duration_sum{uri=\"/v1/status\"} 0.003233080999999999\ngin_request_duration_count{uri=\"/v1/status\"} 100\n# HELP gin_request_total all the server received request num.\n# TYPE gin_request_total counter\ngin_request_total 700\n# HELP gin_request_uv_total all the server received ip num.\n# TYPE gin_request_uv_total counter\ngin_request_uv_total 1\n# HELP gin_response_body_total the server send response body size, unit byte\n# TYPE gin_response_body_total counter\ngin_response_body_total 322135\n# HELP gin_uri_request_total all the server received request num with every uri.\n# TYPE gin_uri_request_total counter\ngin_uri_request_total{code=\"200\",method=\"GET\",uri=\"/v1/:item/*id\"} 300\ngin_uri_request_total{code=\"200\",method=\"GET\",uri=\"/v1/status\"} 100\ngin_uri_request_total{code=\"404\",method=\"GET\",uri=\"\"} 300\n# HELP go_sync_mutex_wait_total_seconds_total Approximate cumulative time goroutines have spent blocked on a sync.Mutex or sync.RWMutex. This metric is useful for identifying global changes in lock contention. Collect a mutex or block profile using the runtime/pprof package for more detailed contention data.\n# TYPE go_sync_mutex_wait_total_seconds_total counter\ngo_sync_mutex_wait_total_seconds_total 0.000130336\n# HELP go_threads Number of OS threads created.\n# TYPE go_threads gauge\ngo_threads 10\n# HELP promhttp_metric_handler_requests_in_flight Current number of scrapes being served.\n# TYPE promhttp_metric_handler_requests_in_flight gauge\npromhttp_metric_handler_requests_in_flight 1\n# HELP promhttp_metric_handler_requests_total Total number of scrapes by HTTP status code.\n# TYPE promhttp_metric_handler_requests_total counter\npromhttp_metric_handler_requests_total{code=\"200\"} 2\npromhttp_metric_handler_requests_total{code=\"500\"} 0\npromhttp_metric_handler_requests_total{code=\"503\"} 0\n```\n\n### 🔎 Logs\n\nChange log level by env LOG_LEVEL\n\n**Format**\n```log\n2025/12/30 16:23:03 INFO: Loading configuration from .env file.\nStarting application, give me 1 sec.. DONE\n\n2025/12/30 16:23:04 INFO TcpProxy: Listening on :9999 and serving content from 127.0.0.1:8080\n2025/12/30 16:23:04 WARN: Config file is not defined, but continue with defaults..\n2025/12/30 16:23:04 INFO: Initialize default routes 🏗️  ...\n\nAvailable routes:\n  ▶︎ GET    /\n  ▶︎ GET    /_healthz/info\n  ▶︎ GET    /_healthz/alive\n  ▶︎ GET    /_healthz/ready\n  ▶︎ GET    /_healthz/metrics\n  ▶︎ GET    /v1/_healthz/metrics\n  ▶︎ GET    /v1/headers\n  ▶︎ GET    /v1/:item/*id\n  ▶︎ GET    /ws\n  ▶︎ GET    /websocket\n  ▶︎ GET    /public/*filepath\n  ▶︎ GET    /static/*filepath\n  ▶︎ HEAD   /public/*filepath\n  ▶︎ HEAD   /static/*filepath\n  ▶︎ POST   /v1/:item/*id\n\n\n2025/12/30 16:23:04 INFO: Running in mode: \"info\" and listening on address :8080. 😈 Enjoy!\n2025/12/30 16:23:14 INFO [AuditLog]: GET   /_metrics      404   From: 127.0.0.1 UA: vm_promscrape\n2025/12/30 16:23:24 INFO [AuditLog]: GET   /_metrics      404   From: 127.0.0.1 UA: vm_promscrape\n\n```\n\n### Backup\n\n* There is nothing to backup\n\n\n## Contribute\n\nThank you for your interest in this project! Everyone is welcome to help.\n\n### ✅ Commit rules\nWe use a simple commit style: type(scope): short message\n\nHere are the types you can use:\n\n| Type     | Description                        | Example Commit Message                         |\n|----------|------------------------------------|------------------------------------------------|\n| **feat** | New feature                        | feat(api): add /v2/status route              |\n| **fix**  | Small fix or bug fix               | fix(handler): check for nil input            |\n| **ref**  | Refactor (clean up or improve)     | ref(server): simplify router setup           |\n| **doc**  | Documentation                      | doc(readme): add build instructions          |\n| **ci**   | CI/CD or pipeline changes          | ci(k8s): append canary release ingress       |\n| **test** | Testing or temporary experiments   | test(api): log request body for debugging    |\n\n### 🎭 Helm release\n\n * Do changes in ./Helm directory\n * Don't forget to increase version in Chart.yaml file\n * Push your changes\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheztd%2Ftroll","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftheztd%2Ftroll","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheztd%2Ftroll/lists"}