Как преследовать событие JFR по нескольким потокам - PullRequest
3 голосов
/ 20 мая 2019

Я пытаюсь смоделировать асинхронную обработку запроса сервлета с помощью пользовательских событий JFR.Проблема, с которой я сталкиваюсь, заключается в том, что при асинхронной обработке запрос может быть #dispatch() обработан несколько раз.Это означает, что вся цепочка обработки запросов может выполняться несколько раз, иногда в разных потоках.Как мне смоделировать это с помощью пользовательских событий JFR?

Что мне может помочь, это либо концепция «родительского» события (возможно, в другом потоке), либо приостановка и возобновление события.

Редактировать

Чтобы проиллюстрировать проблему немного.Обработка асинхронного запроса может занять 100 секунд.Однако фактическая обработка может произойти всего за 4 секунды времени пользователя в методе Servlet#service():

  • секунда 0-1 в потоке A, Servlet#service() метод возвращает, AsyncContext запущено
  • второй 10-11 в потоке B, Servlet#service() метод возвращает, AsyncContext запущен
  • второй 80-81 в потоке A, Servlet#service() метод возвращает, AsyncContext запущен
  • секунда 99-100 в потоке C, метод Servlet#service() возвращает

Меня интересует только генерирование событий для этих четырех длительностей в этих трех потоках, а затем корреляция их с одним запросом.

Ответы [ 2 ]

3 голосов
/ 20 мая 2019

Вы можете добавить поле потока к событию

public class MyEvent extends Event [
  @Label("Start Thread")
  @TranistionFrom
  private final Thread startThread;
  MyEvent(Thread thread) {
    this.startThread = thread;
  }
]

Когда вы фиксируете событие, конечный поток будет сохранен.

Если вы хотите отслеживать событие в нескольких потоках, вам нужно создать событие для каждого потока и иметь идентификатор, чтобы вы могли понять поток.

class MyEvent extends Event {

  @Label("Transition id");
  long id;
}

Если вам нравится, вы можете создать реляционный идентификатор для описания отношения, и JMC должен уметь подсказывать (в контекстных меню и т. Д.), Что существует связь между событиями.

@Label("Transition Id")
@Relational
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@interface TransitionId {
}

Если вы не хотите повторяться, вы можете написать вышеуказанную функциональность в методе базового класса, который вы можете вызывать для каждого нового потока, который посещает событие.

 abstract AbstractTransition extends Event {

   @TransitionId
   @Label("Transition Id")
   private long id;
   public void setTransitionId(long id) {
     this.id = id;
   }
 }

Нет другого способа сделать это.

Невозможно, чтобы JVM знала, в каком потоке находится объект события или какие потоки должны быть записаны. Пользователь должен предоставить по крайней мере один вызов метода для каждого потока, который должен быть затронут (вместе с некоторым контекстом).

1 голос
/ 20 мая 2019

Проблема похожа на то, как связать события JFR для диапазонов и областей вместе в распределенных трассировщиках.

Эта статья может помочь: http://hirt.se/blog/?p=1081

...