From afa28bb62296d30c890a2bd0ecb568b18f1262fc Mon Sep 17 00:00:00 2001 From: MultiMote Date: Fri, 14 Apr 2023 21:55:12 +0300 Subject: [PATCH] First commit --- .gitignore | 4 +++ .gitmodules | 3 +++ CMakeLists.txt | 28 +++++++++++++++++++++ README.md | 20 +++++++++++++++ main.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ mongoose | 1 + 6 files changed, 123 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 main.c create mode 160000 mongoose diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d994124 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.exe +.vscode +/build diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..0c335ab --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "mongoose"] + path = mongoose + url = https://github.com/cesanta/mongoose.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..da8b865 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.0.0) +project(user_idle_exporter VERSION 0.1) + +option(HIDE_CONSOLE "Hides console window" ON) +set(LISTEN_ADDR "0.0.0.0:9183" CACHE STRING "Listen address") + +if(NOT WIN32) +message(FATAL_ERROR "Only Windows supported") +endif() + +set(BUILD_SHARED_LIBS OFF) +set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") + +if(HIDE_CONSOLE) +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mwindows") +endif() + +# strip executable +set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} -s") + +include_directories(mongoose) +add_executable(user_idle_exporter main.c mongoose/mongoose.c) +target_link_libraries(user_idle_exporter ws2_32) +target_compile_definitions(user_idle_exporter PRIVATE + -DUSER_IDLE_EXPORTER_VERSION="${CMAKE_PROJECT_VERSION}" + -DUSER_IDLE_EXPORTER_LISTEN_ADDR="${LISTEN_ADDR}" +) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3a5c956 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# user_idle_exporter + +[Prometheus](https://prometheus.io) Windows user idle time exporter. Must be run as user, not as system account. +Idle time is a number of seconds since last user interaction (keyboard/mouse). + +Example output: + +``` +# HELP user_exporter_build_info User exporter build info +# TYPE user_exporter_build_info gauge +user_idle_exporter_build_info{version="0.1"} 1 +# HELP user_idle_time User idle time +# TYPE user_idle_time gauge +user_idle_seconds 12 +# HELP user_idle_error User idle time retrieval error +# TYPE user_idle_error gauge +user_idle_error 0 +``` + +Default listen address (0.0.0.0) and port (9183) can be only changed in CMakeLists.txt. \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..d11eb4a --- /dev/null +++ b/main.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include "mongoose.h" + +LASTINPUTINFO lii; + +static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) +{ + if (ev == MG_EV_HTTP_MSG) + { + struct mg_http_message *hm = (struct mg_http_message *)ev_data; + + if (mg_http_match_uri(hm, "/")) + { + const char html[] = + "" + "user_exporter" + "" + "

user_exporter

" + "

Metrics

" + "

(version=" USER_IDLE_EXPORTER_VERSION ")

" + "" + ""; + + mg_http_reply(c, 200, "Content-Type: text/html\r\n", html); + } + else if (mg_http_match_uri(hm, "/metrics")) + { + int ret = GetLastInputInfo(&lii); + int seconds = (GetTickCount() - lii.dwTime) / 1000; + + const char text[] = + "# HELP user_exporter_build_info User exporter build info\n" + "# TYPE user_exporter_build_info gauge\n" + "user_idle_exporter_build_info{version=\"" USER_IDLE_EXPORTER_VERSION "\"} 1\n" + "# HELP user_idle_time User idle time\n" + "# TYPE user_idle_time gauge\n" + "user_idle_seconds %d\n" + "# HELP user_idle_error User idle time retrieval error \n" + "# TYPE user_idle_error gauge\n" + "user_idle_error %d\n"; + + mg_http_reply(c, 200, "Content-Type: text/plain\r\n", text, seconds, ret == 0); + } + else + { + mg_http_reply(c, 404, NULL, "404\n"); + } + } +} + +int main() +{ + lii.cbSize = sizeof(LASTINPUTINFO); + + struct mg_mgr mgr; + mg_mgr_init(&mgr); + mg_http_listen(&mgr, USER_IDLE_EXPORTER_LISTEN_ADDR, fn, &mgr); + printf("Listening " USER_IDLE_EXPORTER_LISTEN_ADDR "\n"); + + for (;;) + mg_mgr_poll(&mgr, 1000); + + return 0; +} + diff --git a/mongoose b/mongoose new file mode 160000 index 0000000..4236405 --- /dev/null +++ b/mongoose @@ -0,0 +1 @@ +Subproject commit 4236405b90e051310aadda818e21c811e404b4d8