Skip to content
This repository was archived by the owner on Jun 2, 2025. It is now read-only.

Commit 3f6e68c

Browse files
committed
Add logging and crash handling
1 parent aa6fd4e commit 3f6e68c

13 files changed

+234
-2
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.2.0] - 2024-12-27
9+
10+
### Added
11+
12+
- Added logging to better troubleshoot issues.
13+
814
## [1.1.0] - 2024-12-26
915

1016
### Changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ add_executable(gelly_installer WIN32
5252
src/gui/popups/fatal-error.cpp
5353
src/helpers/launch-gmod.cpp
5454
src/helpers/launch-gmod.hpp
55+
src/logging/log.hpp
56+
src/logging/log.cpp
57+
src/logging/crash-logging.cpp
58+
src/logging/crash-logging.hpp
5559
)
5660

5761
target_link_libraries(gelly_installer

src/curl.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
#include "curl.hpp"
22

3+
#include "logging/log.hpp"
4+
35
namespace gelly {
46
namespace {
57
constexpr auto USER_AGENT = "gelly-installer/1.0";
68
}
7-
Curl::Curl() { curl_global_init(CURL_GLOBAL_ALL); }
8-
Curl::~Curl() { curl_global_cleanup(); }
9+
Curl::Curl() {
10+
Log::Info("Initializing CURL");
11+
curl_global_init(CURL_GLOBAL_ALL);
12+
}
13+
14+
Curl::~Curl() {
15+
Log::Info("Shutting down CURL");
16+
curl_global_cleanup();
17+
}
918

1019
std::shared_ptr<Response> Curl::Get(const std::string &url) const {
20+
Log::Info("Performing GET request to '{}'", url);
1121
const auto handle = curl_easy_init();
1222
if (!handle) {
1323
return nullptr;
@@ -25,6 +35,8 @@ std::shared_ptr<Response> Curl::Get(const std::string &url) const {
2535

2636
const auto code = curl_easy_perform(handle);
2737
if (code != CURLE_OK) {
38+
Log::Error("Failed to perform GET request to '{}': {}", url,
39+
curl_easy_strerror(code));
2840
response->responseCode = code;
2941
} else {
3042
curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &response->responseCode);

src/gui.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "gui.hpp"
22

3+
#include "logging/log.hpp"
4+
35
#include <backends/imgui_impl_sdl2.h>
46
#include <backends/imgui_impl_sdlrenderer2.h>
57
#include <imgui.h>
@@ -63,12 +65,15 @@ void GUI::InitializeImGUI() const {
6365

6466
ImGui_ImplSDL2_InitForSDLRenderer(window->GetWindow(), window->GetRenderer());
6567
ImGui_ImplSDLRenderer2_Init(window->GetRenderer());
68+
69+
Log::Info("Initialized ImGUI");
6670
}
6771

6872
void GUI::ShutdownImGUI() {
6973
ImGui_ImplSDLRenderer2_Shutdown();
7074
ImGui_ImplSDL2_Shutdown();
7175
ImGui::DestroyContext();
76+
Log::Info("Shutdown ImGUI");
7277
}
7378

7479
} // namespace gelly

src/gui/main-installer-window.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "install/get-latest-gelly.hpp"
88
#include "install/install-gelly.hpp"
99
#include "install/uninstall-gelly.hpp"
10+
#include "logging/log.hpp"
1011

1112
#include <imgui.h>
1213

@@ -17,7 +18,14 @@ constexpr auto HEADER = "Gelly Installer";
1718

1819
MainInstallerWindow::MainInstallerWindow(std::shared_ptr<Curl> curl)
1920
: curl(std::move(curl)), latestGellyInfo(GetLatestGellyInfo(this->curl)) {
21+
Log::Info("Latest Gelly version: {}",
22+
latestGellyInfo.has_value() ? latestGellyInfo->version : "N/A");
23+
2024
DetectGellyInstallation();
25+
Log::Info("Gelly installation detected: {}",
26+
gellyInstallation.has_value() ? "yes" : "no");
27+
Log::Info("Gelly version: {}",
28+
gellyInstallation.has_value() ? gellyInstallation->version : "N/A");
2129
}
2230

2331
void MainInstallerWindow::Render() {
@@ -58,6 +66,7 @@ void MainInstallerWindow::Render() {
5866
ImGui::TextColored(ImVec4(0.1f, 0.8f, 0.1f, 1.0f), "%s",
5967
gellyInstallation->version.c_str());
6068
}
69+
6170
ImGui::Separator();
6271
ImGui::PopFont();
6372

@@ -117,6 +126,8 @@ void MainInstallerWindow::DetectGellyInstallation() {
117126
return;
118127
}
119128

129+
Log::Info("Garry's Mod directory: {}", gmodPath->string());
130+
Log::Info("Steam directory: {}", steamPath->string());
120131
gellyInstallation = gelly::DetectGellyInstallation(*gmodPath);
121132
}
122133

src/install/get-latest-gelly.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#include "get-latest-gelly.hpp"
2+
3+
#include "logging/log.hpp"
4+
25
#include <nlohmann/json.hpp>
36

47
namespace gelly {
@@ -11,6 +14,8 @@ std::optional<LatestGellyInfo>
1114
GetLatestGellyInfo(const std::shared_ptr<Curl> &curl) {
1215
const auto response = curl->Get(LATEST_RELEASE_URL);
1316
if (response->responseCode != 200) {
17+
Log::Error("Failed to get latest Gelly release info: status code {}",
18+
response->responseCode);
1419
return std::nullopt;
1520
}
1621

src/install/install-gelly.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "helpers/find-gmod-directory.hpp"
44
#include "helpers/find-steam-directory.hpp"
5+
#include "logging/log.hpp"
56
#include "uninstall-gelly.hpp"
67

78
#include <fstream>
@@ -47,8 +48,10 @@ void ExtractReleaseToDir(const std::filesystem::path &dir,
4748
throw std::runtime_error("Failed to open zip archive.");
4849
}
4950

51+
Log::Info("Extracting Gelly release to {}", dir.string());
5052
try {
5153
zip_int64_t numFiles = zip_get_num_files(archive);
54+
Log::Info("Extracting {} files from zip archive.", numFiles);
5255
for (zip_int64_t i = 0; i < numFiles; i++) {
5356
auto *file = zip_fopen_index(archive, i, 0);
5457
if (!file) {
@@ -94,22 +97,27 @@ void ExtractReleaseToDir(const std::filesystem::path &dir,
9497
zip_fclose(file);
9598
}
9699
} catch (...) {
100+
Log::Error("Failed to extract Gelly release.");
97101
zip_discard(archive);
98102
throw;
99103
}
100104

101105
zip_discard(archive);
106+
Log::Info("Extracted Gelly release to {}", dir.string());
102107
}
103108
} // namespace
104109

105110
void InstallGelly(const LatestGellyInfo &info,
106111
const std::shared_ptr<Curl> &curl,
107112
std::optional<GellyInstallation> priorInstallation) {
113+
Log::Info("Installing Gelly version {}", info.version);
108114
if (priorInstallation.has_value()) {
109115
UninstallGelly(*priorInstallation);
116+
Log::Info("Uninstalled prior Gelly installation.");
110117
}
111118

112119
const auto release = DownloadRelease(info.downloadUrl, curl);
120+
Log::Info("Downloading Gelly release.");
113121
if (release.IsEmpty()) {
114122
throw std::runtime_error("Failed to download Gelly release.");
115123
}
@@ -120,6 +128,7 @@ void InstallGelly(const LatestGellyInfo &info,
120128
throw std::runtime_error("Failed to find Garry's Mod directory.");
121129
}
122130

131+
Log::Info("Extracting Gelly release to Garry's Mod directory.");
123132
ExtractReleaseToDir(*gmodDir, release);
124133
}
125134

src/install/uninstall-gelly.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
#include "uninstall-gelly.hpp"
22

3+
#include "logging/log.hpp"
4+
35
namespace gelly {
46
void UninstallGelly(const GellyInstallation &installation) {
57
remove_all(installation.addonPath);
68
remove(installation.binaryModulePath);
9+
Log::Info("Uninstalled Gelly at {}", installation.addonPath.string());
710
}
811
} // namespace gelly

src/logging/crash-logging.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include "crash-logging.hpp"
2+
3+
#include "log.hpp"
4+
5+
#include <Windows.h>
6+
7+
namespace gelly {
8+
namespace {
9+
// ReSharper disable once CppParameterMayBeConstPtrOrRef
10+
LONG CrashHandler(_EXCEPTION_POINTERS *info) {
11+
Log::Error("Crash detected, writing crash dump");
12+
13+
Log::Error("RIP: 0x{:X}", info->ContextRecord->Rip);
14+
Log::Error("RSP: 0x{:X}", info->ContextRecord->Rsp);
15+
Log::Error("RBP: 0x{:X}", info->ContextRecord->Rbp);
16+
Log::Error("RAX: 0x{:X}", info->ContextRecord->Rax);
17+
Log::Error("RBX: 0x{:X}", info->ContextRecord->Rbx);
18+
Log::Error("RCX: 0x{:X}", info->ContextRecord->Rcx);
19+
20+
switch (info->ExceptionRecord->ExceptionCode) {
21+
case EXCEPTION_ACCESS_VIOLATION:
22+
Log::Error("Access violation");
23+
Log::Error("Attempted to {}", info->ExceptionRecord->ExceptionInformation[0]
24+
? "write"
25+
: "read");
26+
Log::Error("Address: 0x{:X}",
27+
info->ExceptionRecord->ExceptionInformation[1]);
28+
break;
29+
case 0xE06D7363: {
30+
Log::Error("C++ exception");
31+
const auto exception = reinterpret_cast<std::exception *>(
32+
info->ExceptionRecord->ExceptionInformation[1]);
33+
Log::Error("Exception: {}", exception->what());
34+
} break;
35+
default:
36+
Log::Error("Unknown exception code: 0x{:X}",
37+
info->ExceptionRecord->ExceptionCode);
38+
}
39+
40+
Log::SaveToFile();
41+
42+
return EXCEPTION_CONTINUE_SEARCH;
43+
}
44+
} // namespace
45+
46+
void SetupCrashLogging() { AddVectoredExceptionHandler(1, CrashHandler); }
47+
void ShutdownCrashLogging() { RemoveVectoredExceptionHandler(CrashHandler); }
48+
49+
} // namespace gelly

src/logging/crash-logging.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#pragma once
2+
3+
namespace gelly {
4+
void SetupCrashLogging();
5+
void ShutdownCrashLogging();
6+
} // namespace gelly

0 commit comments

Comments
 (0)