diff --git a/src/api/docs/content/index.html b/src/api/docs/content/index.html
index 9e92d18c..cdcc5973 100644
--- a/src/api/docs/content/index.html
+++ b/src/api/docs/content/index.html
@@ -22,11 +22,12 @@
theme = "dark"
allow-try = "true"
sort-endpoints-by = "path"
- default-schema-tab = 'example'
+ default-schema-tab = "model"
schema-style = "tree"
render-style = "view"
primary-color = "#2d87e2"
- header-color = "#2d87e2">
+ header-color = "#2d87e2"
+ schema-expand-level= "2">
Pi-hole API Documentation
diff --git a/src/api/docs/content/specs/ftl.yaml b/src/api/docs/content/specs/ftl.yaml
index ffe2d446..f68d3f2c 100644
--- a/src/api/docs/content/specs/ftl.yaml
+++ b/src/api/docs/content/specs/ftl.yaml
@@ -277,33 +277,51 @@ components:
ftl:
type: object
properties:
- gravity:
- type: integer
- description: Number of collected exact domains on lists
- example: 67906
- groups:
- type: integer
- description: Number of groups
- example: 6
- lists:
- type: integer
- description: Number of lists
- example: 1
- clients:
- type: integer
- description: Number of configured clients
- example: 5
- domains:
+ database:
type: object
properties:
- allowed:
+ gravity:
type: integer
- description: Number of allowed domains
+ description: Number of collected exact domains on lists
+ example: 67906
+ groups:
+ type: integer
+ description: Number of groups
+ example: 6
+ lists:
+ type: integer
+ description: Number of lists
+ example: 1
+ clients:
+ type: integer
+ description: Number of configured clients
+ example: 5
+ domains:
+ type: object
+ properties:
+ allowed:
+ type: integer
+ description: Number of allowed domains
+ example: 10
+ denied:
+ type: integer
+ description: Number of denied domains
+ example: 3
+ privacy_level:
+ type: integer
+ description: Currently used privacy level
+ example: 0
+ clients:
+ type: object
+ properties:
+ total:
+ type: integer
+ description: Number of clients FTL has seen in its lfetime
example: 10
- denied:
+ active:
type: integer
- description: Number of denied domains
- example: 3
+ description: Number of clients actively using FTL
+ example: 8
database:
type: object
properties:
diff --git a/src/api/docs/content/specs/main.yaml b/src/api/docs/content/specs/main.yaml
index 92c6cc86..8fdabe3c 100644
--- a/src/api/docs/content/specs/main.yaml
+++ b/src/api/docs/content/specs/main.yaml
@@ -20,24 +20,15 @@ paths:
/auth:
$ref: 'auth.yaml#/components/paths/auth'
+ /stats/summary:
+ $ref: 'stats.yaml#/components/paths/summary'
+
/dns/blocking:
$ref: 'dns.yaml#/components/paths/blocking'
/dns/cache:
$ref: 'dns.yaml#/components/paths/cache'
- /ftl/client:
- $ref: 'ftl.yaml#/components/paths/client'
-
- /ftl/logs/dns:
- $ref: 'ftl.yaml#/components/paths/logs/dns'
-
- /ftl/sysinfo:
- $ref: 'ftl.yaml#/components/paths/sysinfo'
-
- /ftl/dbinfo:
- $ref: 'ftl.yaml#/components/paths/dbinfo'
-
/database/info:
$ref: 'database.yaml#/components/paths/info'
@@ -65,5 +56,17 @@ paths:
/lists:
$ref: 'lists.yaml#/components/paths/direct'
+ /ftl/client:
+ $ref: 'ftl.yaml#/components/paths/client'
+
+ /ftl/logs/dns:
+ $ref: 'ftl.yaml#/components/paths/logs/dns'
+
+ /ftl/sysinfo:
+ $ref: 'ftl.yaml#/components/paths/sysinfo'
+
+ /ftl/dbinfo:
+ $ref: 'ftl.yaml#/components/paths/dbinfo'
+
/version:
$ref: 'version.yaml#/components/paths/version'
diff --git a/src/api/docs/content/specs/stats.yaml b/src/api/docs/content/specs/stats.yaml
new file mode 100644
index 00000000..1290dec3
--- /dev/null
+++ b/src/api/docs/content/specs/stats.yaml
@@ -0,0 +1,142 @@
+openapi: 3.0.2
+components:
+ paths:
+ summary:
+ get:
+ summary: Get overview of Pi-hole activity
+ description: |
+ Request various query, system ,and FTL properties
+ responses:
+ '200':
+ description: OK
+ content:
+ application/json:
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/queries'
+ - $ref: 'ftl.yaml#/components/schemas/system'
+ - $ref: 'ftl.yaml#/components/schemas/ftl'
+
+ schemas:
+ queries:
+ type: object
+ properties:
+ queries:
+ type: object
+ properties:
+ blocked:
+ type: integer
+ description: Number of blocked queries
+ example: 3465
+ percent_blocked:
+ type: float
+ description: Percent of blocked queries
+ example: 34.5
+ unique_domains:
+ type: integer
+ description: Number of unique domains FTL knows
+ example: 445
+ forwarded:
+ type: integer
+ description: Number of queries that have been forwarded upstream
+ example: 4574
+ cached:
+ type: integer
+ description: Number of queries replied to from cache or local configuration
+ example: 9765
+ types:
+ type: object
+ description: Number of individual queries
+ properties:
+ A:
+ type: integer
+ description: Type A queries
+ example: 3643
+ AAAA:
+ type: integer
+ description: Type AAAA queries
+ example: 123
+ ANY:
+ type: integer
+ description: Type ANY queries
+ example: 3423
+ SRV:
+ type: integer
+ description: Type SRV queries
+ example: 345
+ SOA:
+ type: integer
+ description: Type SOA queries
+ example: 7567
+ PTR:
+ type: integer
+ description: Type PTR queries
+ example: 456
+ TXT:
+ type: integer
+ description: Type TXT queries
+ example: 85
+ NAPTR:
+ type: integer
+ description: Type NAPTR queries
+ example: 346
+ MX:
+ type: integer
+ description: Type MX queries
+ example: 457
+ DS:
+ type: integer
+ description: Type DS queries
+ example: 456
+ RRSIG:
+ type: integer
+ description: Type RRSIG queries
+ example: 345
+ DNSKEY:
+ type: integer
+ description: Type DNSKEY queries
+ example: 55
+ NS:
+ type: integer
+ description: Type NS queries
+ example: 868
+ SVCB:
+ type: integer
+ description: Type SVCB queries
+ example: 645
+ HTTPS:
+ type: integer
+ description: Type HTTPS queries
+ example: 4
+ OTHER:
+ type: integer
+ description: Queries of remaining types
+ example: 845
+ sum:
+ type: integer
+ description: Total number of queries
+ example: 7497
+ replies:
+ type: object
+ description: Number of individual replies
+ properties:
+ NODATA:
+ type: integer
+ description: NODATA responses
+ example: 14
+ NXDOMAIN:
+ type: integer
+ description: NXDOMAIN responses
+ example: 45
+ CNAME:
+ type: integer
+ description: CNAME responses
+ example: 76
+ IP:
+ type: integer
+ description: IP responses
+ example: 85
+ text:
+ type: integer
+ description: text responses
+ example: 16
diff --git a/src/api/ftl.c b/src/api/ftl.c
index b29750d4..b84eac28 100644
--- a/src/api/ftl.c
+++ b/src/api/ftl.c
@@ -28,6 +28,8 @@
#include "../database/query-table.h"
// getgrgid()
#include
+// config struct
+#include "../config.h"
int api_ftl_client(struct ftl_conn *api)
{
@@ -387,14 +389,37 @@ int get_system_obj(struct ftl_conn *api, cJSON *system)
int get_ftl_obj(struct ftl_conn *api, cJSON *ftl)
{
- JSON_OBJ_ADD_NUMBER(ftl, "gravity", counters->database.gravity);
- JSON_OBJ_ADD_NUMBER(ftl, "groups", counters->database.groups);
- JSON_OBJ_ADD_NUMBER(ftl, "lists", counters->database.lists);
- JSON_OBJ_ADD_NUMBER(ftl, "clients", counters->database.clients);
+ cJSON *database = JSON_NEW_OBJ();
+ JSON_OBJ_ADD_NUMBER(database, "gravity", counters->database.gravity);
+ JSON_OBJ_ADD_NUMBER(database, "groups", counters->database.groups);
+ JSON_OBJ_ADD_NUMBER(database, "lists", counters->database.lists);
+ JSON_OBJ_ADD_NUMBER(database, "clients", counters->database.clients);
+
cJSON *domains = JSON_NEW_OBJ();
JSON_OBJ_ADD_NUMBER(domains, "allowed", counters->database.domains.allowed);
JSON_OBJ_ADD_NUMBER(domains, "denied", counters->database.domains.denied);
- JSON_OBJ_ADD_ITEM(ftl, "domains", domains);
+ JSON_OBJ_ADD_ITEM(database, "domains", domains);
+ JSON_OBJ_ADD_ITEM(ftl, "database", database);
+
+ JSON_OBJ_ADD_NUMBER(ftl, "privacy_level", config.privacylevel);
+
+ // unique_clients: count only clients that have been active within the most recent 24 hours
+ int activeclients = 0;
+ for(int clientID=0; clientID < counters->clients; clientID++)
+ {
+ // Get client pointer
+ const clientsData* client = getClient(clientID, true);
+ if(client == NULL)
+ continue;
+
+ if(client->count > 0)
+ activeclients++;
+ }
+
+ cJSON *clients = JSON_NEW_OBJ();
+ JSON_OBJ_ADD_NUMBER(clients, "total", counters->clients);
+ JSON_OBJ_ADD_NUMBER(clients, "active", activeclients);
+ JSON_OBJ_ADD_ITEM(ftl, "clients", clients);
return 0;
}
diff --git a/src/api/stats.c b/src/api/stats.c
index 45f36aa5..43cfc577 100644
--- a/src/api/stats.c
+++ b/src/api/stats.c
@@ -69,52 +69,36 @@ int api_stats_summary(struct ftl_conn *api)
if(total > 0)
percent_blocked = 1e2f*blocked/total;
- // unique_clients: count only clients that have been active within the most recent 24 hours
- int activeclients = 0;
- for(int clientID=0; clientID < counters->clients; clientID++)
+ cJSON *queries = JSON_NEW_OBJ();
+ JSON_OBJ_ADD_NUMBER(queries, "blocked", counters->blocked);
+ JSON_OBJ_ADD_NUMBER(queries, "percent_blocked", percent_blocked);
+ JSON_OBJ_ADD_NUMBER(queries, "unique_domains", counters->domains);
+ JSON_OBJ_ADD_NUMBER(queries, "forwarded", counters->forwarded);
+ JSON_OBJ_ADD_NUMBER(queries, "cached", counters->cached);
+
+ cJSON *types = JSON_NEW_OBJ();
+ for(unsigned int i = TYPE_A; i < TYPE_MAX; i++)
{
- // Get client pointer
- const clientsData* client = getClient(clientID, true);
- if(client == NULL)
+ // We add the collective OTHER type at the end
+ if(i == TYPE_OTHER)
continue;
-
- if(client->count > 0)
- activeclients++;
+ JSON_OBJ_ADD_NUMBER(types, querytypes[i], counters->querytype[i]);
}
+ JSON_OBJ_ADD_NUMBER(types, "OTHER", counters->querytype[TYPE_OTHER]);
+ JSON_OBJ_ADD_ITEM(queries, "types", types);
- // Send response
- cJSON *json = JSON_NEW_OBJ();
- const bool blocking = get_blockingstatus();
- JSON_OBJ_ADD_BOOL(json, "blocking", blocking); // same reply type as in /api/dns/status
- JSON_OBJ_ADD_NUMBER(json, "blocked_queries", counters->blocked);
- JSON_OBJ_ADD_NUMBER(json, "percent_blocked", percent_blocked);
- JSON_OBJ_ADD_NUMBER(json, "unique_domains", counters->domains);
- JSON_OBJ_ADD_NUMBER(json, "forwarded_queries", counters->forwarded);
- JSON_OBJ_ADD_NUMBER(json, "cached_queries", counters->cached);
- JSON_OBJ_ADD_NUMBER(json, "privacy_level", config.privacylevel);
- JSON_OBJ_ADD_NUMBER(json, "total_clients", counters->clients);
- JSON_OBJ_ADD_NUMBER(json, "active_clients", activeclients);
-
- cJSON *total_queries = JSON_NEW_OBJ();
- JSON_OBJ_ADD_NUMBER(total_queries, "A", counters->querytype[TYPE_A]);
- JSON_OBJ_ADD_NUMBER(total_queries, "AAAA", counters->querytype[TYPE_AAAA]);
- JSON_OBJ_ADD_NUMBER(total_queries, "ANY", counters->querytype[TYPE_ANY]);
- JSON_OBJ_ADD_NUMBER(total_queries, "SRV", counters->querytype[TYPE_SRV]);
- JSON_OBJ_ADD_NUMBER(total_queries, "SOA", counters->querytype[TYPE_SOA]);
- JSON_OBJ_ADD_NUMBER(total_queries, "PTR", counters->querytype[TYPE_PTR]);
- JSON_OBJ_ADD_NUMBER(total_queries, "TXT", counters->querytype[TYPE_TXT]);
- JSON_OBJ_ADD_NUMBER(total_queries, "NAPTR", counters->querytype[TYPE_NAPTR]);
- JSON_OBJ_ADD_ITEM(json, "total_queries", total_queries);
-
- JSON_OBJ_ADD_NUMBER(json, "sum_queries", counters->queries);
+ JSON_OBJ_ADD_NUMBER(queries, "sum", counters->queries);
- cJSON *reply_types = JSON_NEW_OBJ();
- JSON_OBJ_ADD_NUMBER(reply_types, "NODATA", counters->reply_NODATA);
- JSON_OBJ_ADD_NUMBER(reply_types, "NXDOMAIN", counters->reply_NXDOMAIN);
- JSON_OBJ_ADD_NUMBER(reply_types, "CNAME", counters->reply_CNAME);
- JSON_OBJ_ADD_NUMBER(reply_types, "IP", counters->reply_IP);
- JSON_OBJ_ADD_NUMBER(reply_types, "domain", counters->reply_domain);
- JSON_OBJ_ADD_ITEM(json, "reply_types", reply_types);
+ cJSON *replies = JSON_NEW_OBJ();
+ JSON_OBJ_ADD_NUMBER(replies, "NODATA", counters->reply_NODATA);
+ JSON_OBJ_ADD_NUMBER(replies, "NXDOMAIN", counters->reply_NXDOMAIN);
+ JSON_OBJ_ADD_NUMBER(replies, "CNAME", counters->reply_CNAME);
+ JSON_OBJ_ADD_NUMBER(replies, "IP", counters->reply_IP);
+ JSON_OBJ_ADD_NUMBER(replies, "text", counters->reply_domain);
+ JSON_OBJ_ADD_ITEM(queries, "replies", replies);
+
+ cJSON *json = JSON_NEW_OBJ();
+ JSON_OBJ_ADD_ITEM(json, "queries", queries);
// Get system object
cJSON *system = JSON_NEW_OBJ();