英文:
Using archunit to enforce log context
问题
I'll provide the translation for the code and error message:
以下是代码的翻译和错误信息:
按照[这个][1]博客文章中建议的方法,我正在尝试创建一个ArchUnit规则,以强制要求日志记录语句具有上下文信息。但是示例中提到的代码无法编译:
```java
public static ArchRule noInfoLoggingWithoutContext() {
ArchCondition<JavaClass> loggerWithOutContext =
callMethodWhere(
target(name("info"))
.and(target(owner(assignableTo(Logger.class))))
.and(target(rawParameterTypes(new DescribedPredicate<>(
"logger.info without context") {
@Override
public boolean test(List<JavaClass> methodParameters) {
return methodParameters.size() <= 1;
}
})))).as("use logger.info without context");
return noClasses().should(loggerWithOutContext);
}
上述提到的代码出现以下错误:
所需类型: DescribedPredicate<? super AccessTarget>
提供的类型: DescribedPredicate<HasParameterTypes>
有什么建议,我们如何实现这样的规则?
archunit版本: 1.0.1
请注意,这是您提供的代码和错误信息的翻译。如果需要进一步的帮助或解释,请随时提出。
<details>
<summary>英文:</summary>
Following the method suggested in [this][1] blog post, I am trying to create an archunit rule that will enforce log statements to have contextual information. But the code mentioned in the example is not compiling:
```java
public static ArchRule noInfoLoggingWithoutContext() {
ArchCondition<JavaClass> loggerWithOutContext =
callMethodWhere(
target(name("info"))
.and(target(owner(assignableTo(Logger.class))))
.and(target(rawParameterTypes(new DescribedPredicate<>("logger.info without context") {
@Override
public boolean test(List<JavaClass> methodParameters) {
return methodParameters.size() <= 1;
}
})))).as("use logger.info without context");
return noClasses().should(loggerWithOutContext);
}
The above mentioned code fails with the following error:
Required type: DescribedPredicate <? super AccessTarget>
Provided: DescribedPredicate<HasParameterTypes>
Any suggestions, how can we implement such a rule?
archunit version: 1.0.1
答案1
得分: 1
你可能选择了错误的静态导入:
import static com.tngtech.archunit.core.domain.JavaAccess.Predicates.target;
(它返回一个 DescribedPredicate<JavaAccess<?>>
)
而不是
import static com.tngtech.archunit.core.domain.JavaCall.Predicates.target;
(它返回一个 DescribedPredicate<JavaCall<?>>
)。
因为 callMethodWhere
接受一个 DescribedPredicate<? super JavaMethodCall>
,
而 JavaMethodCall
继承自 JavaCall
,后者又继承自 JavaCodeUnitAccess
,再者继承自 JavaAccess
,
所以 "错误" 的 target
方法适用于 callMethodWhere
,
但它的谓词只能操作 JavaAccess
,它具有 name
和 owner
,但没有 rawParameterTypes
。
无关于你的问题:我建议将整个规则简化为:
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
import org.slf4j.Logger;
import static com.tngtech.archunit.base.DescribedPredicate.describe;
import static com.tngtech.archunit.core.domain.JavaCall.Predicates.target;
import static com.tngtech.archunit.lang.conditions.ArchConditions.callMethodWhere;
import static com.tngtech.archunit.lang.conditions.ArchPredicates.is;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
public class StackOverflow76250573 {
@ArchTest
ArchRule noInfoLoggingWithoutContext =
noClasses().should(callMethodWhere(target(is(describe("logger.info without context",
target ->
target.getOwner().isAssignableTo(Logger.class)
&& target.getName().equals("info")
&& target.getRawParameterTypes().size() < 2
)))));
}
英文:
You probably picked the "wrong" static import
import static com.tngtech.archunit.core.domain.JavaAccess.Predicates.target;
(which returns a DescribedPredicate<JavaAccess<?>>
) instead of
import static com.tngtech.archunit.core.domain.JavaCall.Predicates.target;
(which returns a DescribedPredicate<JavaCall<?>>
).
As callMethodWhere
takes a DescribedPredicate<? super JavaMethodCall>
,
and as JavaMethodCall extends JavaCall
, which in turn extends JavaCodeUnitAccess
, which in turn extends JavaAccess
, the "wrong" target
method worked for callMethodWhere
, but its predicates could only operate on JavaAccess
, which has a name
and an owner
, but no rawParameterTypes
.
Unrelated to your question: I would simplify the entire rule to
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
import org.slf4j.Logger;
import static com.tngtech.archunit.base.DescribedPredicate.describe;
import static com.tngtech.archunit.core.domain.JavaCall.Predicates.target;
import static com.tngtech.archunit.lang.conditions.ArchConditions.callMethodWhere;
import static com.tngtech.archunit.lang.conditions.ArchPredicates.is;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
public class StackOverflow76250573 {
@ArchTest
ArchRule noInfoLoggingWithoutContext =
noClasses().should(callMethodWhere(target(is(describe("logger.info without context",
target ->
target.getOwner().isAssignableTo(Logger.class)
&& target.getName().equals("info")
&& target.getRawParameterTypes().size() < 2
)))));
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论