Skip to content

Commit

Permalink
feat(log): handle errors (#144)
Browse files Browse the repository at this point in the history
Description
---
Fixes logging, fixes errors translation, improves readability and adds
lots of logs (especially useful for errors debugging)

Motivation and Context
---
Solves #143

How Has This Been Tested?
---

What process can a PR reviewer use to test or verify this change?
---

<!-- Checklist -->
<!-- 1. Is the title of your PR in the form that would make nice release
notes? The title, excluding the conventional commit
tag, will be included exactly as is in the CHANGELOG, so please think
about it carefully. -->


Breaking Changes
---

- [x] None
- [ ] Requires data directory on base node to be deleted
- [ ] Requires hard fork
- [ ] Other - Please specify

<!-- Does this include a breaking change? If so, include this line as a
footer -->
<!-- BREAKING CHANGE: Description what the user should do, e.g. delete a
database, resync the chain -->
  • Loading branch information
karczuRF authored Nov 20, 2024
1 parent 83429bc commit 661beb9
Show file tree
Hide file tree
Showing 16 changed files with 84 additions and 49 deletions.
2 changes: 1 addition & 1 deletion locales/en/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"failed-to-find-tapplet-version": "Failed to find tapplet version",
"failed-to-obtain-permission-token-lock": "Failed to obtain permission token lock",
"failed-to-obtain-auth-token-lock": "Failed to obtain auth token lock",
"provider-call-failed-for-method": "Provider call failed for method {{ method }} with params {{ params }}",
"failed-to-call-provider": "Provider call failed for method {{ method }} with params {{ params }}",
"failed-to-obtain-local-address": "Failed to obtain local address",
"failed-to-start-tapplet-server": "Failed to start tapplet server",
"tapplet-server-already-running": "Tapplet server already running",
Expand Down
2 changes: 1 addition & 1 deletion locales/pl/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"failed-to-find-tapplet-version": "Nie udało się znaleźć wersji tapplet'u",
"failed-to-obtain-permission-token-lock": "Nie udało się uzyskać blokady tokena uprawnień",
"failed-to-obtain-auth-token-lock": "Nie udało się uzyskać blokady tokena autoryzacji",
"provider-call-failed-for-method": "Wywołanie provider'a nie powiodło się dla metody {{ method }} z parametrami {{ params }}",
"failed-to-call-provider": "Wywołanie provider'a nie powiodło się dla metody {{ method }} z parametrami {{ params }}",
"failed-to-obtain-local-address": "Nie udało się uzyskać lokalnego adresu",
"failed-to-start-tapplet-server": "Nie udało się uruchomić serwera tapplet'u",
"tapplet-server-already-running": "Serwer tapplet'u już działa",
Expand Down
29 changes: 19 additions & 10 deletions src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ use crate::{
},
download_utils::{ download_file_with_retries, extract },
error::{
Error::{ self, FailedToObtainPermissionTokenLock, JsonParsingError, RequestError, TappletServerError },
Error::{ self, IOError, FailedToObtainPermissionTokenLock, JsonParsingError, RequestError, TappletServerError },
IOError::*,
RequestError::*,
TappletServerError::*,
},
Expand Down Expand Up @@ -110,13 +111,17 @@ pub async fn call_wallet(
) -> Result<serde_json::Value, Error> {
let permission_token = tokens.permission
.lock()
.inspect_err(|e| error!(target: LOG_TARGET, "❌ Error at call_wallet: {:?}", e))
.map_err(|_| FailedToObtainPermissionTokenLock)?
.clone();
let req_params: serde_json::Value = serde_json::from_str(&params).map_err(|e| JsonParsingError(e))?;

let req_params: serde_json::Value = serde_json
::from_str(&params)
.inspect_err(|e| error!(target: LOG_TARGET, "❌ Error at call_wallet: {:?}", e))
.map_err(|e| JsonParsingError(e))?;
match make_request(Some(permission_token), method, req_params).await {
Ok(res) => Ok(res),
Err(e) => {
error!(target: LOG_TARGET,"❌ Error at call_wallet: {:?}", e);
return Err(Error::RequestFailed { message: e.to_string() });
}
}
Expand All @@ -143,14 +148,16 @@ pub async fn launch_tapplet(

// Extract the tapplet archieve each time before launching
// This way make sure that local files have not been replaced and are not malicious
let _ = extract(&file_path, &tapplet_path.clone()).await;
let _ = extract(&file_path, &tapplet_path.clone()).await
.inspect_err(|e| error!(target: LOG_TARGET, "❌ Error extracting file: {:?}", e))
.map_err(|_| { IOError(FailedToUnpackFile { path: tapplet_path.to_string_lossy().to_string() }) })?;
//TODO should compare integrity field with the one stored in db or from github manifest?
match check_files_and_validate_checksum(tapp_version, tapplet_path.clone()) {
Ok(is_valid) => {
info!(target: LOG_TARGET,"Checksum validated without error. Is valid?: {:?}", is_valid);
info!(target: LOG_TARGET,"Checksum validation successfully with test result: {:?}", is_valid);
}
Err(e) => {
error!(target: LOG_TARGET,"Error validating checksum: {:?}", e);
error!(target: LOG_TARGET,"Error validating checksum: {:?}", e);
return Err(e.into());
}
}
Expand Down Expand Up @@ -228,14 +235,16 @@ pub async fn download_and_extract_tapp(
});
handle.await?.map_err(|_| Error::RequestError(FailedToDownload { url: tapp_version.registry_url.clone() }))?;

let _ = extract(&file_path, &tapplet_path.clone()).await;
let _ = extract(&file_path, &tapplet_path.clone()).await.inspect_err(
|e| error!(target: LOG_TARGET, "❌ Error extracting file: {:?}", e)
);
//TODO should compare integrity field with the one stored in db or from github manifest?
match check_files_and_validate_checksum(tapp_version, tapplet_path.clone()) {
Ok(is_valid) => {
info!(target: LOG_TARGET,"Checksum validated without error. Is valid?: {:?}", is_valid);
info!(target: LOG_TARGET,"Checksum validation successfully with test result: {:?}", is_valid);
}
Err(e) => {
error!(target: LOG_TARGET,"Error validating checksum: {:?}", e);
error!(target: LOG_TARGET,"🚨 Error validating checksum: {:?}", e);
return Err(e.into());
}
}
Expand Down Expand Up @@ -460,6 +469,6 @@ pub fn delete_dev_tapplet(dev_tapplet_id: i32, db_connection: State<'_, Database
pub fn open_log_dir(app_handle: tauri::AppHandle) {
let log_dir = app_handle.path().app_log_dir().expect("Could not get log dir");
if let Err(e) = open::that(log_dir) {
error!(target: LOG_TARGET, "Could not open log dir: {:?}", e);
error!(target: LOG_TARGET, "Could not open log dir: {:?}", e);
}
}
3 changes: 3 additions & 0 deletions src-tauri/src/download_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use tokio::fs::{ File, OpenOptions };
use tokio::io::{ AsyncWriteExt, BufReader };
use tokio::time::sleep;
use tokio_util::compat::{ TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt };
use log::error;

use crate::progress_tracker::ProgressTracker;

Expand Down Expand Up @@ -99,10 +100,12 @@ pub async fn extract(file_path: &Path, dest_dir: &Path) -> Result<(), anyhow::Er
extract_zip(file_path, dest_dir).await?;
}
_ => {
error!(target: LOG_TARGET, "❌ Extract file error: Unsupported file extension",);
return Err(anyhow::anyhow!("Unsupported file extension"));
}
}
None => {
error!(target: LOG_TARGET, "❌ Extract file error: File has no extension",);
return Err(anyhow::anyhow!("File has no extension"));
}
}
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub enum Error {
#[error("failed-to-find-tapplet-version")] VersionNotFound,
#[error("failed-to-obtain-permission-token-lock")] FailedToObtainPermissionTokenLock,
#[error("failed-to-obtain-auth-token-lock")] FailedToObtainAuthTokenLock,
#[error("provider-call-failed-for-method | method-{method} & params-{params}")] ProviderError {
#[error("failed-to-call-provider | method-{method} & params-{params}")] ProviderError {
method: String,
params: String,
},
Expand Down
7 changes: 3 additions & 4 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ async fn try_get_tokens() -> (String, String) {
loop {
match permission_token().await {
Ok(tokens) => {
info!(target: LOG_TARGET, "permission token ok {:?}", tokens);
info!(target: LOG_TARGET, "✅ WALLET DAEMON permission token found: {:?}", tokens);
return tokens;
}
Err(e) => {
warn!(target: LOG_TARGET, "permission token ERR {:?}", e);
warn!(target: LOG_TARGET, "❌ Wallet Daemon permission token error: {:?}", e);
sleep(Duration::from_millis(500));
continue;
}
Expand Down Expand Up @@ -105,7 +105,6 @@ fn setup_tari_universe(app: &mut tauri::App) -> Result<(), Box<dyn std::error::E
let tokens = app.state::<Tokens>();
let handle = tauri::async_runtime::spawn(try_get_tokens());
let (permission_token, auth_token) = tauri::async_runtime::block_on(handle)?;
info!(target: LOG_TARGET, "permission token found {:?}", permission_token);
tokens.permission
.lock()
.map_err(|_| error::Error::FailedToObtainPermissionTokenLock)?
Expand All @@ -121,7 +120,7 @@ fn setup_tari_universe(app: &mut tauri::App) -> Result<(), Box<dyn std::error::E
let handle_start = tauri::async_runtime::spawn(async move { start(tapplet_assets_path).await });
let (addr, cancel_token) = tauri::async_runtime::block_on(handle_start)?.unwrap();
app.manage(AssetServer { addr, cancel_token });
info!(target: LOG_TARGET, "Tari Universe setup completed successfully");
info!(target: LOG_TARGET, "🚀 Tari Universe setup completed successfully");

Ok(())
}
Expand Down
8 changes: 4 additions & 4 deletions src-tauri/src/progress_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,28 +64,28 @@ impl ProgressTrackerInner {
}

pub fn update(&self, title: String, title_params: Option<HashMap<String, String>>, progress: u64) {
debug!(target: LOG_TARGET, "Progress: {}% {}", progress, title);
debug!(target: LOG_TARGET, "⏳️️ Progress: {}% {}", progress, title);
self.window
.emit("message", SetupStatusEvent {
event_type: "download_status".to_string(),
title,
title_params,
progress: progress as f64,
})
.inspect_err(|e| error!(target: LOG_TARGET, "Could not emit event 'message': {:?}", e))
.inspect_err(|e| error!(target: LOG_TARGET, "Could not emit event 'message': {:?}", e))
.ok();
}

pub fn update_with_next_max(&self, title: String, title_params: Option<HashMap<String, String>>, progress: u64) {
debug!(target: LOG_TARGET, "Progress: {}% {}", progress, title);
debug!(target: LOG_TARGET, "⏳️️ Progress: {}% {}", progress, title);
self.window
.emit("message", SetupStatusEvent {
event_type: "setup_status".to_string(),
title,
title_params,
progress: ((self.min as f64) + ((self.next_max - self.min) as f64) * ((progress as f64) / 100.0)) / 100.0,
})
.inspect_err(|e| error!(target: LOG_TARGET, "Could not emit event 'message': {:?}", e))
.inspect_err(|e| error!(target: LOG_TARGET, "Could not emit event 'message': {:?}", e))
.ok();
}
}
16 changes: 11 additions & 5 deletions src-tauri/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ use tari_wallet_daemon_client::{
ComponentAddressOrName,
};
use tauri_plugin_http::reqwest::{ self, header::{ AUTHORIZATION, CONTENT_TYPE } };

use log::{ error, info };
use crate::error::Error;

const JSON_CONNECT_ADDRESS: &str = "127.0.0.1:18010"; // TODO use db to get endpoint
const LOG_TARGET: &str = "tari::dan::wallet_daemon";

pub async fn permission_token() -> Result<(String, String), anyhow::Error> {
let req_params = AuthLoginRequest {
Expand Down Expand Up @@ -48,8 +49,7 @@ pub async fn account_create(account_name: Option<String>, permissions_token: Str
key_id: None,
max_fee: None,
};
let resp = make_request(Some(permissions_token), "accounts.create".to_string(), create_acc_params).await?;

let _resp = make_request(Some(permissions_token), "accounts.create".to_string(), create_acc_params).await?;
Ok(())
}

Expand Down Expand Up @@ -109,7 +109,13 @@ pub async fn make_request<T: Serialize>(
}
let resp = builder.json(&body).send().await?.json::<JsonRpcResponse>().await?;
match resp.result {
JsonRpcAnswer::Result(result) => Ok(result),
JsonRpcAnswer::Error(error) => Err(anyhow::Error::msg(error.to_string())),
JsonRpcAnswer::Result(result) => {
info!(target: LOG_TARGET, "👁️‍🗨️ JSON rpc request result: {:?}", result);
Ok(result)
}
JsonRpcAnswer::Error(error) => {
error!(target: LOG_TARGET, "🚨 JSON rpc request error: {:?}", error);
Err(anyhow::Error::msg(error.to_string()))
}
}
}
6 changes: 3 additions & 3 deletions src-tauri/src/tapplet_installer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub fn get_tapp_download_path(
.path()
.app_data_dir()
.unwrap_or_else(|e| {
error!(target: LOG_TARGET, "Failed to get app dir: {}", e);
error!(target: LOG_TARGET, "Failed to get app dir: {}", e);
PathBuf::from("")
})
.to_path_buf();
Expand Down Expand Up @@ -84,9 +84,9 @@ async fn download_file(url: &str, dest: PathBuf) -> Result<(), Error> {
file.write_all(&chunk).map_err(|_| IOError(FailedToWriteFile { path: path.clone() }))?;
}
} else if response.status().is_server_error() {
println!("Download server error! Status: {:?}", response.status());
error!(target: LOG_TARGET, "❌ Download server error! Status: {:?}", response.status());
} else {
println!("Download failed. Something else happened. Status: {:?}", response);
error!(target: LOG_TARGET, "❌ Download failed! Unknown status. Server response: {:?}", response);
}

Ok(())
Expand Down
7 changes: 5 additions & 2 deletions src-tauri/src/tapplet_server.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use axum::Router;
use log::info;
use log::{ error, info };
use std::{ net::SocketAddr, path::PathBuf };
use tokio::select;
use tokio_util::sync::CancellationToken;
Expand All @@ -24,17 +24,20 @@ pub async fn serve(app: Router, port: u16) -> Result<(String, CancellationToken)
let addr = SocketAddr::from(([127, 0, 0, 1], port));
let listener = tokio::net::TcpListener
::bind(addr).await
.inspect_err(|e| error!(target: LOG_TARGET, "❌ Failed to bind port server error: {:?}", e))
.map_err(|_| TappletServerError(BindPortError { port: addr.to_string() }))?;
let address = listener
.local_addr()
.inspect_err(|e| error!(target: LOG_TARGET, "❌ Failed to obtain local address error: {:?}", e))
.map_err(|_| TappletServerError(FailedToObtainLocalAddress))?
.to_string();

tauri::async_runtime::spawn(async move { axum
::serve(listener, app)
.with_graceful_shutdown(shutdown_signal(cancel_token_clone)).await
.inspect_err(|e| error!(target: LOG_TARGET, "❌ Failed to start server error: {:?}", e))
.map_err(|_| TappletServerError(FailedToStart)) });
info!(target: LOG_TARGET, "Tapplet start process completed successfully");
info!(target: LOG_TARGET, "🚀 Tapplet start process completed successfully");

Ok((address, cancel_token))
}
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/wallet_daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub async fn start_wallet_daemon(
let shutdown = Shutdown::new();
let shutdown_signal = shutdown.to_signal();

info!(target: LOG_TARGET, "Wallet daemon configuration completed successfully");
info!(target: LOG_TARGET, "🚀 Wallet daemon configuration completed successfully");

run_tari_dan_wallet_daemon(config, shutdown_signal).await
}
38 changes: 25 additions & 13 deletions src/components/ErrorSnackBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,35 @@ import React from "react"
import { Language } from "../i18initializer"

const ERROR_KEY_SEPARATOR = "|"
const ERROR_CONTEXT_VAULE_SEPARATOR = "&"

export const resolveBackendErrorMessage = (
translator: TFunction<"errors", undefined>,
error: string,
lng: Language
) => {
const [translationKey, context] = error.split(ERROR_KEY_SEPARATOR)
const contextValues: Record<string, string> = context
.split(ERROR_CONTEXT_VAULE_SEPARATOR)
.reduce<Record<string, string>>((acc, item) => {
const [key, value] = item.split("-")
acc[key.trim()] = value.trim()
return acc
}, {})

return translator(translationKey.trim(), { ...contextValues, lng })
): string => {
const parts = error.split(ERROR_KEY_SEPARATOR)

if (parts.length < 2) {
return translator(error.trim(), { lng })
}

// Extract the nested error name
const nestedErrorPart = parts[1].trim() // Get the second part
const translationKey = nestedErrorPart.split("-").slice(1).join("-") // Extract everything after 'message-'

// Extract the method and params from the remaining part
const context = parts.slice(2).join(ERROR_KEY_SEPARATOR) // Join the remaining parts back
const methodMatch = context.match(/method-([a-zA-Z0-9._]+)/)
const paramsMatch = context.match(/params-(.*)/)

const method = methodMatch ? methodMatch[1] : "unknown method"
const params = paramsMatch ? JSON.parse(paramsMatch[1]) : {}

const formattedParams = JSON.stringify(params, null, 2)
.replace(/"([^"]+)":/g, "$1:") // Remove quotes from keys
.replace(/"([^"]+)"/g, "$1") // Remove quotes from string value

return translator(translationKey.trim(), { method, params: formattedParams, lng })
}

export const ErrorSnackBar = () => {
Expand All @@ -42,7 +54,7 @@ export const ErrorSnackBar = () => {
if (message && message.includes(ERROR_KEY_SEPARATOR)) {
return resolveBackendErrorMessage(t, message, currentLanguage)
}
return message
return t(message)
}, [message, currentLanguage])

return (
Expand Down
7 changes: 6 additions & 1 deletion src/components/TransactionConfirmationModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ import { BalanceUpdateView } from "./BalanceUpdate"
import { useTranslation } from "react-i18next"
import { ErrorSource } from "../store/error/error.types"
import { CallFunction, CallMethod } from "@tari-project/tarijs/dist/builders/types/Instruction"
import { resolveBackendErrorMessage } from "./ErrorSnackBar"
import { metadataSelector } from "../store/metadata/metadata.selector"

const selectSimulationById = (state: RootState, id?: number) => (id ? simulationsSelectors.selectById(state, id) : null)

export const TransactionConfirmationModal: React.FC = () => {
const { t } = useTranslation(["components", "common"])
const transaction = useSelector(transactionSelector.getPendingTransaction)
const simulation = useSelector((state: RootState) => selectSimulationById(state, transaction?.id))
const currentLanguage = useSelector(metadataSelector.selectCurrentLanguage)

const dispatch = useDispatch()

const handleClose = async () => {
Expand Down Expand Up @@ -93,7 +97,8 @@ export const TransactionConfirmationModal: React.FC = () => {
</DialogContentText>
{simulation?.status == "failure" && (
<DialogContentText>
{t("simulation-error-msg", { ns: "components" })}: {simulation?.errorMsg}
{t("simulation-error-msg", { ns: "components" })}:{" "}
{resolveBackendErrorMessage(t, simulation?.errorMsg, currentLanguage)}
</DialogContentText>
)}
<DialogContentText>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Wallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export const Wallet: React.FC = () => {
</Typography>
<Box display="flex" flexDirection="column" gap={2} alignItems="center" py={4}>
<SelectAccount onSubmit={handleCreateAccount} accountsList={accountsList} />
<Paper variant="outlined" elevation={0} sx={{ padding: 1, borderRadius: 2, width: "50%" }}>
<Paper variant="outlined" elevation={0} sx={{ padding: 1, borderRadius: 2, width: "auto", minWidth: 200 }}>
<Stack direction="column" justifyContent="flex-end">
<Typography variant="caption" textAlign="left">{`Name: ${currentAccount?.account.name}`}</Typography>
<Typography variant="caption" textAlign="left">{`${t("address", {
Expand Down
1 change: 0 additions & 1 deletion src/store/provider/provider.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export const initializeAction = () => ({

handleMessage = async (event: MessageEvent<TransactionEvent>) => {
if (!event?.data?.args || !event?.data?.methodName) {
dispatch(errorActions.showError({ message: "no-data-in-event", errorSource: ErrorSource.FRONTEND }))
return
}
if (!event.source) {
Expand Down
1 change: 0 additions & 1 deletion src/store/transaction/transaction.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export type TUProviderMethod = Exclude<keyof TUInternalProvider, "runOne">

export type Transaction = {
methodName: TUProviderMethod
// args: any[]
args: SubmitTransactionRequest[]
id: number
submit: () => void
Expand Down

0 comments on commit 661beb9

Please sign in to comment.