Ведение журнала с помощью XQuery

Я использую XQuery 3.0 для преобразования входящего сообщения в соответствии с моей системой. XQuery вызывается из маршрута Apache Camel через преобразование EIP.

Пример:
transform().xquery("resource:classpath:xquery/myxquery.xquery",String.class)

Хотя преобразование работает без проблем, было бы неплохо, поскольку это отчасти очень сложно, иметь возможность регистрировать некоторую информацию непосредственно во время процесса преобразования.

Итак, я хотел спросить, можно ли войти «в» logback непосредственно из XQuery?

Я уже искал stackoverflow и, конечно, https://www.w3.org/TR/xquery-30-use-cases/ и другие источники, но я просто не смог найти никакой информации о как войти в Xquery.

Моя структура проекта:

  • Приложение Spring-Boot 2
  • Apache-Camel как фреймворк маршрутизации
  • Возврат в качестве среды ведения журнала

Обновление: для интеграции XQuery в Apache-Camel Framework я использую org.apache.camel:camel-saxon-starter:2.22.2.


person the hand of NOD    schedule 21.02.2019    source источник
comment
XQuery / XPath имеют trace функцию w3.org/TR/xpath-functions/ # func-trace, вы можете проверить, отображается ли какой-либо вывод в вашем журнале.   -  person Martin Honnen    schedule 21.02.2019


Ответы (1)


Обновление: поскольку использование fn:trace было некрасивым, я продолжил поиск, и теперь я использую механизм расширения от Saxon для предоставления различных функций ведения журнала, к которым можно получить доступ через xquery:

Для получения дополнительной информации см. Документацию: http://www.saxonica.com/documentation/#!extensibility/integratedfunctions/ext-full-J

Вот что я сделал для логирования (тестировал с Saxon-HE, Camel не является обязательным, я просто использую его случайно):

Первый шаг:

Расширить класс net.sf.saxon.lib.ExtensionFunctionDefinition

public class XQueryInfoLogFunctionDefinition extends ExtensionFunctionDefinition{

    private static final Logger log = LoggerFactory.getLogger(XQueryInfoLogFunctionDefinition.class);

    private final XQueryInfoExtensionFunctionCall functionCall = new XQueryInfoExtensionFunctionCall();

    private static final String PREFIX = "log";

    @Override
    public StructuredQName getFunctionQName() {
        return new StructuredQName(PREFIX, "http://thehandofnod.com/saxon-extension", "info");
    }

    @Override
    public SequenceType[] getArgumentTypes() {
        return new SequenceType[] { SequenceType.SINGLE_STRING };
    }

    @Override
    public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
        return SequenceType.VOID;
    }

    @Override
    public ExtensionFunctionCall makeCallExpression() {
        return functionCall;
    }

}

Второй шаг:

Реализуйте класс FunctionCall

public class XQueryInfoExtensionFunctionCall extends ExtensionFunctionCall {

    private static final Logger log = LoggerFactory.getLogger(XQueryInfoLogFunctionDefinition.class);

    @Override
    public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
        if (arguments != null && arguments.length > 0) {
            log.info(((StringValue) arguments[0]).getStringValue());
        } else
            throw new IllegalArgumentException("We need a message");
        return EmptySequence.getInstance();
    }
}

Третий шаг:

Настройте SaxonConfiguration и привяжите его к контексту верблюда:

    public static void main(String... args) throws Exception {
        Main main = new Main();

        Configuration saxonConfig = Configuration.newConfiguration(); 
        saxonConfig.registerExtensionFunction(new XQueryInfoLogFunctionDefinition());

        main.bind("saxonConfig", saxonConfig);
        main.addRouteBuilder(new MyRouteBuilder());
        main.run(args);
    }

Четвертый шаг:

Определите SaxonConfig в своем XQueryEndpoint: .to("xquery:test.xquery?configuration=#saxonConfig");

Пятый шаг:

Назовите это в своем xquery:

declare namespace log="http://thehandofnod.com/saxon-extension";
log:info("Das ist ein INFO test")

Оригинальный пост a.k.a Как перезаписать fn:trace Funktion:

Благодаря Мартину Хоннену я попробовал функцию fn:trace. Проблема заключалась в том, что по умолчанию он входит в System.err Printstream, а это не то, что я хотел, потому что я хотел объединить функцию fn:trace с Logback Logging-Framework.

Итак, я отладил net.sf.saxon.functions.Trace методы и пришел к следующему решению для настройки моего проекта.

  1. Напишите собственный TraceListener, который расширяется от net.sf.saxon.trace.XQueryTraceListener, и реализуйте методы enter и leave таким образом, чтобы InstructionInfo с constructType == 2041 (для трассировки пользователя) перенаправлялся в SLF4J-API. Пример (только для записи сообщения):
@Override
    public void enter(InstructionInfo info, XPathContext context) {
        // no call to super to keep it simple.
        String nachricht = (String) info.getProperty("label");
        if (info.getConstructType() == 2041 && StringUtils.hasText(nachricht)) {
            getLogger().info(nachricht);
        }
    }

    @Override
    public void leave(InstructionInfo info) {
        // no call to super to keep it simple.
    }
  1. установите пользовательский прослушиватель трассировки в свой net.sf.saxon.Configuration Bean через setTraceListener

  2. Вызовите свой файл xquery из camel через XQueryEndpoint, потому что только там можно перезаписать Configuration с опцией: .to("xquery:/xquery/myxquery.xquery?configuration=#saxonConf"). К сожалению, transform().xquery(...) использует собственные объекты без возможности их настройки.

  3. позвоните {fn:trace($element/text(),"Das ist ein Tracing Test")} в свой xquery и посмотрите сообщение в своем журнале.

person the hand of NOD    schedule 22.02.2019