为AWS CloudWatch创建一个Quarkus扩展
为AWS CloudWatch创建Quarkus扩展
我们最近遇到的情况是,我们想把我们的Quarkus应用日志记录到AWS CloudWatch上。基本上这需要一些时间,但不是什么大问题。添加一个CloudWatch的依赖关系,创建一个日志处理程序,通过提供的AWS CloudWatch API将日志推送到CloudWatch。但如果你想和别人分享呢?当然,你可以把它作为项目的一部分放在GitHub上,这样别人就可以复制和粘贴它,但这并不是与他人分享代码的最优雅的方式。
这就是为什么我们实现了Quarkus扩展,这样其他人可以更容易地使用它,而不需要重新发明轮子或需要复制粘贴东西。如何做到这一点呢?在这里,Quarkiverse Hub就出现了。Quarkiverse是一个GitHub组织,开发者可以在这里托管并与他人分享他们的扩展。在Quarkiverse中托管扩展,而不是用自己做所有事情的老方法,你可以免费得到几个好处。通过使用Quarkiverse,你不需要构建工件,用Sonatype Nexus Manager(或类似的东西)发布它,也不需要在Maven Central和其他资源库中发布它。Quarkiverse自带所有这些东西,所以你可以专注于实现扩展本身。下面的文章描述了初始化、实现和分享CloudWatch Quarkus扩展所需要做的事情。
如果你想使用Quarkiverse在Hub上发布你的扩展(这是我们的建议),并利用所有使用它的优势,你只需要在quarkusio/quarkus GitHub组织中打开一个新的扩展建议问题。这样做,大部分的要求都已经满足了,因为会有一个模板为你生成,你只需要实现你的扩展代码。如果你使用一个现有的项目作为模板,有一些要求你需要照顾到。为了自动发布扩展和发布文档,Quarkiverse组织下的项目有一些规则需要遵循。
-
扩展库应该被命名为quarkus-
-
Quarkiverse扩展必须属于io.quarkiverse.组Id
-
根 pom.xml必须继承 io.quarkiverse:quarkiverse-parent
-
一个Quarkiverse扩展包含以下文件夹和文件:
-
部署
-
运行时间
-
集成-测试
-
文档
-
pom.xml
-
许可证
-
阅读手册
-
这篇文章只涉及运行时和部署内容,因为其他东西是可选的,已经由项目模板生成,甚至是重要的,但当你想了解如何创建Quarkus扩展时,这不是最重要和实用的东西。让我们从部署部分开始。它包含了Quarkus扩展的初始化所需的类。如果没有这个初始化类,当启动你的Quarkus应用程序时,你的扩展将无法被识别。
class LoggingCloudwatchProcessor {
@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem("logging-cloudwatch");
}
@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
LogHandlerBuildItem addCloudwatchLogHandler(final LoggingCloudWatchConfig config,
final LoggingCloudWatchHandlerValueFactory cloudWatchHandlerValueFactory) {
return new LogHandlerBuildItem(cloudWatchHandlerValueFactory.create(config));
}
}
在上面的片段中,你可以看到一个feature()方法,它被@BuildStep注解并返回一个新的FeatureBuildItem。它暴露了在应用程序启动过程中显示在日志中的功能名称(logging-cloudwatch)。第二个方法*addCloudWatchHandler()*初始化了由LoggingCloudWatchConfig和LoggingCloudWatchHandlerValueFactory类提供的扩展运行时配置。幸运的是,有一个LogHandlerBuildItem提供,所以我们可以通过添加我们自己的实现来覆盖现有的日志处理器。还有很多其他的BuildItems提供,所以如果你想创建自己的扩展,绝对值得一看。这个方法的参数是一个配置类,将在下面的片段中描述。
@ConfigRoot(phase = ConfigPhase.RUN_TIME, name = "log.cloudwatch")
public class LoggingCloudWatchConfig {
@ConfigItem(defaultValue = "true")
boolean enabled;
@ConfigItem
public String region;
// ...
}
LoggingCloudWatchConfig在扩展本身和使用该扩展的Quarkus应用程序之间建立了桥梁。它将Quarkus应用程序中的application.properties条目与我们的扩展相结合。这意味着通过这个类你可以定义application.properties文件中的属性,并使扩展可以从外部配置。@ConfigRoot定义了application.properties中属性的前缀,@ConfigItems是后缀。我们用这个类接受的一个application.properties条目是log.cloudwatch.enabled,例如。
除了LoggingCloudWatchConfig,还有一个*addCloudwatchLogHandler()*方法的参数。它是相应的工厂类。
@Recorder
public class LoggingCloudWatchHandlerValueFactory {
public RuntimeValue<Optional<Handler>> create(final LoggingCloudWatchConfig config) {
if (!config.enabled) {
return new RuntimeValue<>(Optional.empty());
}
AWSLogsClientBuilder clientBuilder = AWSLogsClientBuilder.standard();
clientBuilder.setCredentials(new CloudWatchCredentialsProvider(config));
// …
AWSLogs awsLogs = clientBuilder.build();
// …
LoggingCloudWatchHandler handler = new LoggingCloudWatchHandler(awsLogs, config.logGroup.get(),
config.logStreamName.get(), token);
// …
return new RuntimeValue<>(Optional.of(handler));
}
}
LoggingCloudWatchHandlerValueFactory是扩展的实际业务逻辑之间的粘合剂:处理应用程序的日志并将这些日志放到AWS和前面提到的application.properties文件的配置。正如你在*create()*方法中看到的,配置项被检查并用于初始化CloudWatch连接。
现在,我们已经通过添加application.properties条目使扩展用户可以配置扩展,暴露了扩展名称,并向处理程序类提供了配置,该处理程序创建了将日志信息放入AWS CloudWatch所需的AWS CloudWatch对象,我们只需要添加一个缺失的部分。日志处理程序本身。在上面的片段中,在LoggingCloudWatchHandlerValueFactory中,我们已经创建了它,并将其作为RuntimeValue返回,我们在LoggingCloudwatchProcessor类中使用。这就是覆盖现有默认日志处理程序所需的调用链。
class LoggingCloudWatchHandler extends Handler {
private AWSLogs awsLogs;
private String logStreamName;
private String logGroupName;
private String sequenceToken;
// ...
LoggingCloudWatchHandler(AWSLogs awsLogs, String logGroup, String logStreamName, String token) {
this.logGroupName = logGroup;
this.awsLogs = awsLogs;
this.logStreamName = logStreamName;
this.sequenceToken = token;
}
@Override
public void publish(LogRecord record) {
// ...
InputLogEvent logEvent = new InputLogEvent()
.withMessage(body)
.withTimestamp(System.currentTimeMillis());
awsLogs.putLogEvents(request);
}
}
这个日志处理程序是一个java.util.LogHandler,它将LogRecord对象作为发布方法的参数,在应用程序中写入日志时将会被调用。例如像log.info("I Love Open Source!");。如果配置正确,这个日志处理程序将在写入日志时被调用。由于我们想把日志信息放到AWS CloudWatch中,我们需要添加这样做的逻辑。因此,我们创建一个InputLogEvent并调用putLogEvents(),将日志信息放到CloudWatch中。这基本上就是了。
本文中的片段有点简短,但基本上这就是扩展包含的内容。 |
让我们把它总结一下。有一个初始化扩展的处理器类,一个使扩展可配置的配置类,一个接受这些配置并创建AWS CloudWatch连接的值工厂类,以及一个将每个日志消息推送到CloudWatch的自定义LogHandler类。
做完所有这些事情后,唯一缺少的就是发布扩展的版本。这可以通过打开一个Pull Request来完成,它可以更新*.github文件夹中的project.yml文件的当前版本和下一个版本*条目。合并该拉动请求后,会触发一些GitHub动作,将你的新版本带到Maven中心,最后其他人也可以使用你的扩展 :-)
总结
正如你所看到的,创建、实现和与他人分享Quarkus扩展其实非常容易。因此,如果你有一个对社区有用的扩展想法,请随时在quarkusio/quarkus GitHub问题部分创建一个新的扩展建议问题来提出你的想法 :-)