手把手教你完成MaxCompute JDBC自定义日志配置

注:MaxCompute原名ODPS,是阿里云自研的大数据计算平台,文中出现的MaxCompute与ODPS都指代同一平台,不做区分

与MaxCompute JDBC相关的日志有两种,一种是由JDBC内部代码直接输出的日志,第二种是JDBC抛出异常后,由调用JDBC API的宿主应用捕获后输出的。由于第二类日志取决于宿主应用如何处理异常及如何配置日志体系,所以本文主要讨论的对象是第一种日志。

在2.0-beta之前,MaxCompute JDBC的日志只会输出到命令行终端(标准输出流),它底层使用的是JDK自带的 java.util.logging 的 ConsoleHandler。所以除非你是在命令行启动宿主应用的(相对的另一种方式是在可视化界面里双击可执行文件来启动宿主应用,并没有控制台界面),不然日志信息并不好找。这就给用户诊断问题和排查错误带来了不便。

为了让用户能自定义日志的相关配置,比如让用户自己来决定日志输出到终端还是文件、输出的日志文件应该放在哪里,又或者输出的日志文件如何做rotation等。MaxCompute JDBC 在 2.0-beta 中引入了slf4jlogback来让用户能自定义日志配置。为了避免JDBC选择的 slf4j 日志实现框架与宿主应用的 slf4j 日志实现框架产生冲突,MaxCompute JDBC的JAR包中并没有包含某个特定 slf4j 实现的JAR包。而与 logback 之间也不是强依赖的,只有当宿主应用不包含任何 slf4j 日志实现的时候,用户可以通过在classpath中加入 logback 的JAR包,并向JDBC传入logback的配置文件来启用该实现。

  • 为什么slf4j日志实现框架之间会产生冲突?

slf4j 是为了统一不同日志框架的行为和API而产生的一套日志门面框架,它只提供API,但并不提供具体的日志解决方案实现。所以通常需要配合另一种具体的日志实现框架一起使用,比如 logback 、 log4j 。而假设MaxCompute JDBC选择的是 slf4j +logback ,而宿主应用选择的是 slf4j + log4j ,那么运行时就会出现冲突。因为通常用户在编程时会调用 slf4j的LoggerFactory.getLogger来获取日志实例,而在该方法首次被调用时会绑定一个具体的 slf4j 的实现,该行为依赖一个叫做org.slf4j.impl.StaticLoggerBinder的类。而该类在所有 slf4j 的日志实现框架中都会存在,所以当多套 slf4j 日志实现同时存在于classpath的时候,完全依赖于运行时classloader先加载了哪套实现的org.slf4j.impl.StaticLoggerBinder,加载了谁就使用谁的实现以及配置,而这是带有不确定性的,这也是常见的一种JAR包冲突问题。所以如果MaxCompute JDBC带入了与宿主应用不同的 slf4j 日志实现,那么可能会造成宿主应用在运行时获取到另一套实现的日志实例,从而让宿主应用原有的日志配置失效。

据不完全归纳,我暂且将MaxCompute JDBC的用户大致分为两类,分别是取数者和开发者。

  • 取数者
    这类用户通常是某类数据查询或分析工具的使用者,他们需要在取数工具中添加MaxCompute的JDBC Driver,然后配置jdbc url等若干参数,从而利用该工具完成对MaxCompute的SQL查询。
  • 开发者
    这类用户通常是数据产品的开发者,他们通过调用SDK或JDBC的API来编写查询逻辑的相关代码,从而开发出适合目标用户使用的软件产品。

那么现在我将针对这两类用户分别讲讲如何完成自定义日志配置,然后再针对具体的配置做一下说明。如果你对MaxCompute JDBC还不熟悉,那么请在阅读以下内容前先看看这篇《使用 odps-jdbc 接入 ODPS,不再从零开始》

  1. 取数者

我打算继续以SQL Workbench/J作为例子进行讲解。

将 SQL Workbench/J 下载到本地后,你会得到一个可执行文件,双击后在弹出界面中点击 Manager Driver 加载我们的 JDBC jar 包。

此处请注意,由于 SQL Workbench/J 自身没有引入 slf4j 的任何日志实现,所以我们可以通过添加 logback 的jar包来启用MaxCompute JDBC默认的logback实现。

然后新建一个 Connection Profile 。请注意在 URL 部分填入的JDBC URL中较之前多了一个名为 log_conf_file的参数:

该参数可用于指定一个本地的 logback 配置文件作为用于MaxCompute JDBC的日志配置。请注意,该参数是一个指定配置文件的参数,而非指定日志输出位置的参数。所以请确保该参数对应的目录下该文件是存在且应用有权限访问的,并且配置文件需要符合logback配置文件的格式。如果不传递该参数,日志将只输出到控制台。而以之前双击方式打开的 SQL Workbench/J是没有控制台界面的。如果需要将日志输出到特定目录的日志文件中,只需在配置文件中为其添加相应的FileAppender即可。详见第3部分的配置说明。

这一段中提到的JAR包和配置文件请于此处下载:v2.0-beta

  1. 开发者

对于开发者而言,应该对Java的日志框架体系并不陌生,且所开发的应用可能已经使用了 slf4j 及其实现。所以首先需要明确这一点,如果已经使用了 slf4j 及其实现,那么就没有必要再使用JDBC自带的配置功能,可以直接在现有应用的log配置中添加对包com.aliyun.odps.jdbc的日志配置。

如果你没有使用任何的 slf4j 实现,那么请在添加MaxCompute JDBC的JAR包的同时,同时向你的classpath添加logback-core-1.1.7.jar和logback-classic-1.1.7.jar两个JAR包。如果你使用的是maven,可以添加如下依赖:

<dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.7</version>
</dependency>

你可以采用两种方式来指定配置文件,一种是直接将logback.xml放入classpath之中。

还有一种方式是以编程的方式,在如下的config中加入了 log_conf_file 属性的配置或是在jdbc URL串中带上 log_conf_file 参数来指定(见之前SQL Workbench/J的示例图)。当你同时在URL和config中配置该项时,以config的值作为优先项使用。

Properties config = new Properties();
config.put("access_id", "...");
config.put("access_key", "...");
config.put("project_name", "...");
config.put("charset", "...");
config.put("log_conf_file","/Users/emerson/logback.xml");
Connection conn = DriverManager.getConnection("jdbc:odps:<endpoint>", config);
  1. 配置说明

接着我们来看看 logback.xml 的内容:

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
     <!--*Linux or Windows:*-->
    <!--tries $HOME first; if it doesn‘t exist, it tries $USERPROFILE-->
    <file>${HOME:-${USERPROFILE}}/logs/odps.log</file>
    <encoder>
      <pattern>%date %level [%thread] %logger{10}  %X{connectionId} [%file:%line] %msg%n</pattern>
    </encoder>
  </appender>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>

<logger name="com.aliyun.odps.jdbc" level="debug"/>

  <root level="error">
    <appender-ref ref="FILE" />
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

这是一个满足基本常规需求的logback配置,如果你没有更多的特殊需求,可以直接复制该配置文件来使用。我将简单对该配置做一下介绍,如果你对logback的配置想要有更深入的了解,请查看官方文档的configuration章节。

其中<configuration>是配置文件的根标签,所有子标签必须包含在根标签之中。其中子标签分为<appender><encoder><logger> 和 <root>

Logback 的日志实例是有继承关系的。其中 <root> 就是所有日志实例的父实例,而其余 <logger> 都是子实例,默认都继承父实例的配置。而所有的 <logger> 又根据其 name 属性的前缀来继续维持继承关系,假设这段配置中定义了com.aliyun.odps 和 com.aliyun.odps.jdbc 两个日志实例,那后者就是前者的子实例。由于我们目前只有com.aliyun.odps.jdbc 这个包中有输出日志的代码,所以我们只配置了一个日志实例,它覆盖了 <root> 的 error 日志级别,改为了 debug 级别。

其中日志的输出级别及其严重等级关系为:

TRACE < DEBUG < INFO < WARN < ERROR < OFF

即从左往右的严重等级依次递增,日志数量则依次递减。严重等级越小的日志级别将输出所有大于等于它级别的日志。举个例子,如果你选择DEBUG级别,那除TRACE之外的所有日志都将输出。其中OFF表示不输出日志。

其中的 <encoder> 用于将日志事件编码成字节流,它引用了 <pattern> ,<pattern>表明使用默认的PatternLayout ,其中<pattern>%date %level [%thread] %logger{10} %X{connectionId} [%file:%line] %msg%n</pattern> 中引用了很多PatternLayout 中内置的一些变量,用于分别输出日志的日期、级别、线程名、日志实例名、connectionId、类文件、行号、msg信息以及行分隔符。其中更多的内置变量请参阅官方的layouts文档。

这些变量中唯一需要你特别关注的是 %X{connectionId} ,这是一个通过 MDC 设置的每个JDBC Connection唯一的ID,用于标识来自于同一Connection的JDBC日志。

<appender>用于指定日志的输出目标,目前的示例中配置了 FILE 和 STDOUT 两个appender,表明分别将日志输出到文件和标准输出流,其中FILE的appender中又通过 <file> 指明了日志文件的存储路径。

最后我们可以看到日志实例会引用appender,而appender又会引用encoder,从而构造了整个日志配置的体系。

通过以上配置,我们可以在路径/Users/emerson/odps.log下(也就是你的home目录下,上述配置示例中针对Linux和windows的home目录做了兼容)得到格式如下的输出日志:

Logback 是一款相当强大的Java日志框架,你可以通过配置来获取像日志文件rotation、归档,甚至以JMS、邮件方式输出日志等功能。更多的功能请查阅官方文档来获取进一步了解。

欢迎加入MaxCompute钉钉群讨论

阅读原文请点击

时间: 2024-08-06 20:15:46

手把手教你完成MaxCompute JDBC自定义日志配置的相关文章

nginx日志格式及自定义日志配置

nginx的log日志分为access log 和 error log 其中access log 记录了哪些用户,哪些页面以及用户浏览器.ip和其他的访问信息 error log 则是记录服务器错误日志 错误日志的形式如下: 10.1.1.1 - - [22/Aug/2014:16:48:14 +0800] "POST /ajax/MbpRequest.do HTTP/1.1" 200 367 "-" "Dalvik/1.6.0 (Linux; U; An

手把手教你搭建LyncServer2013之部署及配置存档功能(十七)

存档服务器角色在 Lync Server 2013 中也已弃用,Lync Server 2013 存档服务现在并置在每台前端服务器上. Lync Server 2013 提供了一种解决方案,用于对  Lync Server 中的即时消息 (IM) 内容和会议通信进行存档.您可以通过将存档存储与  Exchange 2013 存储集成来实现存档支持,方法是使用  SQL Server 数据库用于存储  Lync Server 2013 存档数据,或者同时使用  Lync Server 2013 和

手把手教你搭建LyncServer2013之部署及配置监控功能(十八)

自弃用监控服务器角色以来,已对 Microsoft Lync Server 2013 监控基础结构进行了重大更改.不再采用不同的监控服务器角色(通常需要组织设置专用计算机来充当监控服务器),现在监控服务已并置到每台前端服务器中.除了其他优点外,此更改还有助于: 减少实现 Lync Server 2013 时所需的服务器角色数.在此情况下,减少监控服务器角色数还可帮助降低成本,因为无需维护用于监控的专用服务器. 降低 Lync Server 安装和管理的复杂性.通过自动在每台前端服务器上并置监控服

东方耀 手把手教React Native实战开发视频教程+源码笔记全集

课程序号标题 第0课0.手把手教React Native实战之开山篇_视频 第1课1.手把手教React Native实战之环境搭建_视频_Windows环境 第1课1.手把手教React Native实战之环境搭建[Mac真机]同时调试开发Android&IOS 第2课2.手把手教React Native实战之从React到RN 第3课3.手把手教React Native实战之flexbox布局(RN基础) 第4讲4.手把手教React Native实战之flexbox布局(伸缩属性) 第5讲

spring-logger spring中日志配置

默认日志 Logback:默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台.在运行应用程序和其他例子时,你应该已经看到很多INFO级别的日志了. 从上图可以看到,日志输出内容元素具体如下: 时间日期:精确到毫秒日志级别:ERROR, WARN, INFO, DEBUG or TRACE进程ID分隔符:— 标识实际日志的开始线程名:方括号括起来(可能会截断控制台输出)Logger名:通常使用源代码的类名日志内容添加日志依赖假如maven依赖中添加了spr

springboot profile 日志配置

1.简介 Spring Profiles提供了一种隔离应用程序配置部分并使其仅在特定环境中可用的方法. 任何@Component或@Configuration 可以标记@Profile以限制何时加载,如以下示例所示:(只有在profile设置为procduction的时候这个bean才会被加载) @Configuration @Profile("production") public class ProductionConfiguration { // ... } 可以使用spring

Android 自定义ViewGroup手把手教你实现ArcMenu

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37567907 逛eoe发现这样的UI效果,感觉很不错,后来知道github上有这么个开源项目~~~~当然本篇不是教你如何使用这个开源项目,而是教你如何自己通过自定义ViewGroup写这样的效果,自定义ViewGroup也是我的痛楚,嘿嘿,希望以此可以抛砖引玉~~ 效果图: 1.实现思路 通过效果图,会有几个问题: a.动画效果如何实现 可以看出动画是从顶点外外发射的,可能有人

Android 手把手教您自定义ViewGroup(一)

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38339817 , 本文出自:[张鸿洋的博客] 最近由于工作的变动,导致的博客的更新计划有点被打乱,希望可以尽快脉动回来~ 今天给大家带来一篇自定义ViewGroup的教程,说白了,就是教大家如何自定义ViewGroup,如果你对自定义ViewGroup还不是很了解,或者正想学习如何自定义,那么你可以好好看看这篇博客. 1.概述 在写代码之前,我必须得问几个问题: 1.ViewG

手把手教你用ViewPager自定义实现Banner轮播

手把手教你用ViewPager自定义实现Banner轮播 欢迎大家关注Android开源网络框架NoHttp:https://github.com/Y0LANDA/NoHttp 我们在实际开发中,很多App都会在做一个广告轮播器(可能是图片,可能是其他View),很多同学都是使用别人封装好的或者直接使用ViewPager自己来改,但是有人可能并不理解里面的原理,或者有人遇到了手势滑动冲突.我们今天就用150行代码实现一自定义的广告轮播器并不干扰原来View滑动事件. 本例代码源码及Demo传送门