public boolean shouldStoreSlow(Transaction transaction) { if (transaction.isPartiallyStored()) { return true; } // check if trace-specific store threshold was set long slowThresholdMillis = transaction.getSlowThresholdMillisOverride(); if (slowThresholdMillis != Transaction.USE_GENERAL_STORE_THRESHOLD) { return transaction.getDurationNanos() >= MILLISECONDS.toNanos(slowThresholdMillis); } // fall back to default slow trace threshold slowThresholdMillis = configService.getTransactionConfig().slowThresholdMillis(); if (transaction.getDurationNanos() >= MILLISECONDS.toNanos(slowThresholdMillis)) { return true; } // for now lumping user recording into slow traces tab // // check if should store for user recording if (configService.getUserRecordingConfig().enabled()) { String user = transaction.getUser(); if (!Strings.isNullOrEmpty(user) && user.equalsIgnoreCase(configService.getUserRecordingConfig().user())) { return true; } } return false; }
void maybeScheduleUserProfiling(Transaction transaction, String user) { UserRecordingConfig userRecordingConfig = configService.getUserRecordingConfig(); if (!userRecordingConfig.enabled()) { return; } if (!user.equalsIgnoreCase(userRecordingConfig.user())) { return; } // schedule the first stack collection for configured interval after transaction start (or // immediately, if the transaction's total time already exceeds configured collection // interval) int intervalMillis = userRecordingConfig.profileIntervalMillis(); ScheduledRunnable userProfileRunnable = new UserProfileRunnable(transaction, configService); long initialDelay = Math.max(0, intervalMillis - NANOSECONDS.toMillis(transaction.getDurationNanos())); userProfileRunnable.scheduleWithFixedDelay( scheduledExecutor, initialDelay, intervalMillis, MILLISECONDS); transaction.setUserProfileRunnable(userProfileRunnable); }
@Override public void runInternal() { if (transaction.isCompleted()) { // there is a small window between trace completion and cancellation of this // command, // plus, should a stop-the-world gc occur in this small window, even two command // executions can fire one right after the other in the small window (assuming the // first // didn't throw an exception which it does now), since this command is scheduled // using // ScheduledExecutorService.scheduleWithFixedDelay() throw new TerminateSubsequentExecutionsException(); } ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); ThreadInfo threadInfo = threadBean.getThreadInfo(transaction.getThreadId(), Integer.MAX_VALUE); transaction.captureStackTrace( threadInfo, configService.getAdvancedConfig().maxStackTraceSamplesPerTransaction(), configService.getAdvancedConfig().timerWrapperMethods()); }
public Aggregator( ScheduledExecutorService scheduledExecutor, Collector collector, ConfigService configService, long aggregateIntervalMillis, Clock clock) { this.scheduledExecutor = scheduledExecutor; this.collector = collector; this.configService = configService; this.clock = clock; this.aggregateIntervalMillis = aggregateIntervalMillis; activeIntervalCollector = new AggregateIntervalCollector( clock.currentTimeMillis(), aggregateIntervalMillis, configService.getAdvancedConfig().maxAggregateTransactionsPerTransactionType(), configService.getAdvancedConfig().maxAggregateQueriesPerQueryType()); // dedicated thread to aggregating transaction data processingThread = new Thread(new TransactionProcessor()); processingThread.setDaemon(true); processingThread.setName("Glowroot-Aggregate-Collector"); processingThread.start(); }