mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-03-28 08:37:15 +00:00
Logs inside the WebUI (#634)
This commit is contained in:
parent
248b1bfa19
commit
a5213c6225
@ -93,6 +93,20 @@ min_log_level
|
||||
|
||||
min_log_level = info
|
||||
|
||||
log_path
|
||||
^^^^^^^^
|
||||
|
||||
**Description**
|
||||
The path where the sunshine log is stored.
|
||||
|
||||
**Default**
|
||||
``sunshine.log``
|
||||
|
||||
**Example**
|
||||
.. code-block:: text
|
||||
|
||||
log_path = sunshine.log
|
||||
|
||||
Controls
|
||||
--------
|
||||
|
||||
|
@ -336,6 +336,7 @@ sunshine_t sunshine {
|
||||
platf::appdata().string() + "/sunshine.conf", // config file
|
||||
{}, // cmd args
|
||||
47989,
|
||||
platf::appdata().string() + "/sunshine.log", // log file
|
||||
};
|
||||
|
||||
bool endline(char ch) {
|
||||
@ -788,7 +789,7 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
|
||||
path_f(vars, "pkey", nvhttp.pkey);
|
||||
path_f(vars, "cert", nvhttp.cert);
|
||||
string_f(vars, "sunshine_name", nvhttp.sunshine_name);
|
||||
|
||||
path_f(vars, "log_path", config::sunshine.log_file);
|
||||
path_f(vars, "file_state", nvhttp.file_state);
|
||||
|
||||
// Must be run after "file_state"
|
||||
|
@ -122,6 +122,7 @@ struct sunshine_t {
|
||||
} cmd;
|
||||
|
||||
std::uint16_t port;
|
||||
std::string log_file;
|
||||
};
|
||||
|
||||
extern video_t video;
|
||||
|
@ -274,6 +274,17 @@ void getApps(resp_https_t response, req_https_t request) {
|
||||
response->write(content);
|
||||
}
|
||||
|
||||
void getLogs(resp_https_t response, req_https_t request) {
|
||||
if(!authenticate(response, request)) return;
|
||||
|
||||
print_req(request);
|
||||
|
||||
std::string content = read_file(config::sunshine.log_file.c_str());
|
||||
SimpleWeb::CaseInsensitiveMultimap headers;
|
||||
headers.emplace("Content-Type", "text/plain");
|
||||
response->write(SimpleWeb::StatusCode::success_ok, content, headers);
|
||||
}
|
||||
|
||||
void saveApp(resp_https_t response, req_https_t request) {
|
||||
if(!authenticate(response, request)) return;
|
||||
|
||||
@ -648,6 +659,7 @@ void start() {
|
||||
server.resource["^/troubleshooting$"]["GET"] = getTroubleshootingPage;
|
||||
server.resource["^/api/pin$"]["POST"] = savePin;
|
||||
server.resource["^/api/apps$"]["GET"] = getApps;
|
||||
server.resource["^/api/logs$"]["GET"] = getLogs;
|
||||
server.resource["^/api/apps$"]["POST"] = saveApp;
|
||||
server.resource["^/api/config$"]["GET"] = getConfig;
|
||||
server.resource["^/api/config$"]["POST"] = saveConfig;
|
||||
|
@ -101,6 +101,7 @@ int entry(const char *name, int argc, char *argv[]) {
|
||||
}
|
||||
} // namespace version
|
||||
|
||||
|
||||
void log_flush() {
|
||||
sink->flush();
|
||||
}
|
||||
@ -219,6 +220,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
boost::shared_ptr<std::ostream> stream { &std::cout, NoDelete {} };
|
||||
sink->locked_backend()->add_stream(stream);
|
||||
sink->locked_backend()->add_stream(boost::make_shared<std::ofstream>(config::sunshine.log_file));
|
||||
sink->set_filter(severity >= config::sunshine.min_log_level);
|
||||
|
||||
sink->set_formatter([message = "Message"s, severity = "Severity"s](const bl::record_view &view, bl::formatting_ostream &os) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
#ifndef SUNSHINE_MAIN_H
|
||||
#define SUNSHINE_MAIN_H
|
||||
|
||||
#include <filesystem>
|
||||
#include <string_view>
|
||||
|
||||
#include "thread_pool.h"
|
||||
@ -50,6 +51,4 @@ MAIL(idr);
|
||||
MAIL(rumble);
|
||||
#undef MAIL
|
||||
} // namespace mail
|
||||
|
||||
|
||||
#endif // SUNSHINE_MAIN_H
|
||||
|
@ -49,6 +49,20 @@
|
||||
The minimum log level printed to standard out
|
||||
</div>
|
||||
</div>
|
||||
<!--Log Path-->
|
||||
<div class="mb-3">
|
||||
<label for="log_path" class="form-label">Logfile Path</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="log_path"
|
||||
placeholder="sunshine.log"
|
||||
v-model="config.log_path"
|
||||
/>
|
||||
<div class="form-text">
|
||||
The file where the current logs of Sunshine are stored.
|
||||
</div>
|
||||
</div>
|
||||
<!--Origin Web UI Allowed-->
|
||||
<div class="mb-3">
|
||||
<label for="origin_web_ui_allowed" class="form-label"
|
||||
|
@ -16,11 +16,7 @@
|
||||
Error while closing Appplication
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="btn btn-warning"
|
||||
:disabled="closeAppPressed"
|
||||
@click="closeApp"
|
||||
>
|
||||
<button class="btn btn-warning" :disabled="closeAppPressed" @click="closeApp">
|
||||
Force Close
|
||||
</button>
|
||||
</div>
|
||||
@ -39,16 +35,28 @@
|
||||
Error while unpairing
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
:disabled="unpairAllPressed"
|
||||
@click="unpairAll"
|
||||
>
|
||||
<button class="btn btn-danger" :disabled="unpairAllPressed" @click="unpairAll">
|
||||
Unpair All
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Logs-->
|
||||
<div class="card p-2 my-4">
|
||||
<div class="card-body">
|
||||
<h2>Logs</h2>
|
||||
<br />
|
||||
<div class="d-flex justify-content-between align-items-baseline py-2">
|
||||
<p>See the logs uploaded by Sunshine</p>
|
||||
<input type="text" class="form-control" v-model="logFilter" placeholder="Find..." style="width: 300px">
|
||||
</div>
|
||||
<div>
|
||||
<div class="troubleshooting-logs">
|
||||
<button class="copy-icon"><i class="fas fa-copy " @click="copyLogs"></i></button>{{actualLogs}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@ -60,9 +68,36 @@
|
||||
closeAppStatus: null,
|
||||
unpairAllPressed: false,
|
||||
unpairAllStatus: null,
|
||||
logs: 'Loading...',
|
||||
logFilter: null,
|
||||
logInterval: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
actualLogs(){
|
||||
if(!this.logFilter)return this.logs;
|
||||
let lines = this.logs.split("\n");
|
||||
lines = lines.filter(x => x.indexOf(this.logFilter) != -1);
|
||||
return lines.join("\n");
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.logInterval = setInterval(() => {
|
||||
this.refreshLogs();
|
||||
}, 5000);
|
||||
this.refreshLogs();
|
||||
},
|
||||
beforeDestroy(){
|
||||
clearInterval(this.logInterval);
|
||||
},
|
||||
methods: {
|
||||
refreshLogs() {
|
||||
fetch("/api/logs",)
|
||||
.then((r) => r.text())
|
||||
.then((r) => {
|
||||
this.logs = r;
|
||||
});
|
||||
},
|
||||
closeApp() {
|
||||
this.closeAppPressed = true;
|
||||
fetch("/api/apps/close", { method: "POST" })
|
||||
@ -87,6 +122,40 @@
|
||||
}, 5000);
|
||||
});
|
||||
},
|
||||
copyLogs(){
|
||||
navigator.clipboard.writeText(this.actualLogs);
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.troubleshooting-logs {
|
||||
white-space: pre;
|
||||
font-family: monospace;
|
||||
overflow: auto;
|
||||
max-height: 500px;
|
||||
min-height: 500px;
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.copy-icon {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
color: rgba(0,0,0,1);
|
||||
appearance: none;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.copy-icon:hover {
|
||||
color: rgba(0,0,0,0.75);
|
||||
}
|
||||
.copy-icon:active {
|
||||
color: rgba(0,0,0,1);
|
||||
}
|
||||
</style>
|
||||
|
Loading…
x
Reference in New Issue
Block a user