nginx / unit

NGINX Unit - universal web app server - a lightweight and versatile open source server that simplifies the application stack by natively executing application code across eight different programming language runtimes.
https://unit.nginx.org
Apache License 2.0
5.29k stars 325 forks source link

How to get metrics with prometheus? #976

Closed umlumpa closed 9 months ago

umlumpa commented 9 months ago

hello i can get metrics inside of container like this curl -X GET --unix-socket /var/run/control.unit.sock http://localhost/statusbut i cant get it outside of container please help i am using this in kubernetes! before i use https://github.com/hipages/php-fpm_exporter for metrics in php-fpm !

lcrilly commented 9 months ago

You can run a PHP application inside the Unit container to read the /status endpoint and expose the data in Prometheus format.

I hope this helps, please let me know https://gist.github.com/lcrilly/ad516de8378dd8ae5303a942e67d55b5

umlumpa commented 9 months ago

Can you send me some example please? Not fully understand! i have like this conf for my php app! how to add here?

{
  "listeners":{
    "*:80":{
      "pass":"routes"
    }
  },
  "routes":[
    {
      "match":{
        "uri":[
          "!/assets/*",
          "*.php",
          "*.php/*"
        ]
      },
      "action":{
        "pass":"applications/php/direct"
      }
    },
    {
      "action":{
        "share":"/var/www/html/src/frontend/web$uri",
        "fallback":{
          "pass":"applications/php/index"
        }
      }
    }
  ],
  "applications":{
    "php":{
      "type":"php",
      "limits": {
        "timeout": 60,
        "requests": 10000
      },
      "options": {
        "file": "/etc/php.ini",
        "admin": {
          "memory_limit": "1000M",
          "variables_order": "EGPCS"
        },
        "user": {
          "display_errors": "0"
        }
      },
      "processes":{
        "max":30,
        "spare":1,
        "idle_timeout":5
      },
      "targets":{
        "direct":{
          "root":"/var/www/html/src/frontend/web"
        },
        "index":{
          "root":"/var/www/html/src/frontend/web",
          "script":"index.php"
        }
      }
    }
  }
}
lcrilly commented 9 months ago

OK, here's a complete solution for you :)

  1. Copy this PHP application to /var/www/unit/prometheus.php
    
    <?php
    $sock = stream_socket_client("unix://".getenv("control_socket"), $errno, $errst);
    fwrite($sock, "GET /status HTTP/1.0\r\n\r\n");
    $resp = fread($sock, 4096);
    fclose($sock);

list($headers, $body) = explode("\r\n\r\n", $resp, 2); $json = json_decode($body);

$metrics = array(); array_push($metrics, "unit_connections_accepted_total ".$json->connections->accepted); array_push($metrics, "unit_connections_active ".$json->connections->active); array_push($metrics, "unit_connections_idle ".$json->connections->idle); array_push($metrics, "unit_connections_closed_total ".$json->connections->closed); array_push($metrics, "unit_requests_total ".$json->requests->total);

foreach($json->applications as $application => $data) { array_push($metrics, "unitapplication".$application."_processes_running ".$data->processes->running); array_push($metrics, "unitapplication".$application."_processes_starting ".$data->processes->starting); array_push($metrics, "unitapplication".$application."_processes_idle ".$data->processes->idle); array_push($metrics, "unitapplication".$application."_requests_active ".$data->requests->active); }

header("Content-Type: text/plain"); echo join("\n", $metrics)."\n"; ?>


2. Apply this configuration
```json
{
  "listeners": {
    "*:80": {
      "pass": "routes"
    }
  },
  "routes": [
    {
      "match": {
        "uri": "/metrics"
      },
      "action": {
        "pass": "applications/prom"
      }
    },
    {
      "match": {
        "uri": [
          "!/assets/*",
          "*.php",
          "*.php/*"
        ]
      },
      "action": {
        "pass": "applications/php/direct"
      }
    },
    {
      "action": {
        "share": "/var/www/html/src/frontend/web$uri",
        "fallback": {
          "pass": "applications/php/index"
        }
      }
    }
  ],
  "applications": {
    "prom": {
      "type": "php",
      "root": "/var/www/unit",
      "script": "prometheus.php",
      "user": "root",
      "environment": {
        "control_socket": "/var/run/control.unit.sock"
      }
    },
    "php": {
      "type": "php",
      "limits": {
        "timeout": 60,
        "requests": 10000
      },
      "options": {
        "file": "/etc/php.ini",
        "admin": {
          "memory_limit": "1000M",
          "variables_order": "EGPCS"
        },
        "user": {
          "display_errors": "0"
        }
      },
      "processes": {
        "max": 30,
        "spare": 1,
        "idle_timeout": 5
      },
      "targets": {
        "direct": {
          "root": "/var/www/html/src/frontend/web"
        },
        "index": {
          "root": "/var/www/html/src/frontend/web",
          "script": "index.php"
        }
      }
    }
  }
}
  1. Test the Prometheus exporter

    curl http://localhost/metrics
  2. Tell me if it works :)

umlumpa commented 9 months ago

thnx a lot this is works! but problem is in permission of /var/run/control.unit.sock

lcrilly commented 9 months ago

Yes, you need to manage the ownership and permissions of the control socket yourself. The plan is to solve this issue with something like https://github.com/nginx/unit/issues/840 but for now the simplest solution is to run the Prometheus exporter application as root.

umlumpa commented 9 months ago

thnx a lot! appreciate!