We are trying to use our logback.xml that we use in GCP Cloud run which has amazing filtering features. Our logback.xml contains this for cloud run
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="com.orderlyhealth.api.logging.logback.GCPCloudLoggingJSONLayout">
<pattern>${CONSOLE_PATTERN}</pattern>
</layout>
</encoder>
</appender>
And our GCPCloudLoggingJSONLayout does a great job at setting all the things we need like clientId, customerRequestId, etc. etc. and we can filter across many many microservices on one customer or one customer request. We lose this in dataflow currently though. We tried adding logback.xml to src/main/resources and deploying the project seems to use it in the shell like so
{"message":"[main][-][:] o.a.b.r.d.DataflowRunner Template successfully created.\n",
"logger":"org.apache.beam.runners.dataflow.DataflowRunner",
"transactionId":null,"socket":null,"clntSocket":null,
"version":null,
"timestamp":{"seconds":1619694798,"nanos":4000000},
"thread":"main",
"severity":"INFO",
"instanceId":null,
"headers":{},
"messageInfo":{"message":"Message short enough. Displayed top level"}
}
thanks for any ideas on modifying dataflow logging.
Currently we see this instead which is not nearly as useful for tracing the customer request through systems
I don't think you can change how Dataflow logs to Cloud logging.
Instead, you can change how/what you log and let Dataflow pass them through to cloud logging. See Logging pipeline messages.
Or you can use cloud logging client libraries in your pipeline directly: https://cloud.google.com/logging/docs/reference/libraries.
Please take a look at How to override Google DataFlow logging with logback? for the latest version of this answer
I copied the current answer there to make it easier for folks who want to look:
Dataflow relies on using java.util.logging (aka JUL) as the logging backend for SLF4J and adds various bridges ensuring that logs from other libraries are output as well. With this kind of setup, we are limited to adding any additional details to the log message itself only.
This also applies to any runner executing a portable job since the container with the SDK harness has a similar logging configuration. For example Dataflow Runner V2.
To do this we want to create a custom formatter to apply to the root JUL logger. For example:
public class CustomFormatter extends SimpleFormatter {
public String formatMessage(LogRecord record) {
// implement whatever logic the is needed to add details to the message portion of the log statement
return super.formatMessage(record);
}
}
And then during start-up of the worker we need to update the root logger to use this formatter. We can achieve this using a JvmInitializer and implement the beforeProcessing method like so:
#AutoService(JvmInitializer.class)
public class LoggerInitializer implements JvmInitializer {
public void beforeProcessing(PipelineOptions options) {
LogManager logManager = LogManager.getLogManager();
Logger rootLogger = logManager.getLogger("");
for (Handler handler : rootLogger.getHandlers()) {
handler.setFormatter(new CustomFormatter());
}
}
}
Related
I run multiple TestNG 7.4.0 suites in parallel using something like (follows kotlin code, but it is the same in java, there is no language dependency):
val testNG = TestNG()
with(testNG) {
setXmlSuites(allMyXmlSuites)
suiteThreadPoolSize = threadCount
}
LISTENERS.forEach { testNG.addListener(it) }
testNG.run()
In my suites i configure the parent module like this
suite.parentModule = SuiteParentModule::class.java.name
My problem is that inside SuiteParentModule I have a singleton that is invoked multiple time, exactly the number of times that are the suites invocation. So I guess every suite has an independent instance of Injector. Here the provider method that logs multiple time:
#Provides
#Singleton
fun provideEnvironmentUrls(): EnvironmentUrls =
EnvironmentUrls(
System.getProperty("url")
).also { logger.info("Using default $it") }
Is there any way to make sure the dependency injection container provided by TestNg using Guice will remain the same, thus having real singletones provided?
I found that, even if using TestNG.setParentModule(), multiple suites will have multiple injectors.
I managed to get only one injector created by moving my code into a single suite.
Further information can be obtained at the issue opened in the TestNG git.
I'm exploring Log4j 2.14.0 and SLF4j 2.0 and trying to generate structured messages.
I've got my Appender set up with a slightly modified LogstashJsonEventLayoutV1.json,
<JsonTemplateLayout eventTemplateUri="classpath:LogstashJsonEventLayoutV1-test.json" properties="true" />
where I've removed the timestamp and hostname(I'm doing this as part of a unit test) and modified the config for "message" like so:
"message": {
"$resolver": "message",
"fallbackKey": "formattedMessage"}
When I log something
log4jLogger.atInfo().log(new MapMessage(Map.of("hello", "world")));
It's obviously generating JSONified log messages:
{"#version":1,"message":{"hello":"world"},"thread_name":"Test worker","level":"INFO","logger_name":"java.lang.Integer"}
In production my shop generally uses Log4J via SLF4J. I'd be willing to use the 2.0.0-alpha1 release of SLF4J to achieve this goal. How would I achieve the same thing via SLF4J's fluent API via addKeyValue?
logger.atDebug().addKeyValue("oldT", oldT).addKeyValue("newT", newT).log("Temperature changed.");
At the end of the day I just wrapped log4j--for this use case, there was no manna to be had for wrapping Slf4j when I could just target log4j.
I have Jenkins ver. 2.7.4 and I want to see custom messages in report
besides stack trace. What do I need to do for this?
If you are writing a jenkins plugin and you've subclassed Notifier, then you can log to the build output using an instance of BuildListener, like so:
Helper method:
private void logger(BuildListener listener, String message){
listener.getLogger().println(message);
}
Example Usage:
logger(listener, "Verbose Logging Enabled");
You can see a real world example of this in the source code for the packagecloud plugin for jenkins
See: https://wiki.jenkins-ci.org/display/JENKINS/Packagecloud+Plugin
This seems like a simple question to me:
I have a project where I automatically generate a Spring-WS WSDL, something like this:
<sws:dynamic-wsdl id="service"
portTypeName="Service"
locationUri="/Service/"
targetNamespace="http://location.com/Service/schemas/Mos">
<sws:xsd location="classpath:/META-INF/Service.xsd"/>
</sws:dynamic-wsdl>
Is there a way, on application context startup, to output the generated address of the wsdl, including context, location, etc? This would be handy if our integration tests start to fail, we can see if the location of the WSDL has changed.
As far as I know, you can find the WSDL at http://yourHost/yourServletContext/beanId.wsdl. In your case, beanId is 'service'.
Check out 3.7. Publishing the WSDL in the Spring-WS documentation for more information about this subject.
If you plan to expose your XSD's as well, the beanId.xsd (or, in my case the method name in the #Configuration class) format will be used. For instance:
private ClassPathResource exampleXsdResource = new ClassPathResource("example.xsd");
#Bean public SimpleXsdSchema example() {
return new SimpleXsdSchema(exampleXsdResource);
}
This exposes an XSD at http://yourHost/yourServletContext/example.xsd.
I'm trying to develop a stand-alone client app that uses web services in a Glassfish container (Metro). About all I have to work from is a wsdl for the wervices I'm trying to use. The wsdl is rife with all kinds of 'wsp:Policy' tags. Looks like IssuedToken, Trust13, ecryption are all utilized.
So I generated some code from netbeans and JAX-WS. Everything went well, but when trying to run the client I get:
'WST0029:STS location could not be obtained from either IssuedToken or from client configuration for accessing the service http://localhost:8080/ ....'
That's when it occured to me that I know nothing about WSS. It doesn't look like any code was generated to deal with security. So, I'll have to go from scratch.
So where to start? Books? Tutorials?
TIA
Metro applies the policy in runtime from either the WSDL or the wsit-client.xml config file. That's why no code is generated related to policies. According to this post it is not possible at the moment to do programatically.
This tutorial explains pretty well some of the things you can do with WSS, and though everything do probably not apply in this case it's still a good read.
The simplest way I've found of generating a client with WSS support is by using the wsimport script from Metro:
cd metro/bin/
mkdir src target
./wsimport.sh -s src -d target -extension -Xendorsed -verbose YourService.wsdl
Then install Metro into your application server (copy the libs to the correct places or run the ant script):
ant -f metro-on-glassfish.xml
Then put your local WSDL file in your classpath (e.g. your resource folder), so Metro can get it at runtime to apply the policies from your generated YourService class:
private final static URL YOURSERVICE_WSDL_LOCATION;
// This is enough, you don't need the wsdlLocation attribute
// on the #WebServiceClient annotation if you have this.
static {
YOURSERVICE_WSDL_LOCATION =
CustomerService.class.getClassLoader().getResource("YourService.wsdl");
}
public YourService() {
super(YOURSERVICE_WSDL_LOCATION,
new QName("http://tempuri.org/", "YourService"));
}
And if you want WS-Addressing you might need to add the feature manually to your binding method (Metro has never generated it for me, so I always have to add it myself).
#WebEndpoint(name = "WSHttpBinding_IYourService")
public IYourService getWSHttpBindingIYourService() {
WebServiceFeature wsAddressing = new AddressingFeature(true);
IYourService service =
super.getPort(new QName("http://xmlns.example.com/services/Your",
"WSHttpBinding_IYourService"), IYourService.class,
wsAddressing);
return service;
}