FND Debug Log(FND_LOG_MESSAGES)

优化FND日志收集与管理
本文指导如何通过配置FNDDebugLogLevel等参数优化日志收集,利用FND_LOG_MESSAGES表集中管理日志,以及如何高效清理和利用日志进行问题定位。包括设置日志级别、重现问题、查询特定日志、清理过期日志等内容。

之前每个模块记录日志的方式都不同,都会把日志写到不同的文件中,对于User来说很麻烦,需要记住很多的配置,现在越来越多的模块使用FND Logging来存储日志,比如WIP,RCV,OAF...FND Debug Log会把Apps的日志输出到FND_LOG_MESSAGES表里。

怎样收集FND的日志

Step 1 profile设置(user级)
FND: Debug Log Level,这个level,可以设置为Unexpected,Error,Exception,Event,Procedure或者Statement,一般情况下设置Log Level为"Statement" level。

FND: Debug Log Enabled 设置为Yes

FND: Debug Log Module
设置为 %,如果你大概知道你的问题是那个模块下的问题,你可以设置这个profile为po%,hr%,fnd%,WIP%...这样收集的日志会更少,也更容易分析。

补充:设置为statement的好处,它会记录所有的日志,如果你只想查看Error的日志,那么你可以在查询语句中限定log_level=5,那么只会输出error级别的日志。

UNEXPECTED:Level Id = 6
ERROR :Level Id = 5
EXCEPTION :Level Id = 4
EVENT :Level Id = 3
PROCEDURE :Level Id = 2
STATEMENT :Level Id = 1

Step 2 重现你的问题

Step 3 从fnd_lot_messages表中收集日志

SELECT *
FROM fnd_log_messages
WHERE user_id = 209122 /*your FND_USER user_id here*/
AND TIMESTAMP > SYSDATE - .3
ORDER BY log_sequence

注意:如果你要收集Concurrent Request的日志,可以用下边的SQL查fnd的日志

select module, to_char(timestamp,'DD-MON-YYYY HH24:MI:SS'), message_text
from fnd_log_messages
where timestamp > sysdate - 2/24
and process_id = ( select os_process_id from fnd_concurrent_requests where request_id = &request_id)
and module like 'po%'


什么样的日志会记录到fnd_log_messages表中

使用fnd_log.STRING(log_level => fnd_log.level_statement,module => 'xxpo.packagename.procedurename',message => 'debug message here');记录的日志,在会在fnd_log_messages表中才能查到。到现在为止还有很多模块不是用fnd_log.STRING的方式来记录日志,还在使用utl_file.put_line来写日志到一个文件,比如inv模块。


如果业务回滚了,那么记录到fnd_log_messages表中的日志是否也会回滚

不会,fnd_log.string调用的procedure定义为pragma AUTONOMOUS_TRANSACTION (自治事务)里边有commit.所以日志不会被回滚掉。


清理fnd_log_messages表

fnd_log_messages表如果太大,肯定会影响性能,所以最好定期清理这张表,Oracle官方提供了一个program去清理这张表。11i这个program叫"Purge Debug Log and System Alerts",R12里改名字了,叫"Purge Logs and Closed System Alerts",需要在system admin职责下运行,这个program默认是scheduled to run daily,并清理7天前的log数据。program会清理以下这些表:
FND_EXCEPTION_NOTES;
FND_OAM_BIZEX_SENT_NOTIF;
FND_LOG_METRICS;
FND_LOG_UNIQUE_EXCEPTIONS;
FND_LOG_EXCEPTIONS;
FND_LOG_MESSAGES;
FND_LOG_TRANSACTION_CONTEXT;
FND_LOG_ATTACHMENTS
这些表都是包含debug或者error信息。

转载请注明出处:http://blog.youkuaiyun.com/pan_tian/article/details/7688987

====EOF====


openguass数据库 DO LANGUAGE plpgsql $$ DECLARE V_SP_NAME nvarchar2 (100) := '002_truncateTables_dml.sql'; V_LOG_PARAMS FND_LOG_PARAMS_TYP; V_ERROR_MSG nvarchar2 (3000); V_IS_OK BOOL; V_CNT NUMERIC; V_ROW_COUNT NUMERIC; V_SQL TEXT := ''; V_CUR RECORD; v_table INT4; -- 表操作相关变量 table_names TEXT [] := ARRAY[ 'demo_copy1', 'demo_copy11' ]; -- 替换为目标表名列表 full_table_name TEXT; table_part TEXT; table_exists BOOLEAN; BEGIN V_IS_OK := TRUE; BEGIN V_LOG_PARAMS := FND_INIT_LOG_PARAM_F (V_SP_NAME, '1', '1', 1); V_LOG_PARAMS.STEP_START_TIME := CLOCK_TIMESTAMP(); V_LOG_PARAMS.PROCESS_STEP_ID := V_LOG_PARAMS.PROCESS_STEP_ID + 1; V_LOG_PARAMS.LOG_MESSAGE := V_SP_NAME || ' begin'; PERFORM FND_START_LOG_P (V_LOG_PARAMS); SET app.current_tenant = 113704385416306; FOREACH full_table_name IN ARRAY table_names LOOP BEGIN -- 分离模式名和表名 SELECT current_schema() INTO schema_part; table_part := full_table_name; -- 检查表是否存在(使用 pg_catalog 优化性能) SELECT EXISTS (SELECT 1 FROM pg_catalog.pg_tables WHERE schemaname = schema_part AND tablename = table_part) INTO table_exists; -- 存在则清空 IF table_exists THEN EXECUTE FORMAT ('TRUNCATE TABLE %I.%I', schema_part, table_part); -- 记录操作日志 V_LOG_PARAMS.PROCESS_STEP_ID := V_LOG_PARAMS.PROCESS_STEP_ID + 1; V_LOG_PARAMS.LOG_MESSAGE := '表 ' || full_table_name || ' 已清空'; PERFORM FND_STEP_LOG_P (V_LOG_PARAMS, 2); ELSE -- 记录跳过日志 V_LOG_PARAMS.PROCESS_STEP_ID := V_LOG_PARAMS.PROCESS_STEP_ID + 1; V_LOG_PARAMS.LOG_MESSAGE := '表 ' || full_table_name || ' 不存在,跳过'; PERFORM FND_STEP_LOG_P (V_LOG_PARAMS, 2); END IF; EXCEPTION WHEN OTHERS THEN V_IS_OK := FALSE; V_ERROR_MSG := '表: ' || full_table_name || ' 错误: ' || SQLERRM; V_LOG_PARAMS.PROCESS_STEP_ID := V_LOG_PARAMS.PROCESS_STEP_ID + 1; V_LOG_PARAMS.LOG_MESSAGE := V_ERROR_MSG; PERFORM FND_EXCEPT_LOG_P (V_LOG_PARAMS); END; END LOOP; EXCEPTION WHEN OTHERS THEN V_IS_OK := FALSE; V_ERROR_MSG := SUBSTR(SQLERRM, 1, 300); V_LOG_PARAMS.PROCESS_STEP_ID := V_LOG_PARAMS.PROCESS_STEP_ID + 1; V_LOG_PARAMS.LOG_MESSAGE := V_ERROR_MSG; PERFORM FND_EXCEPT_LOG_P (V_LOG_PARAMS); RETURN; END; IF V_IS_OK THEN COMMIT; END IF; V_IS_OK := TRUE; IF V_IS_OK THEN GET DIAGNOSTICS V_ROW_COUNT := ROW_COUNT; V_LOG_PARAMS.STEP_TYPE := 'END'; --V_LOG_PARAMS.DML_TYPE := 'ALL'; V_LOG_PARAMS.PROCESS_STEP_ID := V_LOG_PARAMS.PROCESS_STEP_ID + 1; V_LOG_PARAMS.DML_ROW_COUNT := V_ROW_COUNT; V_LOG_PARAMS.DATA_COMPONENT_NAME := V_SP_NAME; V_LOG_PARAMS.LOG_MESSAGE := V_SP_NAME || ' end'; PERFORM FND_STEP_LOG_P (V_LOG_PARAMS, 2); COMMIT; END IF; END; $$ 报错ERROR: "schema_part" is not a known variable. LINE 32: SELECT current_schema() INTO schema_part;
最新发布
09-23
openguass数据库public static final String IDATA_QUERY_ALL_AREA_URL = "App.Intergration.area.all"; public static final String IDATA_QUERY_ALL_DEPARTMENT_URL = "App.Intergration.organization.all"; /* * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. */ -- Description: 清空表 -- Author: cwx1445721 -- Version: 20250930 do LANGUAGE plpgsql $$ DECLARE V_SP_NAME nvarchar2(100) := '002_truncateTables_dml.sql'; V_LOG_PARAMS FND_LOG_PARAMS_TYP; V_ERROR_MSG nvarchar2(3000); V_IS_OK BOOL; V_CNT NUMERIC; V_ROW_COUNT NUMERIC; V_SQL TEXT :=''; V_CUR RECORD; v_table int4; BEGIN V_IS_OK := TRUE; BEGIN V_LOG_PARAMS := FND_INIT_LOG_PARAM_F(V_SP_NAME,'1','1',1); V_LOG_PARAMS.STEP_START_TIME := CLOCK_TIMESTAMP(); V_LOG_PARAMS.PROCESS_STEP_ID := V_LOG_PARAMS.PROCESS_STEP_ID + 1; V_LOG_PARAMS.LOG_MESSAGE := V_SP_NAME||' begin'; PERFORM FND_START_LOG_P(V_LOG_PARAMS); set app.current_tenant = 113704385416306; table_names VARCHAR[] := ARRAY[ 'fii.faai_apn_t' ]; -- 替换为目标表名列表 full_table_name VARCHAR; schema_part VARCHAR; table_part VARCHAR; table_exists BOOLEAN; BEGIN FOREACH full_table_name IN ARRAY table_names LOOP -- 分离模式名和表名 schema_part := split_part(full_table_name, '.', 1); table_part := split_part(full_table_name, '.', 2); -- 检查表是否存在 SELECT EXISTS ( SELECT 1 FROM pg_tables WHERE schemaname = schema_part AND tablename = table_part ) INTO table_exists; -- 获取存在标志[^1] -- 根据存在标志处理 IF table_exists THEN EXECUTE FORMAT('TRUNCATE TABLE %I.%I', schema_part, table_part); -- 安全执行清空 -- RAISE NOTICE 'table %.% 已清空', schema_part, table_part; END IF; END LOOP; EXCEPTION WHEN OTHERS THEN V_IS_OK := FALSE; V_ERROR_MSG := SUBSTR(SQLERRM, 1, 300); V_LOG_PARAMS.PROCESS_STEP_ID := V_LOG_PARAMS.PROCESS_STEP_ID + 1; V_LOG_PARAMS.LOG_MESSAGE := V_ERROR_MSG; PERFORM FND_EXCEPT_LOG_P(V_LOG_PARAMS); RETURN; END; IF V_IS_OK THEN COMMIT; END IF; V_IS_OK := TRUE; IF V_IS_OK THEN GET DIAGNOSTICS V_ROW_COUNT := ROW_COUNT; V_LOG_PARAMS.STEP_TYPE := 'END'; --V_LOG_PARAMS.DML_TYPE := 'ALL'; V_LOG_PARAMS.PROCESS_STEP_ID := V_LOG_PARAMS.PROCESS_STEP_ID + 1; V_LOG_PARAMS.DML_ROW_COUNT := V_ROW_COUNT; V_LOG_PARAMS.DATA_COMPONENT_NAME := V_SP_NAME; V_LOG_PARAMS.LOG_MESSAGE := V_SP_NAME||' end'; PERFORM FND_STEP_LOG_P(V_LOG_PARAMS, 2); COMMIT; END IF; end; $$此sql想要实现若数据库存在数组中的表名则将对应的表清空,修正sql,使这个sql能够实现功能
09-20
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值