diff --git a/documents/references.md b/documents/references.md
index f0f8b861129839781f6fe260ea3cdd25473e7fa8..dd34e5e015dcfd221a802c74a470d388bfb26d49 100644
--- a/documents/references.md
+++ b/documents/references.md
@@ -32,6 +32,7 @@ Various references used in project.
 * Getting File/LineNum:
 ** <https://stackoverflow.com/a/42135375>
 ** <https://stackoverflow.com/a/8884408>
+* Append variables to strings - <https://stackoverflow.com/a/10219339> <https://stackoverflow.com/a/18997915>
 
 #### C++ Classes
 * General Class Syntax - <https://www.w3schools.com/cpp/cpp_classes.asp>
diff --git a/part_1/image.cu b/part_1/image.cu
index 779e780b736099284a40b42522b1127914daca27..d776917eb0db90f58c4a93cab142b412916c15e3 100644
--- a/part_1/image.cu
+++ b/part_1/image.cu
@@ -10,8 +10,17 @@
     #include "utility.h"
 #endif
 
+#ifndef user_headers_logging
+    #define user_headers_logging
+    #include "logging.h"
+#endif
+
 
 // Global Variables.
+#ifndef LOGGING_CLASS_INIT
+    #define LOGGING_CLASS_INIT
+    extern Logging logger;
+#endif
 const Image::Rgb Image::pixelBlack = Image::Rgb(0);
 const Image::Rgb Image::pixelWhite = Image::Rgb(1);
 const Image::Rgb Image::pixelRed = Image::Rgb(1,0,0);
@@ -28,8 +37,9 @@ const Image::Rgb Image::pixelLiBlue = Image::Rgb(0,1,1);
  * :param image_path: Path to an image on the system.
  */
 void Image::calculate_paths(std::string image_path) {
-    // std::cout << "\n\n\n\n\nCalculating input/output paths..." << std::endl;
-    // std::cout << "image_path: " << image_path << std::endl;
+    logger.debug("Image::calculate_paths():");
+    logger.debug("    image_path: " + image_path);
+    logger.debug("");
 
     // // Calculate output path location.
     output_path = "../output/";
@@ -42,7 +52,6 @@ void Image::calculate_paths(std::string image_path) {
 
         // Pull current substring value from input path.
         token = image_path.substr(0, image_path.find("/"));
-        // std::cout << "    " << token << std::endl;
         image_path.erase(0, pos + 1);
 
         // Check if directory value is value we care about.
@@ -60,9 +69,6 @@ void Image::calculate_paths(std::string image_path) {
     }
 
     output_path += base_filename;
-    // std::cout << "output_path: " << output_path << std::endl;
-
-    // std::cout << "Input/output paths calculated.\n\n\n\n\n" << std::endl;
 }
 
 
@@ -70,13 +76,16 @@ void Image::calculate_paths(std::string image_path) {
  * Imports image file data, using class variable data.
  */
 void Image::import_image_file() {
+    logger.debug("Image::import_image_file():");
+    logger.debug("");
+
     // Open input file.
     std::ifstream input_file;
     input_file.open(input_path, std::ios::binary | std::ios::in);
 
     if (! input_file.good()) {
         // Failed to open file.
-        std::cerr << "Failed to open file \"" + input_path + "\"." << std::endl;
+        logger.error("Failed to open file \"" + input_path + "\"");
     } else {
         // File opened. Grab data.
         std::string header;
@@ -89,7 +98,6 @@ void Image::import_image_file() {
         input_file >> width >> height >> bit_depth;
 
         // Create and populate image.
-        // std::cout << "Parsing input image" << std::endl;
         pixel_arr = new Rgb[width * height];
 
         // Skip empty lines in necessary until we get to the binary data.
@@ -116,8 +124,10 @@ void Image::import_image_file() {
  * Base constructor.
  */
 Image::Image() {
+    logger.debug("Image::Image Constructor():");
+    logger.debug("");
+
     // Currently test logic.
-    std::cout << "\nConstructing Image class." << std::endl;
 
     // Essentially creates a 10x10 pixel test image.
     input_path = "../input/pbm/400x300/hallway_00.pbm";
@@ -132,8 +142,6 @@ Image::Image() {
     for (int index = 0; index < (width * height); index++) {
         pixel_arr[index] = c;
     }
-
-    std::cout << "Image class populated." << std::endl;
 }
 
 /**
@@ -141,15 +149,15 @@ Image::Image() {
  * Output path is determined based on parsing input path.
  */
 Image::Image(std::string user_path) {
-    std::cout << "\nConstructing Image class." << std::endl;
-
-    std::cout << "user_path: " << user_path << std::endl;
+    logger.debug("Image::Image Constructor():");
+    logger.debug("    user_path: " + user_path);
+    logger.debug("");
 
     // Re-validate path for saving to class..
     path_validator_struct* return_struct = validate_path(user_path);
     int path_type = return_struct->file_type;
     if (return_struct->err_code) {
-        std::cerr << "Error verifying file type: " << return_struct->err_code.message() << std::endl;
+        logger.error("Error verifying file type: " + return_struct->err_code.message());
         return;
     }
     free_path_validator_struct(return_struct);
@@ -158,11 +166,9 @@ Image::Image(std::string user_path) {
         calculate_paths(user_path);
         import_image_file();
     } else {
-        std::cerr << "Provided path is not to image file. Class initialization failed." << std::endl;
+        logger.error("Provided path is not to image file. Class initialization failed.");
         return;
     }
-
-    std::cout << "Image class populated." << std::endl;
 }
 
 //endregion Constructors.
@@ -174,13 +180,16 @@ Image::Image(std::string user_path) {
  * Displays general properties of image held in class.
  */
 void Image::display_properties() {
-    std::cout << std::endl;
-    std::cout << "input file path: " << input_path << std::endl;
-    std::cout << "output file path: " << output_path << std::endl;
-    std::cout << "width: " << width << std::endl;
-    std::cout << "height: " << height << std::endl;
-    std::cout << "bit depth: " << bit_depth << std::endl;
-    std::cout << std::endl;
+    logger.debug("Image::display_properties():");
+    logger.debug("");
+
+    logger.info("");
+    logger.info("input file path: " + input_path);
+    logger.info("output file path: " + output_path);
+    logger.info("width: " + width);
+    logger.info("height: " + height);
+    logger.info("bit depth: " + bit_depth);
+    logger.info("");
 }
 
 
@@ -188,7 +197,10 @@ void Image::display_properties() {
  * Saves class image data to output file.
  */
 void Image::save() {
-    std::cout << "Attempting to save image to \"" << output_path << "\"." << std::endl;
+    logger.debug("Image::save():");
+    logger.debug("");
+
+    logger.debug("Attempting to save image to \"" + output_path + "\".");
 
     // Open output file stream.
     std::ofstream output_file;
@@ -201,7 +213,7 @@ void Image::save() {
         // Check if opened successfully.
         if (output_file.fail()) {
             // Failed to open.
-            std::cout << "Failed to open file \"" + output_path + "\".\n";
+            logger.error("Failed to open file \"" + output_path + "\"");
         } else {
             // Opened successfully.
 
@@ -221,10 +233,10 @@ void Image::save() {
 
         // Close file stream.
         output_file.close();
-        std::cout << "Image saved." << std::endl;
+        logger.info("Image saved.");
 
     } catch (const char* err) {
-        fprintf(stderr, "%s\n", err);
+        logger.error("Failed to save image: " + std::string(err));
         output_file.close();
     }
 }
diff --git a/part_1/logging.cu b/part_1/logging.cu
index 74ce6a06ec0cb4fedfa65aff755e39aa27d07858..5fb3771f7cbb3a9eeef3df3ed9157c0cabcae9b3 100644
--- a/part_1/logging.cu
+++ b/part_1/logging.cu
@@ -7,6 +7,7 @@
 // User Import Headers.
 #ifndef user_headers
     #define user_headers
+    #define user_headers_logging
     #include "logging.h"
 #endif
 
@@ -15,15 +16,21 @@
  * Class constructor.
  */
 Logging::Logging() {
-    std::cout << "Initializing logger." << std::endl;
     std::filesystem::path cwd = std::filesystem::current_path();
     core_logging_folder = cwd.string() + "/log/";
-    std::cout << "logging_folder: " << core_logging_folder << std::endl;
+
+    // Check if logging directory exists.
+    struct stat info;
+    if ( (stat(core_logging_folder.c_str(), &info) != 0) || (! info.st_mode & S_IFDIR)) {
+        // Directory does not exist.
+        mkdir(core_logging_folder.c_str(), 0777);
+    }
 
     // Open file descriptors.
-    error_stream.open(core_logging_folder + "error.log", std::ios::binary | std::ios::out);
-    warn_stream.open(core_logging_folder + "warn.log", std::ios::binary | std::ios::out);
-    info_stream.open(core_logging_folder + "info.log", std::ios::binary | std::ios::out);
+    error_stream.open(core_logging_folder + "error.log", std::ios::app | std::ios::out);
+    warn_stream.open(core_logging_folder + "warn.log", std::ios::app | std::ios::out);
+    info_stream.open(core_logging_folder + "info.log", std::ios::app | std::ios::out);
+    debug_stream.open(core_logging_folder + "debug.log", std::ios::app | std::ios::out);
 }
 
 /**
@@ -31,6 +38,17 @@ Logging::Logging() {
  * Closes file descriptors, if open.
  */
 Logging::~Logging() {
+    close_log_files();
+}
+
+
+/**
+ * Closes all open logging file descriptors.
+ */
+void Logging::close_log_files() {
+    if (debug_stream.is_open()) {
+        debug_stream.close();
+    }
     if (info_stream.is_open()) {
         info_stream.close();
     }
@@ -42,29 +60,82 @@ Logging::~Logging() {
     }
 }
 
+
+/**
+ * Writes message to info log file.
+ */
+void Logging::debug(std::string msg, std::string log_type, const char* file, long line_num) {
+    // Build and write logging message.
+    std::string log_prefix = " [" + log_type + "] [ " + std::string(file) + " | " + std::to_string(line_num) + " ] ";
+    debug_stream << log_prefix << msg << std::endl;
+}
+
+
 /**
  * Writes message to info log file.
  */
-void Logging::info(char const* file, long line_num, std::string msg) {
-    info_stream << msg << std::endl;
+void Logging::info(std::string msg, std::string log_type, const char* file, long line_num) {
+    // Build and write logging message.
+    std::string log_prefix = " [" + log_type + "] [ " + std::string(file) + " | " + std::to_string(line_num) + " ] ";
+    info_stream << log_prefix << msg << std::endl;
+
+    // Write to console.
+    std::cout << log_prefix << msg << std::endl;
+
+    // Also write to lower level loggers.
+    debug(msg, log_type, file, line_num);
 }
 
 /**
  * Writes message to warning log file.
  */
-void Logging::warn(char const* file, long line_num, std::string msg) {
-    warn_stream << msg << std::endl;
+void Logging::warn(std::string msg, std::string log_type, const char* file, long line_num) {
+    // Build and write logging message.
+    std::string log_prefix = " [" + log_type + "] [ " + std::string(file) + " | " + std::to_string(line_num) + " ] ";
+    warn_stream << log_prefix << msg << std::endl;
 
     // Also write to lower level loggers.
-    info(file, line_num, msg);
+    info(msg, log_type, file, line_num);
 }
 
 /**
  * Writes message to error log file.
  */
-void Logging::error(char const* file, long line_num, std::string msg) {
-    error_stream << msg << std::endl;
+void Logging::error(std::string msg, std::string log_type, const char* file, long line_num) {
+    // Build and write logging message.
+    std::string log_prefix = " [" + log_type + "] [ " + std::string(file) + " | " + std::to_string(line_num) + " ] ";
+    error_stream << log_prefix << msg << std::endl;
 
     // Also write to lower level loggers.
-    warn(file, line_num, msg);
+    warn(msg, log_type, file, line_num);
+}
+
+
+/**
+ * Prints out logging location to console.
+ */
+void Logging::display_logging_folder() {
+    std::cout << "Logging folder: " << core_logging_folder << std::endl;
+}
+
+
+/**
+ * Resets contents of logging files.
+ */
+void Logging::clear_log_files() {
+    // First close any open logging file descriptors.
+    close_log_files();
+
+    // Open log files in "write mode", which will override any present data.
+    error_stream.open(core_logging_folder + "error.log", std::ios::out);
+    warn_stream.open(core_logging_folder + "warn.log", std::ios::out);
+    info_stream.open(core_logging_folder + "info.log", std::ios::out);
+    debug_stream.open(core_logging_folder + "debug.log", std::ios::out);
+
+    // Close log files and reopen in "append mode". Probably not necessary but here to be safe.
+    close_log_files();
+    error_stream.open(core_logging_folder + "error.log", std::ios::app | std::ios::out);
+    warn_stream.open(core_logging_folder + "warn.log", std::ios::app | std::ios::out);
+    info_stream.open(core_logging_folder + "info.log", std::ios::app | std::ios::out);
+    debug_stream.open(core_logging_folder + "debug.log", std::ios::out);
 }
diff --git a/part_1/logging.h b/part_1/logging.h
index b21751935af5c6b1080d18ac9256f68be8897a02..2d7d38e524853c5a70cc70755ea97f1afa869525 100644
--- a/part_1/logging.h
+++ b/part_1/logging.h
@@ -7,6 +7,7 @@
 #include <cstdio>
 #include <cstdlib>
 #include <cctype>
+#include <execinfo.h>
 #include <iostream>
 #include <filesystem>
 #include <fstream>
@@ -22,6 +23,7 @@ class Logging {
 
     private:
         std::string core_logging_folder;
+        std::ofstream debug_stream;
         std::ofstream info_stream;
         std::ofstream warn_stream;
         std::ofstream error_stream;
@@ -38,19 +40,38 @@ class Logging {
          */
         ~Logging();
 
+        /**
+         * Closes all open logging file descriptors.
+         */
+        void close_log_files();
+
+        /**
+         * Writes message to info log file.
+         */
+        void debug(std::string msg, std::string log_type = "DEBUG", const char* file = __builtin_FILE(), long line_num  = __builtin_LINE());
+
         /**
          * Writes message to info log file.
          */
-        void info(char const* file, long line_num, std::string msg);
+        void info(std::string msg, std::string log_type = "INFO", const char* file = __builtin_FILE(), long line_num  = __builtin_LINE());
 
         /**
          * Writes message to warning log file.
          */
-        void warn(char const* file, long line_num, std::string msg);
+        void warn(std::string msg, std::string log_type = "WARN", const char* file = __builtin_FILE(), long line_num  = __builtin_LINE());
 
         /**
          * Writes message to error log file.
          */
-        void error(char const* file, long line_num, std::string msg);
-};
+        void error(std::string msg, std::string log_type = "ERROR", const char* file = __builtin_FILE(), long line_num  = __builtin_LINE());
+
+        /**
+         * Prints out logging location to console.
+         */
+        void display_logging_folder();
 
+        /**
+         * Resets contents of logging files.
+         */
+        void clear_log_files();
+};
diff --git a/part_1/main.cu b/part_1/main.cu
index d7950db864d917b5aa43c1217e476c4814f36953..5710a71bc3c0e8245b861e94e368f4b8712af91a 100644
--- a/part_1/main.cu
+++ b/part_1/main.cu
@@ -17,11 +17,15 @@
 // User Import Headers.
 #ifndef user_headers
     #define user_headers
-    #include "logging.h"
     #include "image.h"
     #include "utility.h"
 #endif
 
+#ifndef user_headers_logging
+    #define user_headers_logging
+    #include "logging.h"
+#endif
+
 
 // Method Declaration.
 void process_dir(std::string path_str);
@@ -32,6 +36,10 @@ void process_file(std::string path_str);
 
 
 // Global Variables.
+#ifndef LOGGING_CLASS_INIT
+    #define LOGGING_CLASS_INIT
+    Logging logger;
+#endif
 
 
 /*
@@ -42,36 +50,37 @@ int main(int argc, char* argv[]) {
     printf("\n");
     printf("\n");
 
-    Logging logger;
+    // Initialize logging and clear any existing log contents for new program run.
+    logger.clear_log_files();
+
+    // Check provided number of args.
+    if (argc < 2) {
+        // No args provided.
+        printf("Provided too few program args. Expected one arg.");
+    } else if (argc > 2) {
+        // More than one arg provided.
+        printf("Provided too many program args. Expected one arg.");
+    } else {
+        // Correct number of args provided. Pass to image class for processing.
+
+        // Check data type.
+        std::string path_str = argv[1];
+        path_validator_struct* return_struct = validate_path(path_str);
+        int path_type = return_struct->file_type;
+        if (return_struct->err_code) {
+            std::cerr << "Error verifying file type: " << return_struct->err_code.message() << std::endl;
+        }
+        free_path_validator_struct(return_struct);
 
-    // // Check provided number of args.
-    // if (argc < 2) {
-    //     // No args provided.
-    //     printf("Provided too few program args. Expected one arg.");
-    // } else if (argc > 2) {
-    //     // More than one arg provided.
-    //     printf("Provided too many program args. Expected one arg.");
-    // } else {
-    //     // Correct number of args provided. Pass to image class for processing.
-
-    //     // Check data type.
-    //     std::string path_str = argv[1];
-    //     path_validator_struct* return_struct = validate_path(path_str);
-    //     int path_type = return_struct->file_type;
-    //     if (return_struct->err_code) {
-    //         std::cerr << "Error verifying file type: " << return_struct->err_code.message() << std::endl;
-    //     }
-    //     free_path_validator_struct(return_struct);
-
-    //     // Handle based on provided type.
-    //     if (path_type == TYPE_DIR) {
-    //         // Process dir.
-    //         process_dir(path_str);
-    //     } else if (path_type == TYPE_FILE) {
-    //         // Process file.
-    //         process_file(path_str);
-    //     }
-    // }
+        // Handle based on provided type.
+        if (path_type == TYPE_DIR) {
+            // Process dir.
+            process_dir(path_str);
+        } else if (path_type == TYPE_FILE) {
+            // Process file.
+            process_file(path_str);
+        }
+    }
 
     printf("\n");
     printf("\n");
@@ -85,7 +94,11 @@ int main(int argc, char* argv[]) {
  * Assumes directory is full of image files.
  */
 void process_dir(std::string path_str) {
-    std::cout << "Handling dir." << std::endl;
+    logger.debug("process_dir():");
+    logger.debug("    path_str: " + path_str);
+    logger.debug("");
+
+    logger.info("Handling dir.");
 
     // Process all files in directory.
     for (const auto & entry : std::filesystem::directory_iterator(path_str)) {
@@ -120,7 +133,11 @@ void process_dir(std::string path_str) {
  * Processes a single image file.
  */
 void process_file(std::string path_str) {
-    std::cout << "Handling file." << std::endl;
+    logger.debug("process_file():");
+    logger.debug("    path_str: " + path_str);
+    logger.debug("");
+
+    logger.info("Handling file.");
 
     Image image(path_str);
     image.display_properties();
diff --git a/part_1/utility.cu b/part_1/utility.cu
index ec66384d93d8fced1de670a5e73984a8bf4df0ff..d585b055a8e974d7e07d506485e8a842cd35839c 100644
--- a/part_1/utility.cu
+++ b/part_1/utility.cu
@@ -8,8 +8,17 @@
     #include "utility.h"
 #endif
 
+#ifndef user_headers_logging
+    #define user_headers_logging
+    #include "logging.h"
+#endif
+
 
 // Global Variables.
+#ifndef LOGGING_CLASS_INIT
+    #define LOGGING_CLASS_INIT
+    extern Logging logger;
+#endif
 const int TYPE_DIR = 0;
 const int TYPE_FILE = 1;
 const int TYPE_OTHER = 2;
@@ -20,16 +29,10 @@ path_validator_struct* path_validator_ptr;
  * Initializes a "path_validator" object.
  */
 path_validator_struct* initialize_path_validator_struct(int file_type, std::error_code err_code) {
-
-    // printf("\n");
-    // printf("initialize_path_validator_struct:\n");
-    // printf("    file_type: %i\n", file_type);
-    // if (err_code) {
-    //     std::cerr << "    err_code: " << err_code.message();
-    // } else {
-    //     printf("    err_code: null\n");
-    // }
-    // printf("\n");
+    logger.debug("initialize_path_validator_struct():");
+    logger.debug("    file_type: " + std::to_string(file_type));
+    // logger.debug("    err_code: " + err_code);
+    logger.debug("");
 
     // Create struct.
     path_validator_ptr = (path_validator_struct*) calloc(1, sizeof(path_validator_struct));
@@ -46,6 +49,10 @@ path_validator_struct* initialize_path_validator_struct(int file_type, std::erro
  * Destroyes passed "path_validator" object and all associated fields.
  */
 void free_path_validator_struct(path_validator_struct* path_validator_ptr) {
+    logger.debug("free_path_validator_struct():");
+    // logger.debug("    path_validator_ptr: " + path_validator_ptr);
+    logger.debug("");
+
     free(path_validator_ptr);
 }
 
@@ -55,11 +62,13 @@ void free_path_validator_struct(path_validator_struct* path_validator_ptr) {
  * Returns struct of data.
  */
 path_validator_struct* validate_path(std::string path_str) {
+    logger.debug("validate_path():");
+    logger.debug("    path_str: " + path_str);
+    logger.debug("");
+
     int type_value = TYPE_OTHER;
     std::error_code ec;
 
-    std::cout << "path_str: \"" + path_str + "\"\n";
-
     // Check if provided path exists.
     std::ifstream test_path_exists(path_str);
     if (test_path_exists) {