我的应用程序使用angular 7和spring boot 2运行。每次用户与应用程序交互(单击一些按钮或链接)时,我都需要在json文件中存储一些数据。json应该如下所示(只是一个示例):
[
"event": {
userid : 1
ipAddress : x.x.x.x
lastConnectionDateTime : ...,
action : "click on link 1"
},
"event": {
userid : 2
ipAddress : y.y.y.y
lastConnectionDateTime : ...,
action : "click on button THE_BUTTON"
},
...
]
>
使用异步调用webservice的角度拦截器手动执行此操作。然后,webservice将调用一个异步spring服务,该服务将数据追加到json文件中。使用这个解决方案,我将不得不擦除一周以上的数据,这感觉就像重新创建轮子一样。
使用log4j2或logback之类的日志库。在log4j2中,有一个JsonLayout,它可以帮助我使用“loggerfields”来实现这一点,该“loggerfields”包含一个“KeyValuePairs”列表来将自定义字段放入我的json中,但是我有三个问题:
>
使用该方法似乎会生成一个带有“message”字段的json,其中包含我的自定义值。如何将它们放在我的事件对象的根级别,就像我上面给出的示例一样?
提前谢谢你
关于你问题的这一部分:
我想在这个要点中,您是在询问如何将动态变量的值注入JSONLayout
的KeyValuePair
元素。答案是,您将使用类似于JSOLayout文档末尾示例中的查找-类似于
我让您回到上面--如果使用查找,数据将放在生成的JSON中它自己的键下。
有几种方法可以处理将其他日志事件与JSON事件分离的问题。我建议您考虑将标记与MarkerFilter一起使用,或者使用特殊名称创建记录器配置(我建议您仔细阅读log4j2手册中的体系结构页,以了解记录器名称是如何工作的)。例如,如果要创建一个具有特殊名称的记录器配置,可以执行如下操作:
private static final Logger JSON_EVENT_LOGGER = LogManager.getLogger("JSON_EVENT_LOGGER");
这将在您的配置中定义,如下所示(假设是XML配置):
<Logger name="JSON_EVENT_LOGGER" additivity="false">
...
</Logger>
我建议您阅读有关可加性属性的内容,以便您能够很好地理解为什么在这里将其设置为false。基本上,您不希望这些json日志事件转到任何父记录器的追加器。
下面是一个非常简单的示例,它使用第二种方法创建具有特殊名称的记录器配置:
首先,一个java类生成一些日志事件:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
public class SomeClass {
private static final Logger log = LogManager.getLogger();
private static final Logger JSON_EVENT_LOGGER = LogManager.getLogger("JSON_EVENT_LOGGER");
public static void main(String[] args){
ThreadContext.put("userid", "1");
ThreadContext.put("ipAddress", "127.0.0.1");
ThreadContext.put("lastConnectionDateTime", "...timestamp...");
ThreadContext.put("action", "click link 1");
JSON_EVENT_LOGGER.info("A JSON message uses the special logger");
log.info("A non-json message uses the normal logger");
}
}
现在是定义记录器和追加器的log4j2.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
<Console name="ConsoleJSON" target="SYSTEM_OUT">
<JsonLayout compact="false" eventEol="true" stacktraceAsString="true">
<KeyValuePair key="userid" value="$${ctx:userid}"/>
<KeyValuePair key="ipAddress" value="$${ctx:ipAddress}"/>
<KeyValuePair key="lastConnectionDateTime" value="$${ctx:lastConnectionDateTime}"/>
<KeyValuePair key="action" value="$${ctx:action}"/>
</JsonLayout>
</Console>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console"/>
</Root>
<Logger name="JSON_EVENT_LOGGER" level="ALL" additivity="false">
<Appenderref ref="ConsoleJSON"/>
</Logger>
</Loggers>
</Configuration>
当java类执行时,控制台中会生成以下日志:
{
"thread" : "main",
"level" : "INFO",
"loggerName" : "JSON_EVENT_LOGGER",
"message" : "A JSON message uses the special logger",
"endOfBatch" : false,
"loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
"instant" : {
"epochSecond" : 1576215690,
"nanoOfSecond" : 541000000
},
"threadId" : 1,
"threadPriority" : 5,
"userid" : "1",
"ipAddress" : "127.0.0.1",
"lastConnectionDateTime" : "...timestamp...",
"action" : "click link 1"
}
23:41:30.653 [main] INFO example.SomeClass - A non-json message uses the normal logger
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import org.apache.logging.log4j.ThreadContext;
public class SomeClass2 {
private static final Logger log = LogManager.getLogger();
private static final Marker JSON_EVENT = MarkerManager.getMarker("JSON_EVENT");
public static void main(String[] args){
ThreadContext.put("userid", "1");
ThreadContext.put("ipAddress", "127.0.0.1");
ThreadContext.put("lastConnectionDateTime", "...timestamp...");
ThreadContext.put("action", "click link 1");
log.info(JSON_EVENT, "A JSON message uses the special logger");
log.info("A non-json message uses the normal logger");
}
}
注意这里的区别--两种类型的消息都只有一个记录器对象,对记录器的一次调用包括标记
来指示它是一个JSON事件。
接下来是log4j2.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<MarkerFilter marker="JSON_EVENT" onMatch="DENY" onMismatch="NEUTRAL"/>
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
<Console name="ConsoleJSON" target="SYSTEM_OUT">
<MarkerFilter marker="JSON_EVENT" onMatch="ACCEPT" onMismatch="DENY"/>
<JsonLayout compact="false" eventEol="true" stacktraceAsString="true">
<KeyValuePair key="userid" value="$${ctx:userid}"/>
<KeyValuePair key="ipAddress" value="$${ctx:ipAddress}"/>
<KeyValuePair key="lastConnectionDateTime" value="$${ctx:lastConnectionDateTime}"/>
<KeyValuePair key="action" value="$${ctx:action}"/>
</JsonLayout>
</Console>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console"/>
<Appenderref ref="ConsoleJSON"/>
</Root>
</Loggers>
</Configuration>
再次注意这里的区别--有2个追加器,但只有一个记录器配置(root
)。根记录器指定两个追加器,然后追加器负责使用markerfilter
过滤事件。
最后,运行java代码的结果输出:
{
"thread" : "main",
"level" : "INFO",
"loggerName" : "example.SomeClass2",
"marker" : {
"name" : "JSON_EVENT"
},
"message" : "A JSON message uses the special logger",
"endOfBatch" : false,
"loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
"instant" : {
"epochSecond" : 1576275417,
"nanoOfSecond" : 684000000
},
"threadId" : 1,
"threadPriority" : 5,
"userid" : "1",
"ipAddress" : "127.0.0.1",
"lastConnectionDateTime" : "...timestamp...",
"action" : "click link 1"
}
16:16:57.756 [main] INFO example.SomeClass2 - A non-json message uses the normal logger
注意:我使用的是log4j2版本2.11.1,如果使用更新的版本,可能会看到不同的结果。当我在2.12.1中尝试这些相同的示例时,JSON输出非常不同。
问题内容: 我有以下json文件。我想知道我应该将json文件放在我的项目中的位置以及如何读取和存储它。 问题答案: 将该文件放入资产中 。 对于在Android Studio项目中创建的项目,您需要在主文件夹下创建资产文件夹。 将该文件读取为: 然后您可以简单地通过此函数读取此返回 有关JSON的更多详细信息,请参见 http://www.vogella.com/articles/Android
问题内容: 我有一个如下文件: 我正在尝试将其导入文件。为此,我将其添加到类型定义中: 我正在这样导入。 在文件中,我将颜色用作。但是我得到一个错误: 属性’primaryMain’在类型’typeof“ * .json”上不存在 问题答案: 导入表单和模块声明需要就模块的形状,导出的内容达成一致。 编写时(自TypeScript 2.9导入JSON时,针对兼容模块格式的一种次佳实践, 请参见no
问题内容: 我是React的新手,正在尝试从外部文件导入JSON 变量。我收到以下错误: 找不到模块“ ./customData.json” 有人可以帮我吗?如果我的变量位于外部JSON文件中,但没有该变量,则它可以工作。 index.js hobbies.js profile.js customData.json 问题答案: 一种不错的方法(不添加伪造的.js扩展名,用于代码而不用于数据和配置)
我想保存JSch日志文件,因为它不显示任何东西在控制台。 这是我的代码: 把jsch记录器放在哪里来获取文件中的一些信息。我试过了,但从来没有成功过: D
问题内容: 我正在尝试在React组件中加载language.json文件。当我想导入json文件时,第一步出现以下错误。这是错误: 我正在使用webpack,这是配置文件: 并且我已经安装了以下软件包: 这就是我尝试导入文件(ES6格式)的方式: 另外,我检查了json文件格式并进行了验证!那么,您认为问题出在哪里? 问题答案: azium是正确的,需要加载程序,但这是很好的配置: npm命令
和 因为该类在JDBC包中。那我就这么做 Edit2:因为我在控制台中获得的日志消息看起来与logback.xml中的日志消息不同,所以它看起来完全忽略了我的logback.xml。