private void updateAccumulatedBuildTime(BuildRuleEvent buildRuleEvent) {
   Optional<? extends BuildRuleEvent> started =
       Preconditions.checkNotNull(
           threadsToRunningBuildRuleEvent.put(
               buildRuleEvent.getThreadId(), Optional.<BuildRuleEvent>absent()));
   Preconditions.checkState(started.isPresent());
   Preconditions.checkState(buildRuleEvent.getBuildRule().equals(started.get().getBuildRule()));
   AtomicLong current = accumulatedRuleTime.get(buildRuleEvent.getBuildRule().getBuildTarget());
   // It's technically possible that another thread receives resumed and finished events
   // while we're processing this one, so we have to check that the current counter exists.
   if (current != null) {
     current.getAndAdd(buildRuleEvent.getTimestamp() - started.get().getTimestamp());
   }
 }
  @Test
  public void testBuildJson() throws IOException {
    ProjectFilesystem projectFilesystem = new ProjectFilesystem(tmpDir.getRoot().toPath());

    ObjectMapper mapper = new ObjectMapper();

    ChromeTraceBuildListener listener =
        new ChromeTraceBuildListener(
            projectFilesystem,
            new FakeClock(1409702151000000000L),
            mapper,
            Locale.US,
            TimeZone.getTimeZone("America/Los_Angeles"),
            /* tracesToKeep */ 42,
            false);

    BuildTarget target = BuildTargetFactory.newInstance("//fake:rule");

    FakeBuildRule rule =
        new FakeBuildRule(
            target,
            new SourcePathResolver(new BuildRuleResolver()),
            ImmutableSortedSet.<BuildRule>of());
    RuleKey ruleKey = new RuleKey("abc123");
    rule.setRuleKey(ruleKey);
    String stepShortName = "fakeStep";
    String stepDescription = "I'm a Fake Step!";
    UUID stepUuid = UUID.randomUUID();

    ExecutionContext context = createMock(ExecutionContext.class);
    replay(context);

    ImmutableSet<BuildTarget> buildTargets = ImmutableSet.of(target);
    Iterable<String> buildArgs = Iterables.transform(buildTargets, Functions.toStringFunction());
    Clock fakeClock = new IncrementingFakeClock(TimeUnit.MILLISECONDS.toNanos(1));
    BuckEventBus eventBus =
        BuckEventBusFactory.newInstance(
            fakeClock, new BuildId("ChromeTraceBuildListenerTestBuildId"));
    eventBus.register(listener);

    eventBus.post(
        CommandEvent.started("party", ImmutableList.of("arg1", "arg2"), /* isDaemon */ true));
    eventBus.post(ArtifactCacheConnectEvent.started());
    eventBus.post(ArtifactCacheConnectEvent.finished());
    eventBus.post(BuildEvent.started(buildArgs));
    eventBus.post(
        ArtifactCacheEvent.started(ArtifactCacheEvent.Operation.FETCH, ImmutableSet.of(ruleKey)));
    eventBus.post(
        ArtifactCacheEvent.finished(
            ArtifactCacheEvent.Operation.FETCH, ImmutableSet.of(ruleKey), CacheResult.hit("http")));
    eventBus.post(BuildRuleEvent.started(rule));
    eventBus.post(StepEvent.started(stepShortName, stepDescription, stepUuid));

    eventBus.post(StepEvent.finished(stepShortName, stepDescription, stepUuid, 0));
    eventBus.post(
        BuildRuleEvent.finished(
            rule,
            BuildRuleStatus.SUCCESS,
            CacheResult.miss(),
            Optional.of(BuildRuleSuccessType.BUILT_LOCALLY),
            Optional.<HashCode>absent(),
            Optional.<Long>absent()));

    try (TraceEventLogger ignored =
        TraceEventLogger.start(eventBus, "planning", ImmutableMap.of("nefarious", "true"))) {
      eventBus.post(new TraceEvent("scheming", ChromeTraceEvent.Phase.BEGIN));
      eventBus.post(
          new TraceEvent(
              "scheming", ChromeTraceEvent.Phase.END, ImmutableMap.of("success", "false")));
    }

    eventBus.post(BuildEvent.finished(buildArgs, 0));
    eventBus.post(
        CommandEvent.finished(
            "party", ImmutableList.of("arg1", "arg2"), /* isDaemon */ true, /* exitCode */ 0));
    listener.outputTrace(new BuildId("BUILD_ID"));

    File resultFile = new File(tmpDir.getRoot(), BuckConstant.BUCK_TRACE_DIR + "/build.trace");

    List<ChromeTraceEvent> resultMap =
        mapper.readValue(resultFile, new TypeReference<List<ChromeTraceEvent>>() {});

    assertEquals(17, resultMap.size());

    assertEquals("process_name", resultMap.get(0).getName());
    assertEquals(ChromeTraceEvent.Phase.METADATA, resultMap.get(0).getPhase());
    assertEquals(ImmutableMap.of("name", "buck"), resultMap.get(0).getArgs());

    assertEquals("party", resultMap.get(1).getName());
    assertEquals(ChromeTraceEvent.Phase.BEGIN, resultMap.get(1).getPhase());
    assertEquals(ImmutableMap.of("command_args", "arg1 arg2"), resultMap.get(1).getArgs());

    assertEquals("artifact_connect", resultMap.get(2).getName());
    assertEquals(ChromeTraceEvent.Phase.BEGIN, resultMap.get(2).getPhase());

    assertEquals("artifact_connect", resultMap.get(3).getName());
    assertEquals(ChromeTraceEvent.Phase.END, resultMap.get(3).getPhase());

    assertEquals("build", resultMap.get(4).getName());
    assertEquals(ChromeTraceEvent.Phase.BEGIN, resultMap.get(4).getPhase());

    assertEquals("artifact_fetch", resultMap.get(5).getName());
    assertEquals(ChromeTraceEvent.Phase.BEGIN, resultMap.get(5).getPhase());

    assertEquals("artifact_fetch", resultMap.get(6).getName());
    assertEquals(ChromeTraceEvent.Phase.END, resultMap.get(6).getPhase());

    // BuildRuleEvent.Started
    assertEquals("//fake:rule", resultMap.get(7).getName());
    assertEquals(ChromeTraceEvent.Phase.BEGIN, resultMap.get(7).getPhase());
    assertEquals(ImmutableMap.of("rule_key", "abc123"), resultMap.get(7).getArgs());

    assertEquals("fakeStep", resultMap.get(8).getName());
    assertEquals(ChromeTraceEvent.Phase.BEGIN, resultMap.get(8).getPhase());

    assertEquals("fakeStep", resultMap.get(9).getName());
    assertEquals(
        ImmutableMap.of(
            "description", "I'm a Fake Step!",
            "exit_code", "0"),
        resultMap.get(9).getArgs());
    assertEquals(ChromeTraceEvent.Phase.END, resultMap.get(9).getPhase());

    // BuildRuleEvent.Finished
    assertEquals("//fake:rule", resultMap.get(10).getName());
    assertEquals(ChromeTraceEvent.Phase.END, resultMap.get(10).getPhase());
    assertEquals(
        ImmutableMap.of(
            "cache_result", "miss",
            "success_type", "BUILT_LOCALLY"),
        resultMap.get(10).getArgs());

    assertEquals("planning", resultMap.get(11).getName());
    assertEquals(ChromeTraceEvent.Phase.BEGIN, resultMap.get(11).getPhase());
    assertEquals(ImmutableMap.of("nefarious", "true"), resultMap.get(11).getArgs());

    assertEquals("scheming", resultMap.get(12).getName());
    assertEquals(ChromeTraceEvent.Phase.BEGIN, resultMap.get(12).getPhase());
    assertEquals(ImmutableMap.of(), resultMap.get(12).getArgs());

    assertEquals("scheming", resultMap.get(13).getName());
    assertEquals(ChromeTraceEvent.Phase.END, resultMap.get(13).getPhase());
    assertEquals(ImmutableMap.of("success", "false"), resultMap.get(13).getArgs());

    assertEquals("planning", resultMap.get(14).getName());
    assertEquals(ChromeTraceEvent.Phase.END, resultMap.get(14).getPhase());
    assertEquals(ImmutableMap.of(), resultMap.get(14).getArgs());

    assertEquals("build", resultMap.get(15).getName());
    assertEquals(ChromeTraceEvent.Phase.END, resultMap.get(15).getPhase());

    assertEquals("party", resultMap.get(16).getName());
    assertEquals(ChromeTraceEvent.Phase.END, resultMap.get(16).getPhase());
    assertEquals(
        ImmutableMap.of(
            "command_args", "arg1 arg2",
            "daemon", "true"),
        resultMap.get(16).getArgs());

    verify(context);
  }