Skip to content

Commit

Permalink
Improve trace logging: More compact output of context objects like re…
Browse files Browse the repository at this point in the history
…source, value map etc. (#53)
  • Loading branch information
stefanseifert authored Jun 14, 2024
1 parent 852f0a2 commit dcacef7
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 11 deletions.
6 changes: 6 additions & 0 deletions changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/plugins/maven-changes-plugin/xsd/changes-1.0.0.xsd">
<body>

<release version="2.0.10" date="not released">
<action type="update" dev="sseifert" issue="53">
Improve trace logging: Make log messages involving value maps and resource/page objects more compact and better readable.
</action>
</release>

<release version="2.0.8" date="2024-05-22">
<action type="update" dev="sseifert" issue="51">
Dynamic Media Support: Append fmt=png-alpha for PNG assets to ensure that the alpha channel is preserved in the Dynamic Media rendition.
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/io/wcm/handler/media/MediaArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.osgi.annotation.versioning.ProviderType;

import io.wcm.handler.media.format.MediaFormat;
import io.wcm.handler.media.impl.AemObjectsReflectionToStringBuilder;
import io.wcm.handler.media.markup.DragDropSupport;
import io.wcm.handler.media.markup.IPERatioCustomize;
import io.wcm.handler.mediasource.dam.AemRenditionType;
Expand Down Expand Up @@ -843,7 +844,7 @@ public String toString() {
sb.append("webOptimizedImageDeliveryDisabled", webOptimizedImageDeliveryDisabled);
}
if (properties != null && !properties.isEmpty()) {
sb.append("properties", properties);
sb.append("properties", AemObjectsReflectionToStringBuilder.filteredValueMap(properties));
}
return sb.build();
}
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/io/wcm/handler/media/MediaRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@

import java.util.HashMap;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.wrappers.ValueMapDecorator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.annotation.versioning.ProviderType;

import io.wcm.handler.media.impl.AemObjectsReflectionToStringBuilder;

/**
* Holds all properties that are part of a media handling request.
*/
Expand Down Expand Up @@ -119,10 +119,11 @@ public MediaRequest(@Nullable Resource resource, @Nullable String mediaRef, @Nul

@Override
public String toString() {
ToStringBuilder sb = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
ToStringBuilder sb = new ToStringBuilder(this,
io.wcm.wcm.commons.util.ToStringStyle.SHORT_PREFIX_OMIT_NULL_STYLE);
if (resource != null) {
sb.append("resource", resource.getPath());
sb.append("resourceProperties", "[" + StringUtils.join(resource.getValueMap().entrySet(), ",") + "]");
sb.append("resourceProperties", AemObjectsReflectionToStringBuilder.filteredValueMap(resource.getValueMap()));
}
if (mediaRef != null) {
sb.append("mediaRef", mediaRef);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* #%L
* wcm.io
* %%
* Copyright (C) 2024 wcm.io
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package io.wcm.handler.media.impl;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;

import com.day.cq.wcm.api.Page;

/**
* Extends ReflectionToStringBuilder to provide custom handling for AEM-related objects
* (Resource, ValueMap, Page) for a more compact log output.
*/
public class AemObjectsReflectionToStringBuilder extends ReflectionToStringBuilder {

/**
* @param object Object to output
*/
public AemObjectsReflectionToStringBuilder(Object object) {
super(object);
}

/**
* @param object Object to output
* @param style Style
*/
public AemObjectsReflectionToStringBuilder(Object object, ToStringStyle style) {
super(object, style);
}

@Override
protected Object getValue(Field field) throws IllegalAccessException {
if (Resource.class.isAssignableFrom(field.getType())) {
Resource resource = (Resource)field.get(this.getObject());
if (resource != null) {
return resource.getPath();
}
}
else if (ValueMap.class.isAssignableFrom(field.getType())) {
ValueMap valueMap = (ValueMap)field.get(this.getObject());
if (valueMap != null) {
return filteredValueMap(valueMap);
}
}
else if (Page.class.isAssignableFrom(field.getType())) {
Page page = (Page)field.get(this.getObject());
if (page != null) {
return page.getPath();
}
}
return super.getValue(field);
}

/**
* Filter value map to exclude jcr:* properties and null values.
* @param props Value map
* @return Filtered value map, sorted by key
*/
public static Map<String, Object> filteredValueMap(ValueMap props) {
return props.entrySet().stream()
.filter(entry -> !entry.getKey().startsWith("jcr:") && entry.getValue() != null)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (o1, o2) -> o1, TreeMap::new));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.sling.api.adapter.Adaptable;
import org.apache.sling.api.adapter.SlingAdaptable;
import org.apache.sling.api.resource.Resource;
Expand All @@ -41,11 +40,11 @@
import io.wcm.handler.media.Rendition;
import io.wcm.handler.media.UriTemplate;
import io.wcm.handler.media.UriTemplateType;
import io.wcm.handler.media.impl.AemObjectsReflectionToStringBuilder;
import io.wcm.handler.media.spi.MediaHandlerConfig;
import io.wcm.handler.mediasource.dam.AssetRendition;
import io.wcm.handler.mediasource.dam.impl.dynamicmedia.DynamicMediaSupportService;
import io.wcm.handler.mediasource.dam.impl.weboptimized.WebOptimizedImageDeliveryService;
import io.wcm.wcm.commons.util.ToStringStyle;

/**
* {@link Asset} implementation for DAM assets.
Expand Down Expand Up @@ -225,7 +224,8 @@ public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {

@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_OMIT_NULL_STYLE);
return new AemObjectsReflectionToStringBuilder(this,
io.wcm.wcm.commons.util.ToStringStyle.SHORT_PREFIX_OMIT_NULL_STYLE).build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.sling.api.adapter.Adaptable;
import org.apache.sling.api.adapter.SlingAdaptable;
import org.apache.sling.api.resource.Resource;
Expand All @@ -36,8 +35,8 @@
import io.wcm.handler.media.Rendition;
import io.wcm.handler.media.UriTemplate;
import io.wcm.handler.media.UriTemplateType;
import io.wcm.handler.media.impl.AemObjectsReflectionToStringBuilder;
import io.wcm.handler.media.spi.MediaHandlerConfig;
import io.wcm.wcm.commons.util.ToStringStyle;

/**
* {@link Asset} implementation for inline media objects stored in a node in a content page.
Expand Down Expand Up @@ -169,7 +168,8 @@ public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {

@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_OMIT_NULL_STYLE);
return new AemObjectsReflectionToStringBuilder(this,
io.wcm.wcm.commons.util.ToStringStyle.SHORT_PREFIX_OMIT_NULL_STYLE).build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/
package io.wcm.handler.mediasource.ngdm;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.ValueMap;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -119,4 +120,12 @@ final class NextGenDynamicMediaAsset implements Asset {
return null;
}

@Override
public String toString() {
return new ToStringBuilder(this)
.append("reference", context.getReference())
.append("metadata", context.getMetadata())
.toString();
}

}
14 changes: 14 additions & 0 deletions src/test/java/io/wcm/handler/media/MediaRequestTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,27 @@

import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import io.wcm.handler.media.testcontext.AppAemContext;
import io.wcm.testing.mock.aem.junit5.AemContext;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;

@ExtendWith(AemContextExtension.class)
class MediaRequestTest {

private final AemContext context = AppAemContext.newAemContext();

@Test
void testToString() {
MediaRequest request = new MediaRequest("/path", null);
assertTrue(StringUtils.contains(request.toString(), "/path"));
}

@Test
void testToString_Resource() {
MediaRequest request = new MediaRequest(context.create().resource("/content/test"), null);
assertTrue(StringUtils.contains(request.toString(), "/content/test"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* #%L
* wcm.io
* %%
* Copyright (C) 2024 wcm.io
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package io.wcm.handler.media.impl;

import static com.day.cq.commons.jcr.JcrConstants.JCR_CREATED;
import static com.day.cq.commons.jcr.JcrConstants.JCR_PRIMARYTYPE;
import static com.day.cq.commons.jcr.JcrConstants.NT_UNSTRUCTURED;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.util.Date;
import java.util.Map;

import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import com.day.cq.wcm.api.Page;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.wcm.handler.media.testcontext.AppAemContext;
import io.wcm.sling.commons.resource.ImmutableValueMap;
import io.wcm.testing.mock.aem.junit5.AemContext;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;

@ExtendWith(AemContextExtension.class)
class AemObjectsReflectionToStringBuilderTest {

private final AemContext context = AppAemContext.newAemContext();

@SuppressWarnings("null")
private static final ValueMap VALUEMAP_SAMPLE = ImmutableValueMap.of(
"prop1", "value1",
JCR_CREATED, new Date(),
JCR_PRIMARYTYPE, NT_UNSTRUCTURED,
"prop2", 5,
"prop3", null);

@Test
void testBuild() {
ClassWithFields obj = new ClassWithFields();
obj.prop1 = "value1";
obj.resource = context.create().resource("/content/resource1",
"prop2", "value2");
obj.page = context.create().page("/content/page1");
obj.props = VALUEMAP_SAMPLE;

assertEquals("[page=/content/page1,prop1=value1,props={prop1=value1, prop2=5},resource=/content/resource1]",
new AemObjectsReflectionToStringBuilder(obj, ToStringStyle.NO_CLASS_NAME_STYLE).build());
}

@Test
void testBuild_NullObjects() {
ClassWithFields obj = new ClassWithFields();

assertNotNull(new AemObjectsReflectionToStringBuilder(obj).build());
}

@Test
void testFilteredValueMap() {
Map<String, Object> filtered = AemObjectsReflectionToStringBuilder.filteredValueMap(VALUEMAP_SAMPLE);

assertEquals(Map.of("prop1", "value1", "prop2", 5), filtered);
}

@SuppressWarnings("unused")
@SuppressFBWarnings("URF_UNREAD_FIELD")
private static final class ClassWithFields {
String prop1;
Resource resource;
Page page;
ValueMap props;
}

}

0 comments on commit dcacef7

Please sign in to comment.