/* * Copyright 2012-2016 the original author or authors. * * 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. */ package org.glowroot.agent.ui.sandbox; import java.util.Map; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.glowroot.agent.plugin.api.Agent; import org.glowroot.agent.plugin.api.Message; import org.glowroot.agent.plugin.api.MessageSupplier; import org.glowroot.agent.plugin.api.OptionalThreadContext; import org.glowroot.agent.plugin.api.ThreadContext.Priority; import org.glowroot.agent.plugin.api.TimerName; import org.glowroot.agent.plugin.api.TraceEntry; import org.glowroot.agent.plugin.api.weaving.BindTraveler; import org.glowroot.agent.plugin.api.weaving.OnAfter; import org.glowroot.agent.plugin.api.weaving.OnBefore; import org.glowroot.agent.plugin.api.weaving.Pointcut; public class NestableCallAspect { private static final ImmutableList<String> USERS = ImmutableList.of("able", "baker", "charlie"); private static final AtomicInteger counter = new AtomicInteger(); @Pointcut(className = "org.glowroot.agent.ui.sandbox.NestableCall", methodName = "execute", methodParameterTypes = {}, nestingGroup = "ui-sandbox-nestable", timerName = "nestable") public static class NestableCallAdvice { private static final TimerName timerName = Agent.getTimerName(NestableCallAdvice.class); private static final Random random = new Random(); @OnBefore public static TraceEntry onBefore(OptionalThreadContext context) { int count = counter.getAndIncrement(); String transactionName; String headline; if (random.nextBoolean()) { transactionName = "Nestable with a very long trace headline"; headline = "Nestable with a very long trace headline to test wrapping" + " abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz"; } else { transactionName = Strings.repeat(String.valueOf((char) ('a' + random.nextInt(26))), 40); headline = transactionName; } if (random.nextInt(10) == 0) { // create a long-tail of transaction names to simulate long-tail of urls transactionName += random.nextInt(1000); } TraceEntry traceEntry; if (count % 10 == 0) { traceEntry = context.startTransaction("Background", transactionName, getRootMessageSupplier(headline), timerName); } else { traceEntry = context.startTransaction("Sandbox", transactionName, getRootMessageSupplier(headline), timerName); } int index = count % (USERS.size() + 1); if (index < USERS.size()) { context.setTransactionUser(USERS.get(index), Priority.USER_PLUGIN); } else { context.setTransactionUser(null, Priority.USER_PLUGIN); } if (random.nextBoolean()) { context.addTransactionAttribute("My First Attribute", "hello world"); context.addTransactionAttribute("My First Attribute", "hello world"); context.addTransactionAttribute("My First Attribute", "hello world " + random.nextInt(10)); } if (random.nextBoolean()) { context.addTransactionAttribute("Second", "val " + random.nextInt(10)); } if (random.nextBoolean()) { context.addTransactionAttribute("A Very Long Attribute Value", Strings.repeat("abcdefghijklmnopqrstuvwxyz", 3)); } if (random.nextBoolean()) { context.addTransactionAttribute("Another", "a b c d e f g h i j k l m n o p q r s t u v w x y z" + " a b c d e f g h i j k l m n o p q r s t u v w x y z"); } return traceEntry; } @OnAfter public static void onAfter(@BindTraveler TraceEntry traceEntry) { double value = random.nextDouble(); if (value < 0.8) { traceEntry.end(); } else if (value < 0.9) { traceEntry.endWithError("root entry randomized error", new IllegalStateException()); } else { String reallyLongErrorMessage = Strings.repeat("abcdefghijklmnopqrstuvwxyz ", 100); traceEntry.endWithError(reallyLongErrorMessage, new IllegalStateException()); } } } private static MessageSupplier getRootMessageSupplier(final String traceEntryMessage) { return new MessageSupplier() { @Override public Message get() { Map<String, ?> detail = ImmutableMap .of("attr1", getLongDetailValue(false), "attr2", "value2", "attr3", ImmutableMap.of("attr31", ImmutableMap.of("attr311", ImmutableList.of("v311a", "v311b")), "attr32", getLongDetailValue(true), "attr33", getLongDetailValue(false))); return Message.create(traceEntryMessage, detail); } }; } private static String getLongDetailValue(boolean spaces) { int length = new Random().nextInt(200); StringBuilder sb = new StringBuilder(length); for (int i = 0; i < length; i++) { sb.append(i % 10); if (spaces && i % 10 == 0) { sb.append(' '); } } return sb.toString(); } }