Skip to content

Commit

Permalink
ui: add frontend logging service
Browse files Browse the repository at this point in the history
  • Loading branch information
laurenzhonauer committed Oct 27, 2021
1 parent 6dd8742 commit 03fc7fe
Show file tree
Hide file tree
Showing 17 changed files with 1,854 additions and 24,131 deletions.
6 changes: 6 additions & 0 deletions frontend/configureServer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,11 @@ INJECT_FILE_PATH="${WWW_DIR}/env.js"
sed -i 's/REACT_APP_EMAIL_SERVICE_ENABLED: "false"/REACT_APP_EMAIL_SERVICE_ENABLED: "'$REACT_APP_EMAIL_SERVICE_ENABLED'"/g' ${INJECT_FILE_PATH}
sed -i 's/REACT_APP_EXPORT_SERVICE_ENABLED: "false"/REACT_APP_EXPORT_SERVICE_ENABLED: "'$REACT_APP_EXPORT_SERVICE_ENABLED'"/g' ${INJECT_FILE_PATH}

sed -i 's/REACT_APP_LOGGING: "true"/REACT_APP_LOGGING: "'$REACT_APP_LOGGING'"/g' ${INJECT_FILE_PATH}
sed -i 's/REACT_APP_LOG_LEVEL: "trace"/REACT_APP_LOG_LEVEL: "'$REACT_APP_LOG_LEVEL'"/g' ${INJECT_FILE_PATH}
sed -i 's/REACT_APP_LOGGING_SERVICE_HOST: "localhost"/REACT_APP_LOGGING_SERVICE_HOST: "'$REACT_APP_LOGGING_SERVICE_HOST'"/g' ${INJECT_FILE_PATH}
sed -i 's/REACT_APP_LOGGING_SERVICE_PORT: "3001"/REACT_APP_LOGGING_SERVICE_PORT: "'$REACT_APP_LOGGING_SERVICE_PORT'"/g' ${INJECT_FILE_PATH}
sed -i 's/REACT_APP_LOGGING_SERVICE_HOST_SSL: "false"/REACT_APP_LOGGING_SERVICE_HOST_SSL: "'$REACT_APP_LOGGING_SERVICE_HOST_SSL'"/g' ${INJECT_FILE_PATH}

nginx -g "daemon off;"

23,810 changes: 45 additions & 23,765 deletions frontend/package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "trubudget-frontend",
"version": "1.26.0",
"version": "1.26.0",
"private": true,
"repository": {
"type": "git",
Expand Down Expand Up @@ -53,7 +53,9 @@
"redux": "^3.6.0",
"redux-debounced": "^0.4.0",
"redux-immutable": "^4.0.0",
"redux-saga": "^1.0.2"
"redux-logger": "^3.0.6",
"redux-saga": "^1.0.2",
"seamless-immutable": "^7.1.4"
},
"devDependencies": {
"@babel/register": "^7.4.4",
Expand Down
8 changes: 7 additions & 1 deletion frontend/public/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@ window.injectedEnv = {
// Per default, do not request health from email-service
REACT_APP_EMAIL_SERVICE_ENABLED: "false",
// Per default, do not request health from excel-export-service
REACT_APP_EXPORT_SERVICE_ENABLED: "false"
REACT_APP_EXPORT_SERVICE_ENABLED: "false",
// Per default, do not send log messages to log-server
REACT_APP_LOGGING: "false",
REACT_APP_LOG_LEVEL: "trace",
REACT_APP_LOGGING_SERVICE_HOST: "localhost",
REACT_APP_LOGGING_SERVICE_PORT: "3001",
REACT_APP_LOGGING_SERVICE_HOST_SSL: "false"
};
28 changes: 13 additions & 15 deletions frontend/src/index.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
import amber from "@material-ui/core/colors/amber";
import red from "@material-ui/core/colors/deepOrange";
import grey from "@material-ui/core/colors/grey";
import blue from "@material-ui/core/colors/indigo";
import { createMuiTheme, MuiThemeProvider } from "@material-ui/core/styles";
import { ConnectedRouter } from "connected-react-router/immutable";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import { createBrowserHistory } from "history";
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { ConnectedRouter } from "connected-react-router/immutable";
import { Route, Switch, withRouter } from "react-router";
import { MuiThemeProvider, createMuiTheme } from "@material-ui/core/styles";
import { createBrowserHistory } from "history";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";

import red from "@material-ui/core/colors/deepOrange";
import blue from "@material-ui/core/colors/indigo";
import grey from "@material-ui/core/colors/grey";
import amber from "@material-ui/core/colors/amber";

import Main from "./pages/Main/Main";
import "./logging/console";
import withInitialLoading from "./pages/Loading/withInitialLoading";
import LoginPageContainer from "./pages/Login/LoginPageContainer";
import PrivateRoute from "./pages/Login/PrivateRoute";
import Main from "./pages/Main/Main";
import LiveNotificationContainer from "./pages/Notifications/LiveNotificationContainer";

import configureStore from "./store";
import withInitialLoading from "./pages/Loading/withInitialLoading";

// setup dayjs
// if you need to add time to your charts you have to add a dayjs adapter
Expand All @@ -28,7 +26,7 @@ dayjs.extend(relativeTime);

const history = createBrowserHistory();

const store = configureStore(history);
export const store = configureStore(history);

const muiTheme = createMuiTheme({
palette: {
Expand Down
35 changes: 35 additions & 0 deletions frontend/src/logging/console.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* eslint-disable space-before-function-paren */
/* eslint-disable no-console */
import { createLogMsg } from "./logger";
(() => {
const _log = console.log;
const _error = console.error;
const _warning = console.warning;

console.error = function(errMessage) {
_error.apply(console, arguments);
createLogMsg({
service: "FRONTEND",
what: "Error",
why: errMessage
});
};

console.log = function(logMessage) {
_log.apply(console, arguments);
createLogMsg({
service: "FRONTEND",
what: "Log",
why: logMessage
});
};

console.warning = function(warnMessage) {
createLogMsg({
service: "FRONTEND",
what: "Error",
why: warnMessage
});
_warning.apply(console, arguments);
};
})();
98 changes: 98 additions & 0 deletions frontend/src/logging/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import axios from "axios";
import { createLogger } from "redux-logger";
import { store } from "./../index";
const {
NODE_ENV,
REACT_APP_LOGGING,
REACT_APP_LOG_LEVEL,
REACT_APP_LOGGING_SERVICE_HOST,
REACT_APP_LOGGING_SERVICE_PORT,
REACT_APP_LOGGING_SERVICE_HOST_SSL
} = process.env;

let instance = undefined;
const logMessages = [];
const getToken = () => (store ? store.getState().toJS().login.jwt : "");
const getUserId = () => (store ? store.getState().toJS().login.id : "");

const createConnection = () => {
if (REACT_APP_LOGGING === false) return;
// SSL musst be enabled when using logger in production
if (NODE_ENV !== "developement" && REACT_APP_LOGGING_SERVICE_HOST_SSL === "false" && REACT_APP_LOGGING === "true") {
// eslint-disable-next-line no-console
console.error(
"Seems you are using TruBudget in production with logging enabled but without SSL! Enable SSL for Frontend-Logging to proceed!"
);
}
// Build url
instance = axios.create();
instance.defaults.baseURL = `${
REACT_APP_LOGGING_SERVICE_HOST_SSL ? "http://" : "https://"
}${REACT_APP_LOGGING_SERVICE_HOST}:${REACT_APP_LOGGING_SERVICE_PORT}`;

setInterval(pushLogToServer, 1000 * 10);
};

const setToken = () => {
let t = getToken();
instance.defaults.headers.common["Authorization"] = t ? `Bearer ${t}` : "";
};

const logger = createLogger({
timestamp: true,
logErrors: true,
predicate: (getState, action) => predicate(getState, action),
stateTransformer: s => stateTransformer(s),
diff: true,
errorTransformer: error => errorTransformer(error)
});
const stateTransformer = s => s;

const predicate = (getState, action) => {
createLogMsg({
service: "FRONTEND",
what: "Trace",
why: {
action: action,
prevState: stateTransformer(getState())
}
});
//In trace mode print to console
if (REACT_APP_LOG_LEVEL === "trace" && REACT_APP_LOGGING === "true") return true;
return false;
};

const errorTransformer = error => {
createLogMsg({
service: "FRONTEND",
what: "Error",
why: error
});
return error;
};
const pushLogToServer = async () => {
if (instance && logMessages.length > 0) {
if (
instance.defaults.headers.common["Authorization"] === "" ||
instance.defaults.headers.common["Authorization"] === undefined
)
setToken();
await instance.post("/api", { logMessages: logMessages }).catch(ignore => ignore);
while (logMessages.length) {
logMessages.pop();
}
}
};

export const createLogMsg = async log => {
if (REACT_APP_LOGGING === "false") return;
const msg = {
...log,
when: new Date().toString(),
who: getUserId()
};
logMessages.push(msg);
};

createConnection();
export default logger;
12 changes: 6 additions & 6 deletions frontend/src/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
* Create the store with asynchronously loaded reducers
*/

import { createStore, applyMiddleware, compose } from "redux";
import { fromJS } from "immutable";
import { routerMiddleware } from "connected-react-router";
import createSagaMiddleware from "redux-saga";
import { fromJS } from "immutable";
import { applyMiddleware, compose, createStore } from "redux";
import createDebounce from "redux-debounced";

import createSagaMiddleware from "redux-saga";
import { loadState, persistState } from "./localStorage";
import reduxLogger from "./logging/logger";
import createReducer from "./reducers";
import rootSaga from "./sagas";
import { loadState, persistState } from "./localStorage";

const sagaMiddleware = createSagaMiddleware();

export default function configureStore(history) {
// Create the store with two middlewares
// 1. sagaMiddleware: Makes redux-sagas work
// 2. routerMiddleware: Syncs the location/URL path to the state
const middlewares = [sagaMiddleware, createDebounce(), routerMiddleware(history)];
const middlewares = [sagaMiddleware, createDebounce(), routerMiddleware(history), reduxLogger];

const enhancers = [applyMiddleware(...middlewares)];

Expand Down
5 changes: 5 additions & 0 deletions logging-service/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
LOGGER_PORT=3001
API_HOST=localhost
API_PORT=8080
LOG_LEVEL=trace
NODE_ENV=development
Loading

0 comments on commit 03fc7fe

Please sign in to comment.