diff --git a/DESCRIPTION b/DESCRIPTION index 800faac..feaa693 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -34,7 +34,8 @@ Imports: R6, ResultModelManager, yaml, - stringr + stringr, + ParallelLogger Remotes: javier-gracia-tabuenca-tuni/DatabaseConnector@bigquery-DBI-2 Suggests: diff --git a/NAMESPACE b/NAMESPACE index f06b1e3..636fce7 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -12,16 +12,19 @@ export(createPlotFromResults) export(createReport) export(createStratifiedCodeCountsTable) export(create_api) +export(fct_setUpLogger) export(getCDMSource) export(getCodeCounts) export(getCodeCounts_memoise) export(getConceptsWithCodeCounts) export(getConceptsWithCodeCounts_memoise) +export(getLogs) export(helper_FinnGen_getDatabaseFile) export(helper_FinnGen_getDatabaseFileCounts) export(helper_createSqliteDatabaseFromDatabase) export(pruneLevelsFromResults) export(runApiServer) +export(sendFeedback) importFrom(DatabaseConnector,connect) importFrom(DatabaseConnector,createConnectionDetails) importFrom(DatabaseConnector,createDbiConnectionDetails) diff --git a/R/fct_logs.R b/R/fct_logs.R new file mode 100644 index 0000000..61e5495 --- /dev/null +++ b/R/fct_logs.R @@ -0,0 +1,59 @@ + +#' Set Up Logger +#' +#' Sets up a logger with console and file appenders for logging. +#' +#' @param sToken The session token to be added to log entries +#' +#' @return A logger object. +#' +#' @export +fct_setUpLogger <- function(sToken=""){ + + timestamp <- timestamp <- as.character(as.numeric(format(Sys.time(), "%d%m%Y%H%M%OS2"))*100) + folderWithLog <- file.path(tempdir(), paste0("logs", timestamp)) + dir.create(folderWithLog, showWarnings = FALSE) + fileName <- file.path(folderWithLog, "log.txt") + options(parallelLoggerTempFile = fileName) + + logger <- ParallelLogger::createLogger( + threshold = "TRACE", + appenders = list( + # to console for tracking + .createConsoleAppenderForSandboxLogging(sToken=sToken), + # to file for showing in app + ParallelLogger::createFileAppender( + fileName = fileName, + layout = ParallelLogger::layoutTimestamp + ) + ) + ) + ParallelLogger::clearLoggers() + #addDefaultFileLogger(file.path(folderWithLog, "log2.txt")) + ParallelLogger::registerLogger(logger) + +} + + +#' Create Console Appender for Sandbox Logging +#' +#' Creates a console appender for sandbox logging with a specified layout. +#' +#' @param layout A layout function for the logger. Defaults to ParallelLogger::layoutParallel. +#' @param sToken The session token to be added to log entries +#' +#' @return An appender object for logging. +#' +.createConsoleAppenderForSandboxLogging <- function(layout = ParallelLogger::layoutParallel,sToken) { + appendFunction <- function(this, level, message, echoToConsole) { + # Avoid note in check: + # Should add session id (session$token) to help group logs by session in central log database. + # paste0("[sandbox-co2-log] session:", session$token, message) + missing(this) + message <- paste0("[sandbox-co2-log] --session:",sToken,"-- ",message) + writeLines(message, con = stderr()) + } + appender <- list(appendFunction = appendFunction, layout = layout) + class(appender) <- "Appender" + return(appender) +} diff --git a/R/getCDMSource.R b/R/getCDMSource.R index b0b545f..41c9d8a 100644 --- a/R/getCDMSource.R +++ b/R/getCDMSource.R @@ -18,7 +18,7 @@ #' getCDMSource <- function( CDMdbHandler) { - message("getCDMSource") + ParallelLogger::logInfo("getCDMSource: Getting CDM source information") # # VALIDATE # diff --git a/R/getCodeCounts.R b/R/getCodeCounts.R index 315e4ee..0687b56 100644 --- a/R/getCodeCounts.R +++ b/R/getCodeCounts.R @@ -36,7 +36,7 @@ getCodeCounts <- function( CDMdbHandler, conceptId, codeCountsTable = "code_counts") { - message("getCodeCounts: ", conceptId) + ParallelLogger::logInfo("getCodeCounts: Getting code counts for conceptId: ", conceptId) # # VALIDATE # diff --git a/R/getConceptsWithCodeCounts.R b/R/getConceptsWithCodeCounts.R index 2f10f2a..dc5fbb9 100644 --- a/R/getConceptsWithCodeCounts.R +++ b/R/getConceptsWithCodeCounts.R @@ -37,6 +37,8 @@ getConceptsWithCodeCounts <- function( vocabularyDatabaseSchema <- CDMdbHandler$vocabularyDatabaseSchema resultsDatabaseSchema <- CDMdbHandler$resultsDatabaseSchema + ParallelLogger::logInfo("getConceptsWithCodeCounts: Getting concepts with code counts") + # # FUNCTION # diff --git a/R/getLogs.R b/R/getLogs.R new file mode 100644 index 0000000..7f43c88 --- /dev/null +++ b/R/getLogs.R @@ -0,0 +1,17 @@ + +#' Get logs from ParallelLogger temp file +#' +#' @description +#' Retrieves log messages from the ParallelLogger temporary log file. +#' This may help track internal API events, errors, and debug information. +#' +#' @return A character vector with each log line as a string. +#' +#' @export +getLogs <- function() { + ParallelLogger::logInfo("getLogs: Getting logs") + # + fileName <- getOption("parallelLoggerTempFile") + logs <- readLines(fileName) + return(logs) +} diff --git a/R/runApiServer.R b/R/runApiServer.R index f64761b..5946b16 100644 --- a/R/runApiServer.R +++ b/R/runApiServer.R @@ -40,8 +40,11 @@ runApiServer <- function( # VALIDATE # + fct_setUpLogger() + ParallelLogger::logInfo("Starting ROMOPAPI API server") + if (is.null(cohortTableHandlerConfig)) { - message("No path to database config provided. Using the test counts only database.") + ParallelLogger::logInfo("No path to database config provided. Using the test counts only database.") # if not provided, use the test counts only database test_databasesConfig <- HadesExtras_readAndParseYaml( pathToYalmFile = system.file("testdata", "config", "onlyCounts_databasesConfig.yml", package = "ROMOPAPI"), @@ -58,6 +61,7 @@ runApiServer <- function( } if (buildCountsTable == TRUE) { + ParallelLogger::logInfo("Building code counts tables") createCodeCountsTables(CDMdbHandler, codeCountsTable = "code_counts") } diff --git a/R/sendFeedback.R b/R/sendFeedback.R new file mode 100644 index 0000000..685c461 --- /dev/null +++ b/R/sendFeedback.R @@ -0,0 +1,21 @@ + + + +#' Send feedback to the API server +#' +#' @param feedback A character string containing the feedback to send. +#' +#' @return NULL +#' +#' @export +sendFeedback <- function(feedback) { + + # + # VALIDATE + # + feedback |> checkmate::assertCharacter() + # + # FUNCTION + # + ParallelLogger::logInfo("FEEDBACK: ", feedback) +} \ No newline at end of file diff --git a/inst/plumber/plumber.R b/inst/plumber/plumber.R index 26b876a..d624f72 100644 --- a/inst/plumber/plumber.R +++ b/inst/plumber/plumber.R @@ -110,3 +110,19 @@ function(res) { # Read and return the file content readChar(file_path, file.info(file_path)$size) } + +#* Get the logs +#* @get /getLogs +function() { + logs <- getLogs() + return(logs) +} + +#* Send feedback to the API server +#* @post /sendFeedback +function(res, feedback = "") { + feedback <- as.character(feedback) + sendFeedback(feedback) + res$status <- 200 + return(list(message = "Feedback sent")) +} \ No newline at end of file diff --git a/inst/testdata/config/atlasDev_databasesConfig.yml b/inst/testdata/config/atlasDev_databasesConfig.yml index 4d93223..335ccac 100644 --- a/inst/testdata/config/atlasDev_databasesConfig.yml +++ b/inst/testdata/config/atlasDev_databasesConfig.yml @@ -13,8 +13,8 @@ BQ5k: bigint: integer64 tempEmulationSchema: atlas-development-270609.sandbox cdm: - cdmDatabaseSchema: atlas-development-270609.finngen_omop_r13_v3 - vocabularyDatabaseSchema: atlas-development-270609.finngen_omop_r13_v3 + cdmDatabaseSchema: atlas-development-270609.finngen_omop_r13_v3_5k + vocabularyDatabaseSchema: atlas-development-270609.finngen_omop_r13_v3_5k resultsDatabaseSchema: atlas-development-270609.sandbox cohortTable: cohortDatabaseSchema: atlas-development-270609.sandbox diff --git a/inst/testdata/data/FinnGenR13_countsOnly.sqlite b/inst/testdata/data/FinnGenR13_countsOnly.sqlite index 22ea300..da24204 100644 Binary files a/inst/testdata/data/FinnGenR13_countsOnly.sqlite and b/inst/testdata/data/FinnGenR13_countsOnly.sqlite differ diff --git a/inst/testdata/data/createTestingData.R b/inst/testdata/data/createTestingData.R index d84aa40..6161cc1 100644 --- a/inst/testdata/data/createTestingData.R +++ b/inst/testdata/data/createTestingData.R @@ -8,7 +8,8 @@ conceptIds <- c( 317009, # Snomed: Asthma 45596282, # ICD10: Asthma 21601855, # ATC level 4: C10AA (Statins) - 2010001615 # test endpoint + #2010001615, # test endpoint + 320136 # Big graph, parent of Asthma snomed concept (Disorders of the respiratory system) ) CDMdbHandler <- HadesExtras_createCDMdbHandlerFromList(test_cohortTableHandlerConfig, loadConnectionChecksLevel = "basicChecks") @@ -45,3 +46,4 @@ dplyr::tbl(connection, "stratified_code_counts") |> dplyr::count() |> dplyr::pull(n) |> expect_gt(0) + diff --git a/man/dot-createConsoleAppenderForSandboxLogging.Rd b/man/dot-createConsoleAppenderForSandboxLogging.Rd new file mode 100644 index 0000000..d0da0f4 --- /dev/null +++ b/man/dot-createConsoleAppenderForSandboxLogging.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fct_logs.R +\name{.createConsoleAppenderForSandboxLogging} +\alias{.createConsoleAppenderForSandboxLogging} +\title{Create Console Appender for Sandbox Logging} +\usage{ +.createConsoleAppenderForSandboxLogging( + layout = ParallelLogger::layoutParallel, + sToken +) +} +\arguments{ +\item{layout}{A layout function for the logger. Defaults to ParallelLogger::layoutParallel.} + +\item{sToken}{The session token to be added to log entries} +} +\value{ +An appender object for logging. +} +\description{ +Creates a console appender for sandbox logging with a specified layout. +} diff --git a/man/fct_setUpLogger.Rd b/man/fct_setUpLogger.Rd new file mode 100644 index 0000000..6f28acb --- /dev/null +++ b/man/fct_setUpLogger.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fct_logs.R +\name{fct_setUpLogger} +\alias{fct_setUpLogger} +\title{Set Up Logger} +\usage{ +fct_setUpLogger(sToken = "") +} +\arguments{ +\item{sToken}{The session token to be added to log entries} +} +\value{ +A logger object. +} +\description{ +Sets up a logger with console and file appenders for logging. +} diff --git a/man/getLogs.Rd b/man/getLogs.Rd new file mode 100644 index 0000000..570e660 --- /dev/null +++ b/man/getLogs.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/getLogs.R +\name{getLogs} +\alias{getLogs} +\title{Get logs from ParallelLogger temp file} +\usage{ +getLogs() +} +\value{ +A character vector with each log line as a string. +} +\description{ +Retrieves log messages from the ParallelLogger temporary log file. +This may help track internal API events, errors, and debug information. +} diff --git a/man/sendFeedback.Rd b/man/sendFeedback.Rd new file mode 100644 index 0000000..5b80baa --- /dev/null +++ b/man/sendFeedback.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sendFeedback.R +\name{sendFeedback} +\alias{sendFeedback} +\title{Send feedback to the API server} +\usage{ +sendFeedback(feedback) +} +\arguments{ +\item{feedback}{A character string containing the feedback to send.} +} +\description{ +Send feedback to the API server +} diff --git a/tests/testmanual/manualtest-runApiServer.R b/tests/testmanual/manualtest-runApiServer.R new file mode 100644 index 0000000..7c69921 --- /dev/null +++ b/tests/testmanual/manualtest-runApiServer.R @@ -0,0 +1,10 @@ + + +databaseConfig <- yaml::read_yaml("inst/testdata/config/onlyCounts_databasesConfig.yml") + +ROMOPAPI::runApiServer( + cohortTableHandlerConfig = databaseConfig$cohortTableHandler, + buildCountsTable = FALSE +) + +# http://127.0.0.1:8585/__docs__/