Adobe AEM

A Comprehensive Guide to New Relic: Full-Stack Observability & Use Cases

9 min read

Master New Relic APM, Infrastructure, browser monitoring, and NRQL with this detailed technical tutorial covering real-world observability use cases, with a special focus on Adobe Experience Manager (AEM).

New RelicObservabilityAPMDevOpsMonitoringAEMAdobe Experience ManagerArchitecture
A Comprehensive Guide to New Relic: Full-Stack Observability & Use Cases

For a Technical Architect, installing a monitoring agent and looking at default CPU/Memory dashboards is merely scratching the surface. True observability in an enterprise Adobe Experience Manager (AEM) ecosystem requires deep integration into OSGi, the JCR (Jackrabbit Oak), Apache Sling, and the Dispatcher caching layers.

When a P1 incident occurs—like a Publish tier suffering from thread pool exhaustion or the Dispatcher serving stale content—you need deterministic data, not guesswork.

This guide is an architect-level deep dive into instrumenting, tuning, and utilizing New Relic for AEM (applicable to AEM as a Cloud Service, AMS, and On-Premise).


1. The Architect's Dilemma: Custom Instrumentation vs. AEMaaCS Limitations

By default, the New Relic Java Agent hooks into standard Java EE servlets. Because AEM routes requests through Apache Sling and an OSGi container, the default APM trace will often just show a massive block of time spent in org.apache.sling.engine.impl.SlingMainServlet.

To get true visibility into custom code, you need Custom Instrumentation. However, how you achieve this depends entirely on your hosting model.

The AEM as a Cloud Service (AEMaaCS) Reality

According to official Adobe documentation, AEMaaCS provides a built-in, Adobe-managed New Relic sub-account. It is crucial for architects to understand the limitations of this managed account:

  • No Custom Instrumentation: You cannot inject custom XML pointcuts or use @Trace annotations in the Adobe-managed agent.
  • No Log Ingestion or Custom Alerts: The built-in account disables log ingestion and custom NRQL alerting.
  • The Workaround: To achieve true custom observability on AEMaaCS, architects must provision a Customer-Managed New Relic Account. You then use Cloud Manager to configure Log Forwarding via the New Relic HTTPS Log API. You rely on heavily structured logging in your Java code, which is forwarded to your private New Relic account where you can build custom NRQL alerts and dashboards.

Strategy for AMS & On-Premise: XML & @Trace Annotations

If you are on Adobe Managed Services (AMS) or On-Premise, you control the Java agent and can fully instrument OSGi.

XML-Based Custom Instrumentation: For third-party bundles, create an extension.xml inside the extensions directory of your New Relic agent folder:

<?xml version="1.0" encoding="UTF-8"?>
<extension xmlns="https://newrelic.com/docs/java/xsd/v1.0" name="AEM_Custom_OSGi_Instrumentation" version="1.0">
  <instrumentation>
    <!-- Instrument a heavy Sling Model -->
    <pointcut transactionStartPoint="false">
      <className>com.mycompany.aem.core.models.impl.MegaNavigationModelImpl</className>
      <method>
        <name>getNavigationItems</name>
      </method>
    </pointcut>
    
    <!-- Instrument a Sling Job Consumer (Start a new transaction here) -->
    <pointcut transactionStartPoint="true">
      <className>com.mycompany.aem.core.jobs.AssetSyncJobConsumer</className>
      <method>
        <name>process</name>
      </method>
    </pointcut>
  </instrumentation>
</extension>

Strategy B: The @Trace Annotation

For code you control, add the New Relic API dependency to your core bundle's pom.xml:

<dependency>
    <groupId>com.newrelic.agent.java</groupId>
    <artifactId>newrelic-api</artifactId>
    <version>8.5.0</version>
    <scope>provided</scope>
</dependency>

Then, annotate complex OSGi service methods. Use dispatcher = true for background tasks (like Sling Jobs or Scheduled Tasks) to ensure they are tracked as standalone transactions rather than lumped into a generic "Background Task" bucket.

import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Trace;
import org.osgi.service.component.annotations.Component;

@Component(service = InventorySyncService.class)
public class InventorySyncServiceImpl implements InventorySyncService {

    @Trace(dispatcher = true)
    public void syncWithERP() {
        NewRelic.setTransactionName("Custom", "InventorySyncJob");
        // Add custom metadata for NRQL querying
        NewRelic.addCustomParameter("syncSource", "SAP_ERP");
        
        try {
            executeComplexSync();
        } catch (Exception e) {
            NewRelic.noticeError(e);
            throw e;
        }
    }
}

2. Scraping AEM's Heartbeat: Custom JMX Integrations (AMS & On-Premise)

AEM exposes its most critical health metrics via Java Management Extensions (JMX). The New Relic Java Agent can scrape these MBeans automatically if configured, allowing you to build architect-level dashboards.

Create a jmx.yml file in your newrelic/extensions folder to capture specific AEM MBeans:

name: AEM_Critical_JMX_Metrics
version: 1.0
enabled: true
jmx:
  # 1. Track Replication Queue Backlogs
  - object_name: "com.adobe.granite.replication:type=agent,id=publish"
    metrics:
      - attributes: QueueSize
        type: simple
      - attributes: Status
        type: simple

  # 2. Track Jackrabbit Oak Repository Sessions (Detect ResourceResolver leaks)
  - object_name: "org.apache.jackrabbit.oak:name=Sessions,type=SessionStats"
    metrics:
      - attributes: SessionCount
        type: simple

  # 3. Track TarMK Segment Store Size (Monitor for Compaction failures)
  - object_name: "org.apache.jackrabbit.oak:name=TarMK disk usage,type=SegmentRevisionGarbageCollection"
    metrics:
      - attributes: RepositorySize
        type: simple

Architect's NRQL Use Case: You can now create a New Relic Alert that triggers before a system crash. Query: SELECT latest(QueueSize) FROM JmxBuiltIn WHERE objectName LIKE '%id=publish%' Alert Threshold: Trigger P2 if QueueSize > 5000 for more than 15 minutes.


3. Distributed Tracing: The CDN -> Dispatcher -> Publisher Pipeline

Modern AEM architectures utilize CDNs (Fastly/Akamai) in front of Apache Dispatcher, which proxies to AEM Publishers. When a request is slow, where is the latency introduced?

To trace this, you must pass unique trace IDs through the stack and ingest them into New Relic.

Step 1: Dispatcher Configuration (Apache)

Modify your httpd.conf to generate a unique Request ID and inject it into both the request headers (to pass to AEM) and the Apache access log.

# Generate unique ID
RewriteEngine On
RewriteCond %{ENV:UNIQUE_ID} ^$
RewriteRule ^ - [E=UNIQUE_ID:%{UNIQUE_ID}]

# Pass to AEM
RequestHeader set X-Request-Id "%{UNIQUE_ID}e"

# Log it in Dispatcher access.log for New Relic Infra Agent to parse
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D %{UNIQUE_ID}e %{X-Cache}o" combined_with_trace
CustomLog "logs/access_log" combined_with_trace

Step 2: AEM Sling Filter (Java)

Create a global Sling Filter in AEM to read the X-Request-Id and bind it to the New Relic transaction.

import com.newrelic.api.agent.NewRelic;
// ... (OSGi annotations)
public class TraceIdFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        HttpServletRequest req = (HttpServletRequest) request;
        String traceId = req.getHeader("X-Request-Id");
        
        if (traceId != null) {
            // Bind the Apache Unique ID to the New Relic Transaction
            NewRelic.addCustomParameter("cdnDispatcherTraceId", traceId);
        }
        chain.doFilter(request, response);
    }
}

Now, when a user complains about a 10-second page load, you take the Trace ID from the browser's response headers, query it in NRQL (SELECT * FROM Transaction WHERE cdnDispatcherTraceId = 'abc-123'), and immediately see if the time was spent in AEM or if the Dispatcher took 9 seconds waiting for a backend connection timeout.


4. Frontend Observability: SPA Editor & Edge Delivery Services

If your AEM implementation uses the SPA Editor (React/Angular) or Edge Delivery Services (formerly Project Helix), standard page-load metrics are insufficient.

Single Page Application (SPA) Tracking

For AEM SPA Editor, a route change doesn't trigger a full browser reload. You must use the New Relic Browser API to manually record interactions.

In your React App's Router configuration:

import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

export function NewRelicRouteTracker() {
  const location = useLocation();

  useEffect(() => {
    if (typeof newrelic !== 'undefined') {
      // End previous interaction and start a new one
      newrelic.setCurrentRouteName(location.pathname);
      newrelic.interaction().setName(`Route: ${location.pathname}`).save();
    }
  }, [location]);

  return null;
}

Edge Delivery Services (EDS)

EDS relies heavily on edge caching and Fastly/Cloudflare. Because there is no heavy Java backend rendering the HTML, New Relic RUM (Browser) becomes your primary source of truth. Focus your NRQL dashboards on Core Web Vitals:

-- Architect Dashboard: LCP by Device Type for Edge Delivery Site
SELECT percentile(largestContentfulPaint, 75) 
FROM PageViewTiming 
WHERE appName = 'AEM_Edge_Production' 
FACET deviceType TIMESERIES AUTO

5. Post-Mortem Walkthrough: Diagnosing ResourceResolver Leaks

Let's put on our Architect hats and walk through a critical production incident using New Relic.

The Incident: At 2:00 PM on Cyber Monday, the AEM Author instance completely locks up. The JVM process is running, but no users can log in, and the UI spins endlessly.

The Architect's Diagnosis in New Relic:

  1. APM > JVMs > Memory: You check the Heap graph. The Heap is at 95% and erratic, but it's not a complete OutOfMemory (OOM) flatline.
  2. APM > JVMs > Threads: You look at the Thread Count. The number of active threads spiked from 200 to 1,400 right at 2:00 PM. We have thread pool exhaustion.
  3. Thread Profiler: You trigger a 2-minute Thread Profile in New Relic. The resulting tree shows that 1,100 threads are in a BLOCKED state, waiting on a monitor lock inside org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore.
  4. JMX Metrics Dashboard: You check the custom JMX dashboard we built earlier. The SessionCount metric shows 85,000 open JCR sessions.
  5. Logs in Context: You query the AEM error.log via New Relic: SELECT * FROM Log WHERE message LIKE '%Unclosed ResourceResolver%' SINCE 2 hours ago The logs point directly to com.mycompany.aem.core.listeners.ProductUpdateListener.

The Root Cause & Fix: A custom OSGi Event Listener was triggering on every commerce product sync. Inside the listener, resourceResolverFactory.getServiceResourceResolver() was called, but the resolver was not wrapped in a try-with-resources block or explicitly closed in a finally block. The massive influx of Cyber Monday product updates leaked thousands of sessions, exhausting the Oak repository's connection pool and blocking all subsequent threads.

Fix: Push a hotfix wrapping the resolver in a try-with-resources block, and configure New Relic to alert if JCR Session Count exceeds 5,000.


Conclusion: Shifting from Monitoring to Observability

Monitoring is looking at a dashboard to see if CPU is high. Observability is being able to ask arbitrary, ad-hoc questions about your system and getting immediate answers based on telemetry data.

For an AEM Architect, New Relic is the lens through which you understand your system's behavior under stress. By implementing custom OSGi pointcuts, scraping Jackrabbit JMX metrics, injecting distributed trace IDs through your Dispatcher, and precisely measuring SPA route changes, you transition your team from reactive firefighters to proactive engineers.


Official References & Documentation

To dive deeper into the specific configurations mentioned in this guide, refer to the official documentation from both Adobe and New Relic:

Share this article

Discussion

By commenting you agree to the Privacy Policy. Guest comments are reviewed before they appear.

Loading discussion…

Subscribe to the Newsletter

Get the latest articles, tutorials, and tech insights delivered straight to your inbox. No spam, unsubscribe anytime.

Back to Blog