Инструментарий для добавления регистрации в код Scala

В Java мы можем использовать AspectJ прозрачно добавить ведение журнала в классы Java (или, возможно, использовать другие инструменты инструментария байт-кода). Теперь мне интересно, как прозрачно добавить логирование в функции Scala.

Я хотел бы инструмент для преобразования функции foo

def foo(x:Int) = x + 1

к чему-то такому:

def foo (x: Int) = { 
   log.trace ("Enter foo with x =" + x) // добавляется автоматически
   val r = x + 1
   log.trace("Exit foo with r = " + r) // добавляется автоматически  
   р
}

Как бы вы прозрачно добавили логирование в функции Scala?

1 ответ

AspectJ будет прекрасно работать с кодом Scala. Вам просто нужно следовать правилам искажения имени в Scala (т.е. def > становится def $gt) и так далее.

Предположим, у вас есть

class Foo {
  def foo(x: Int) {
  }
  def bar() { }
}

Чтобы добавить ведение журнала, вы можете использовать синтаксис Java AspectJ, добавив

"org.aspectj" % "aspectjweaver" % "1.7.2",
"org.aspectj" % "aspectjrt" % "1.7.2"

На ваш build.sbt, Двигаясь дальше, вы можете иметь следующий аспект:

@Aspect
public class MonitorAspect {

    @Pointcut(value = "execution (* your.package.Foo.*(..))")
    public void methodsInFoo() {}

    @Before("methodsInFoo()")
    public void enter(JoinPoint jp) {
        // log
    }

    @After("methodsInFoo()")
    public void exit(JoinPoint jp) {
    }
}

Последний кусок будет META-INF/aop.xml, который определяет работу для ткача времени загрузки:

<aspectj>

    <aspects>
        <aspect name="your.package.MonitorAspect"/>
    </aspects>

    <weaver options="-XnoInline">
        <include within="your.package.*"/>
    </weaver>

</aspectj>

Наконец, начните свою JVM с -javaagent:$PATH_TO_ASPECTJWEAVER.JAR и все готово


В вашем случае, возможно, стоит подумать об использовании функций более высокого порядка. Если вы используете журналирование в качестве примера и действительно делаете что-то до и после какой-то внутренней функции, вам следует рассмотреть возможность использования HOF.

def logged[U](f: => U): U = {
    log.info("Before")
    val ret = f
    log.info("After")
    ret
}

Здесь у вас есть logged функция, которая принимает другую функцию fимеет дело с журналами и делает что угодно f делает.

Другие вопросы по тегам