需求背景
在flink中,我們使用druid datasource建立資料來源:
dataSource = DruidDataSourceFactory.createDataSource(prop);
現在我希望透過druid列印sql執行日誌。
參考https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_LogFilter
需要設定system properties。有兩種選擇:
- 提交任務jar包時,指定
-D
選項 - 在flink任務程式碼中,透過config.yaml檔案,指定不同環境下的日誌配置。
我選擇透過程式碼來控制,config.yaml檔案內容如下:
properties:
# 列印druid sql日誌。參考https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_LogFilter
druid:
log:
stmt:
executableSql: true
filters: log4j
接下來需要解析這個配置,然後set到system properties中。相關程式碼:
private static Configuration getYamlConfig(String fileName) throws Exception {
ClassLoader cl = ConfigHelper.class.getClassLoader();
try (InputStream is = cl.getResourceAsStream(fileName)) {
Yaml yaml = new Yaml(new Constructor(Configuration.class));
Configuration config = yaml.load(is);
return config;
}
}
public class SystemPropertiesHelper {
private static final Logger log = LoggerFactory.getLogger(SystemPropertiesHelper.class);
public static void setSystemProperties(Map<String, Object> yamlMap, String parentKey) {
for (Map.Entry<String, Object> entry : yamlMap.entrySet()) {
String key = parentKey.isEmpty() ? entry.getKey() : parentKey + "." + entry.getKey();
Object value = entry.getValue();
if (value instanceof Map) {
setSystemProperties((Map<String, Object>) value, key);
} else {
log.info("Set system property: {}={}", key, value.toString());
System.setProperty(key, value.toString());
}
}
}
}
接下來,我在main方法入口的地方,呼叫ystemPropertiesHelper.setSystemProperties(configuration.getProperties(), "");
設定系統屬性。
本地執行(flink local env)是可以的,能列印出flink執行日誌。但是把jar釋出到測試的flink叢集之後就不行了,死活日誌打不出來。
後來透過日誌發現,在job manager的log中確實設定成功了系統屬性
2024-07-25 06:46:27,900 INFO com.tide.util.SystemPropertiesHelper [] - Set system property: druid.log.stmt.executableSql=true
2024-07-25 06:46:27,901 INFO com.tide.util.SystemPropertiesHelper [] - Set system property: druid.filters=log4j
但是,task manager的log中並沒有進行相關設定。顯然,任務jar包主要
是由task manager執行的,druid datasource相關程式碼也是在運算元中呼叫的,肯定也是在task manager中執行的。
分析到這裡,關鍵點是理解在任務jar包執行過程中,job manager和task manager分別承擔的職責是什麼?
參考https://www.cnblogs.com/xing901022/p/14300093.html
1、job manager 會透過反射呼叫jar包的main方法,然後解析,生成StreamGraph。 因此,我們把setSystemProperties
操作放到main方法中執行,自然是在job manager jvm程序中執行
2、job manager把運算元排程到特定的task manager進行執行。
因此,要解決問題,必須在運算元的邏輯程式碼中執行。修改程式碼:
Configuration configuration = ConfigHelper.getConfig();
if (configuration.getProperties() != null) {
// 設定系統屬性。控制druid sql log的行為
SystemPropertiesHelper.setSystemProperties(configuration.getProperties(), "");
}
initDataSource();
就ok了。
擴充套件
使用druid 列印sql log,還需要在log4j新增配置:
<logger name="druid.sql.Statement" additivity="false">
<level value="DEBUG"></level>
<appender-ref ref="console"/>
<appender-ref ref="file"/>
</logger>