Multi-step config in logback with clojure tools.logging - clojure

I'm trying to use a custom appender in a clojure application using logback & clojure tools.logging.
My config looks like this:
<appender name="Sentry" class="net.kencochrane.raven.logback.SentryAppender">
<dsn>some-dsn</dsn>
</appender>
This results in the following runtime error:
The following loggers will not work because they were created during the default configuration phase of the underlying logging system.....
A quick google search turns up a document to use a JoranConfigurator programatically to perform a multi-step configuration, but I actually don't see an exposed method in tools.logging to perform multi-step configuration. Any advise other than modifying tools.logging? Am I missing something obvious? Thanks for your time.

tools.logging doesn't do any configuration of the underlying logging system. In the case of logback it just talks to the logging system via slf4j. The configuration of the actual logging is totally on the logback side.

An easy way might be to use a logback.xml config file and Logback dependencies with clojure/tools.logging. Based on Sentry docs it looks like you need the following dependencies:
[org.clojure/tools.logging "0.3.1" :exclusions [org.clojure/clojure]]
[org.slf4j/slf4j-api "1.7.25"]
[org.codehaus.janino/janino "3.0.7"] ; for conditional config processing
[ch.qos.logback/logback-classic "1.2.3"]
[ch.qos.logback/logback-core "1.2.3"]
[com.getsentry.raven/raven-logback "8.0.2"]
The Sentry docs page also has snippets of Logback XML config that you can use. For MDC attributes, you may want to take a look at Cambium.

here's a simple setup using sentry-java-logback,
with deps:
[org.clojure/tools.logging "0.4.1"]
[ch.qos.logback/logback-classic "1.2.3"]
[io.sentry/sentry-logback "3.2.0"]
and logback.xml:
<!-- Sentry -->
<appender name="SENTRY" class="io.sentry.logback.SentryAppender">
<encoder>
<pattern>${defaultPattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<options>
<dsn>https://........</dsn>
<release>1.0.0</release>
<serverName>ABCDE</serverName>
<environment>production</environment>
</options>
<minimumBreadcrumbLevel>DEBUG</minimumBreadcrumbLevel>
</appender>
<!-- ....THIS MIGHT CHANGE.... -->
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="SENTRY"/>
</root>
you can read more on Sentry docs

Related

How can I create test-suites to run on VisualPHPUnit?

I am using VisualPHPUnit and I am trying to organize my tests into suites (due to the fact that Selenium IDE does not export PHPUnit test suites).
I am currently implementing the option of the configuration XML file.
Yet,it is very limiting cause I want to run test suites on demand and not uploading each time on the server a new XML file (aka test suite).
I know that I can create an XML file with many test-suites in it but I would like to run them individually.
As you understand i am struggling towards DontRepeatYourself principle and code reuse.You know..just choose login.php , then the testcase and them logout.php and run them.
Is something like this possible???
Moreover...would it be difficult VisualPHPUnit to parse only one XML file and create a dropdown box of testsuites to choose from and run?
This is my XML file
<phpunit>
<!-- This is required for VPU to work correctly -->
<listeners>
<listener class="PHPUnit_Util_Log_JSON"></listener>
</listeners>
<testsuites>
<testsuite name="TestSuite1">
<file>/var/www/VisualPHPUnit/app/unitTests/Login/Login.php</file>
<file>/var/www/VisualPHPUnit/app/unitTests/CreateCourse/CreateCourse1.php</file>
<file>/var/www/VisualPHPUnit/app/unitTests/Logout.php</file>
</testsuite>
</testsuites>
</phpunit>
actually the PHP formaters are once again available for Selenium IDE. You may want to check this out:
https://addons.mozilla.org/en-us/firefox/addon/selenium-ide-php-formatters/
there are 2 php formaters: PHP_unit and PHP_Selenium

Jetty no longer includes request URL path as part of thread id?

We are using Logback with Jetty and our appender config looks like:
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{0} - %msg%n</pattern>
</encoder>
</appender>
With Jetty 7.5.4 the %thread property would be expanded to include the URL path of the request along with the thread id -- something like [qtp2105333421-78 - /requested/url]
Since upgrading to 7.6.8 it appears that the request path is no longer included -- logs now contain only [qtp2105333421-78].
I've only been able to find discussion of someone trying to exclude the request path from the log. I'm trying to include it now that it's missing and I couldn't find anything that sounded relevant in the Jetty changelog. Is this something that has been removed, or is it possible to change the logging pattern to get access to the request path again?
The request path in the Thread name is a DEBUG only features in 7.5.4
See org.eclipse.jetty.server.HttpConnection.handleRequest() from Jetty 7.5.4 line #407
It is still present as a DEBUG feature, but the move to Jetty 7.6.x had some refactoring that might be biting you.
See org.eclipse.jetty.server.AbstractHttpConnection.handleRequest() from Jettty 7.6.10 line #431.
Note the class change HttpConnection to AbstractHttpConnection

Multiple artifacts of the module in Ivy

I would like to retrieve jar to a specific folder(like lib) by ivy, below is my retrieve definition in the build.xml:
<ivy:retrieve pattern="lib/[artifact].[ext]" conf="webInfLib" />
And the definition of my ivy.xml like below:
<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd"
xmlns:m="http://ant.apache.org/ivy/maven">
<info organisation="xxxx" module="xxxx" status="integration"/>
<configurations>
<conf name="webInfLib" description="add jar to web-inf/lib folder"/>
</configurations>
<dependencies>
<dependency org="org.springframework" name="spring-beans" rev="2.5.5" transitive="false" conf="webInfLib -> default"/>
<dependency org="net.sf.json-lib" name="json-lib" rev="2.3">
<artifact name="json-lib" type="jar" m:classifier="jdk15"/>
</dependency>
</dependencies>
</ivy-module>
But it always throws:
impossible to ivy retrieve: java.lang.RuntimeException: Multiple artifacts of the module xxxxxx are retrieved to the same file! Update the retrieve pattern to fix this error.
I have read some similar question and their suggest to change the retrieve pattern to a more complex one. I try something like "[artifact]-revision.[ext]", but not help. And when I execute "ivy.resolve", it work fines. Is there any suggestion about this issue?
The retrieve pattern is the problem that's true.
You are trying
[artifact]-[revision].ext
so I would imagine the binary jar and the source jar would be both written on the same location for any arbitrary dependency. But if you add something unique to the case that you are having
[artifact]-[revision](-[classifier]).[ext]
In the case of a source or doc, the classifier would have a value and therefore would have a different name. In case of no classifier (like the case of the binary compiled jar) there won't be any classifier and this is dealt with by the parentheses ( )

How to use interceptor on the default page?

Here's my situation : in the webapp, I use an interceptor to set the language(Locale).
If a user is logged, I used the language property of this user.
Else if a cookie is set, I use the value of this cookie.
Else, I use the setting of the browser.
It works well when I navigate into the app and when I am logged.
The problem is at the welcome page, since it calls mydomain.com/index.jsp, it don't go through the interceptors so the language isn't set(it's always using the browser setting).
Is there a way to go through the interceptors on the index page or to set the Locale value in the index.jsp page ?
Thank you!
The solution :
I removed the .jsp from the index.jsp in the web.xml file :
<welcome-file-list>
<welcome-file>index</welcome-file>
</welcome-file-list>
I added the index action to my struts.xml file :
<default-action-ref name="index" />
<action name="index">
<interceptor-ref name="appStack" />
<result name="success">index.jsp</result>
</action>
The language interceptor is part of the appStack.
Thank you guys for your helps!
I recommend that you do one of two things: (your choice)
(1) Implement your logic in a web filter and have your container configured with this filter so you can set the language (if not already set). This is easy to do, just look at any example of a HelloWorld filter.
or...
(2) Make sure that your home page is only reachable as a Struts2 action (you can define a default action in your Struts2 config file) and ensure that your interceptor is part of the default stack.
Hope that helps!
I would just add the conventions plugin (struts2-conventions-plugin-x.x.x.jar) where x.x.x is the version you are using.
Then I would move all the public jsp's under /WEB-INF/content and be done.
In your web.xml I don't mention any welcome files... but if you would like to be explicit:
<welcome-file-list>
<welcome-file>index</welcome-file>
</welcome-file-list>
If using Struts 2.2.1 your web.xml should minimally look like...
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<filter>
<filter-name>action</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>action</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
If you want to do it the struts.xml way then just move the index.jsp under /WEB-INF and create an action mapping for it... something like:
<action name="index">
<result>/WEB-INF/index.jsp</result>
</action>
which would be in a package with namespace "/" or "".
On the other hand I haven't looked at the Local stuff in a while but are you sure you're not reinventing the wheel... the i18n interceptor is already in the default stack.
Look into it's use. Long story short there are language property files defined for each language. If Struts2 has determined such properties are in use then then the struts tags will search the value in its name attribute for a matching string in the property file and return the value of that map entry.
It all works pretty slick. Sorry if this is what you are already doing but on the chance you didn't know it should save you a lot of time.

Ivy and Snapshots (Nexus)

I'm using ant, ivy and nexus repo manager to build and store my artifacts. I managed to get everything working: dependency resolution and publishing. Until I hit a problem... (of course!).
I was publishing to a 'release' repo in nexus, which is locked to 'disable redeploy' (even if you change the setting to 'allow redeploy' (really lame UI there imo). You can imagine how pissed off I was getting when my changes weren't updating through the repo before I realised that this was happening.
Anyway, I now have to switch everything to use a 'Snapshot' repo in nexus. Problem is that this messes up my publish. I've tried a variety of things, including extensive googling, and haven't got anywhere whatsoever. The error I get is a bad PUT request, error code 400.
Can someone who has got this working please give me a pointer on what I'm missing.
Many thanks,
Alastair
fyi, here's my config:
Note that I have removed any attempts at getting snapshots to work as I didn't know what was actually (potentially) useful and what was complete guff. This is therefore the working release-only setup.
Also, please note that I've added the XXX-API ivy.xml for info only. I can't even get the xxx-common to publish (and that doesn't even have dependencies).
Ant task:
<target name="publish" depends="init-publish">
<property name="project.generated.ivy.file" value="${project.artifact.dir}/ivy.xml"/>
<property name="project.pom.file" value="${project.artifact.dir}/${project.handle}.pom"/>
<echo message="Artifact dir: ${project.artifact.dir}"/>
<ivy:deliver
deliverpattern="${project.generated.ivy.file}"
organisation="${project.organisation}"
module="${project.artifact}"
status="integration"
revision="${project.revision}"
pubrevision="${project.revision}" />
<ivy:resolve />
<ivy:makepom
ivyfile="${project.generated.ivy.file}"
pomfile="${project.pom.file}"/>
<ivy:publish
resolver="${ivy.omnicache.publisher}"
module="${project.artifact}"
organisation="${project.organisation}"
revision="${project.revision}"
pubrevision="${project.revision}"
pubdate="now"
overwrite="true"
publishivy="true"
status="integration"
artifactspattern="${project.artifact.dir}/[artifact]-[revision](-[classifier]).[ext]"
/>
</target>
Couple of ivy files to give an idea of internal dependencies:
XXX-Common project:
<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
<info
organisation="com.myorg.xxx"
module="xxx_common"
status="integration"
revision="1.0">
</info>
<publications>
<artifact name="xxx_common" type="jar" ext="jar"/>
<artifact name="xxx_common" type="pom" ext="pom"/>
</publications>
<dependencies>
</dependencies>
</ivy-module>
XXX-API project:
<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
<info
organisation="com.myorg.xxx"
module="xxx_api"
status="integration"
revision="1.0">
</info>
<publications>
<artifact name="xxx_api" type="jar" ext="jar"/>
<artifact name="xxx_api" type="pom" ext="pom"/>
</publications>
<dependencies>
<dependency org="com.myorg.xxx" name="xxx_common" rev="1.0" transitive="true" />
</dependencies>
</ivy-module>
IVY Settings.xml:
<ivysettings>
<properties file="${ivy.project.dir}/project.properties" />
<settings
defaultResolver="chain"
defaultConflictManager="all" />
<credentials host="${ivy.credentials.host}" realm="Sonatype Nexus Repository Manager" username="${ivy.credentials.username}" passwd="${ivy.credentials.passwd}" />
<caches>
<cache name="ivy.cache" basedir="${ivy.cache.dir}" />
</caches>
<resolvers>
<ibiblio name="xxx_publisher" m2compatible="true" root="${ivy.xxx.publish.url}" />
<chain name="chain">
<url name="xxx">
<ivy pattern="${ivy.xxx.repo.url}/com/myorg/xxx/[module]/[revision]/ivy-[revision].xml" />
<artifact pattern="${ivy.xxx.repo.url}/com/myorg/xxx/[module]/[revision]/[artifact]-[revision].[ext]" />
</url>
<ibiblio name="xxx" m2compatible="true" root="${ivy.xxx.repo.url}"/>
<ibiblio name="public" m2compatible="true" root="${ivy.master.repo.url}" />
<url name="com.springsource.repository.bundles.release">
<ivy pattern="http://repository.springsource.com/ivy/bundles/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
<artifact pattern="http://repository.springsource.com/ivy/bundles/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
</url>
<url name="com.springsource.repository.bundles.external">
<ivy pattern="http://repository.springsource.com/ivy/bundles/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
<artifact pattern="http://repository.springsource.com/ivy/bundles/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
</url>
</chain>
</resolvers>
</ivysettings>
w00h00t.
(There's something cathartic about asking the world for help. Usually you fix the problem much faster, even without a response).
Anyway, for the interested it came down to a couple of things:
a) the addition of -SNAPSHOT to all revisions. This involved forking a second ivy.xml -> ivy.SNAPSHOT.xml and referencing that explicitly in the ivy ant tasks.
b) given that this is a manual addition I had to go through my entire tree of build files and provide parallel paths for release and snapshot flows. This, in my opinion, is lame. But, as I guess we're extremely unlikely to invent any other type of flow, this probably won't bloat, and 2 parallel flows is where it will stay.
c) I specified various hints to ivy to check for updates to the snapshots. e.g. checkUpdated="true" and changePattern=".*-SNAPSHOT" on the resolver. And the addition of
<modules org="myorg" name=*" resolveMode="dynamic" />
Still, it'd be nice if there had been automatic integration with snapshot stuff. A bit of (optional) cleverness on the part of ivy. Let's face it, maven repos like nexus ARE really useful and I'm certainly using ivy only to get round maven's crappy build process. I like using nexus.
Anyway. If anyone ever wants to question further on this, feel free.
I'm not sure if this would help with the problem of having 2 sets of configurations, but at least the build.xml would be a little bit simpler.
You can define the revision attribute on the info element in ivy.xml as ${project.revision}.
You can then omit the revision="${project.revision}" attributes on ivy elements in build.xml.
See my answer on this another question for example:
https://stackoverflow.com/a/8853823/1148030
It should be noted, the only necessary step is to include the '-SNAPSHOT' to revision when publishing to Nexus. The other steps listed in the answer are optional/improvements. To pull the published item down, you need to add '-SNAPSHOT' to the revision as well.