// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h"

#include <utility>

#include "base/trace_event/common/trace_event_common.h"
#include "base/trace_event/trace_buffer.h"
#include "base/trace_event/trace_log.h"
#include "build/build_config.h"
#include "services/tracing/public/cpp/perfetto/producer_client.h"
#include "services/tracing/public/cpp/perfetto/traced_value_proto_writer.h"
#include "third_party/perfetto/include/perfetto/tracing/core/startup_trace_writer.h"
#include "third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.h"

using TraceLog = base::trace_event::TraceLog;
using TrackEvent = perfetto::protos::pbzero::TrackEvent;

namespace tracing {

namespace {

// To mark TraceEvent handles that have been added by Perfetto,
// we use the chunk index so high that TraceLog would've asserted
// at this point anyway.
constexpr uint32_t kMagicChunkIndex =
    base::trace_event::TraceBufferChunk::kMaxChunkIndex;

base::ThreadTicks ThreadNow() {
  return base::ThreadTicks::IsSupported()
             ? base::subtle::ThreadTicksNowIgnoringOverride()
             : base::ThreadTicks();
}

}  // namespace

// static
constexpr size_t TrackEventThreadLocalEventSink::kMaxCompleteEventDepth;

TrackEventThreadLocalEventSink::TrackEventThreadLocalEventSink(
    std::unique_ptr<perfetto::StartupTraceWriter> trace_writer,
    uint32_t session_id,
    bool disable_interning)
    : ThreadLocalEventSink(std::move(trace_writer),
                           session_id,
                           disable_interning),
      // TODO(eseckler): Tune these values experimentally.
      interned_event_categories_(1000),
      interned_event_names_(1000, 100),
      interned_annotation_names_(1000, 100),
      interned_source_locations_(1000),
      process_id_(TraceLog::GetInstance()->process_id()),
      thread_id_(static_cast<int>(base::PlatformThread::CurrentId())) {}

TrackEventThreadLocalEventSink::~TrackEventThreadLocalEventSink() {}

// TODO(eseckler): Decide on a (temporary) way to trigger this periodically.
// Long-term, it should be triggered by a signal from the service. Short-term,
// maybe we can reset it every N events and/or seconds.
void TrackEventThreadLocalEventSink::ResetIncrementalState() {
  reset_incremental_state_ = true;
}

void TrackEventThreadLocalEventSink::AddConvertableToTraceFormat(
    base::trace_event::ConvertableToTraceFormat* value,
    perfetto::protos::pbzero::DebugAnnotation* annotation) {
  PerfettoProtoAppender proto_appender(annotation);
  if (value->AppendToProto(&proto_appender)) {
    return;
  }

  std::string json = value->ToString();
  annotation->set_legacy_json_value(json.c_str());
}

void TrackEventThreadLocalEventSink::AddTraceEvent(
    base::trace_event::TraceEvent* trace_event,
    base::trace_event::TraceEventHandle* handle) {
  // TODO(eseckler): Support splitting COMPLETE events into BEGIN/END pairs.
  // For now, we emit them as legacy events so that the generated JSON trace
  // size remains small.
  if (handle && trace_event->phase() == TRACE_EVENT_PHASE_COMPLETE) {
    // 'X' phase events are added through a scoped object and
    // will have its duration updated when said object drops off
    // the stack; keep a copy of the event around instead of
    // writing it into SHM, until we have the duration.
    // We can't keep the TraceEvent around in the scoped object
    // itself as that causes a lot more codegen in the callsites
    // and bloats the binary size too much (due to the increased
    // sizeof() of the scoped object itself).
    DCHECK_LT(current_stack_depth_, kMaxCompleteEventDepth);
    if (current_stack_depth_ >= kMaxCompleteEventDepth) {
      return;
    }

    complete_event_stack_[current_stack_depth_] = std::move(*trace_event);
    handle->event_index = ++current_stack_depth_;
    handle->chunk_index = kMagicChunkIndex;
    handle->chunk_seq = session_id_;
    return;
  }

  uint32_t flags = trace_event->flags();
  bool copy_strings = flags & TRACE_EVENT_FLAG_COPY;
  bool explicit_timestamp = flags & TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP;

  ScopedPerfettoPostTaskBlocker post_task_blocker(
      !!(flags & TRACE_EVENT_FLAG_DISALLOW_POSTTASK));

  if (reset_incremental_state_) {
    interned_event_categories_.ResetEmittedState();
    interned_event_names_.ResetEmittedState();
    interned_annotation_names_.ResetEmittedState();
    interned_source_locations_.ResetEmittedState();

    // Emit a new thread descriptor in a separate packet, where we also set
    // the |reset_incremental_state| field.
    auto trace_packet = trace_writer_->NewTracePacket();
    trace_packet->set_incremental_state_cleared(true);
    auto* thread_descriptor = trace_packet->set_thread_descriptor();
    thread_descriptor->set_pid(process_id_);
    thread_descriptor->set_tid(thread_id_);
    if (explicit_timestamp) {
      // Don't use a user-provided timestamp as a reference timestamp.
      last_timestamp_ = TRACE_TIME_TICKS_NOW();
    } else {
      last_timestamp_ = trace_event->timestamp();
    }
    if (trace_event->thread_timestamp().is_null()) {
      last_thread_time_ = ThreadNow();
    } else {
      // Thread timestamp is never user-provided.
      DCHECK(trace_event->thread_timestamp() <= ThreadNow());
      last_thread_time_ = trace_event->thread_timestamp();
    }
    thread_descriptor->set_reference_timestamp_us(
        last_timestamp_.since_origin().InMicroseconds());
    thread_descriptor->set_reference_thread_time_us(
        last_thread_time_.since_origin().InMicroseconds());
    // TODO(eseckler): Fill in remaining fields in ThreadDescriptor.

    reset_incremental_state_ = false;
  }

  const char* category_name =
      TraceLog::GetCategoryGroupName(trace_event->category_group_enabled());
  InterningIndexEntry* interned_category =
      interned_event_categories_.LookupOrAdd(category_name);

  InterningIndexEntry* interned_name;
  const size_t kMaxSize = base::trace_event::TraceArguments::kMaxSize;
  InterningIndexEntry* interned_annotation_names[kMaxSize] = {nullptr};

  if (copy_strings) {
    interned_name =
        interned_event_names_.LookupOrAdd(std::string(trace_event->name()));
    for (size_t i = 0; i < trace_event->arg_size() && trace_event->arg_name(i);
         ++i) {
      interned_annotation_names[i] = interned_annotation_names_.LookupOrAdd(
          std::string(trace_event->arg_name(i)));
    }
  } else {
    interned_name = interned_event_names_.LookupOrAdd(trace_event->name());
    for (size_t i = 0; i < trace_event->arg_size() && trace_event->arg_name(i);
         ++i) {
      interned_annotation_names[i] =
          interned_annotation_names_.LookupOrAdd(trace_event->arg_name(i));
    }
  }

  // Start a new packet which will contain the trace event and any new
  // interning index entries.
  auto trace_packet = trace_writer_->NewTracePacket();
  auto* track_event = trace_packet->set_track_event();

  // Events for different processes/threads always use an absolute timestamp.
  bool force_absolute_timestamp =
      ((flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID) &&
       trace_event->process_id() != base::kNullProcessId) ||
      thread_id_ != trace_event->thread_id() || explicit_timestamp;

  if (force_absolute_timestamp || last_timestamp_ > trace_event->timestamp()) {
    track_event->set_timestamp_absolute_us(
        trace_event->timestamp().since_origin().InMicroseconds());
  } else {
    track_event->set_timestamp_delta_us(
        (trace_event->timestamp() - last_timestamp_).InMicroseconds());
    last_timestamp_ = trace_event->timestamp();
  }

  if (!trace_event->thread_timestamp().is_null()) {
    // Thread timestamps are never user-provided, but COMPLETE events may get
    // reordered, so we can still observe timestamps that are further in the
    // past. Emit those as absolute timestamps, since we don't support
    // negative deltas.
    if (last_thread_time_ > trace_event->thread_timestamp()) {
      track_event->set_thread_time_absolute_us(
          trace_event->thread_timestamp().since_origin().InMicroseconds());
    } else {
      track_event->set_thread_time_delta_us(
          (trace_event->thread_timestamp() - last_thread_time_)
              .InMicroseconds());
      last_thread_time_ = trace_event->thread_timestamp();
    }
  }

  // TODO(eseckler): Split comma-separated category strings.
  track_event->add_category_iids(interned_category->id);

  for (size_t i = 0; i < trace_event->arg_size() && trace_event->arg_name(i);
       ++i) {
    auto type = trace_event->arg_type(i);
    auto* annotation = track_event->add_debug_annotations();

    annotation->set_name_iid(interned_annotation_names[i]->id);

    if (type == TRACE_VALUE_TYPE_CONVERTABLE) {
      AddConvertableToTraceFormat(trace_event->arg_convertible_value(i),
                                  annotation);
      continue;
    }

    auto& value = trace_event->arg_value(i);
    switch (type) {
      case TRACE_VALUE_TYPE_BOOL:
        annotation->set_bool_value(value.as_bool);
        break;
      case TRACE_VALUE_TYPE_UINT:
        annotation->set_uint_value(value.as_uint);
        break;
      case TRACE_VALUE_TYPE_INT:
        annotation->set_int_value(value.as_int);
        break;
      case TRACE_VALUE_TYPE_DOUBLE:
        annotation->set_double_value(value.as_double);
        break;
      case TRACE_VALUE_TYPE_POINTER:
        annotation->set_pointer_value(static_cast<uint64_t>(
            reinterpret_cast<uintptr_t>(value.as_pointer)));
        break;
      case TRACE_VALUE_TYPE_STRING:
      case TRACE_VALUE_TYPE_COPY_STRING:
        annotation->set_string_value(value.as_string ? value.as_string
                                                     : "NULL");
        break;
      default:
        NOTREACHED() << "Don't know how to serialize this value";
        break;
    }
  }

  auto* legacy_event = track_event->set_legacy_event();

  legacy_event->set_name_iid(interned_name->id);

  char phase = trace_event->phase();
  legacy_event->set_phase(phase);

  if (phase == TRACE_EVENT_PHASE_COMPLETE) {
    legacy_event->set_duration_us(trace_event->duration().InMicroseconds());

    if (!trace_event->thread_timestamp().is_null()) {
      int64_t thread_duration = trace_event->thread_duration().InMicroseconds();
      if (thread_duration != -1) {
        legacy_event->set_thread_duration_us(thread_duration);
      }
    }
  } else if (phase == TRACE_EVENT_PHASE_INSTANT) {
    switch (flags & TRACE_EVENT_FLAG_SCOPE_MASK) {
      case TRACE_EVENT_SCOPE_GLOBAL:
        legacy_event->set_instant_event_scope(
            TrackEvent::LegacyEvent::SCOPE_GLOBAL);
        break;

      case TRACE_EVENT_SCOPE_PROCESS:
        legacy_event->set_instant_event_scope(
            TrackEvent::LegacyEvent::SCOPE_PROCESS);
        break;

      case TRACE_EVENT_SCOPE_THREAD:
        legacy_event->set_instant_event_scope(
            TrackEvent::LegacyEvent::SCOPE_THREAD);
        break;
    }
  }

  uint32_t id_flags =
      flags & (TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_HAS_LOCAL_ID |
               TRACE_EVENT_FLAG_HAS_GLOBAL_ID);
  switch (id_flags) {
    case TRACE_EVENT_FLAG_HAS_ID:
      legacy_event->set_unscoped_id(trace_event->id());
      break;
    case TRACE_EVENT_FLAG_HAS_LOCAL_ID:
      legacy_event->set_local_id(trace_event->id());
      break;
    case TRACE_EVENT_FLAG_HAS_GLOBAL_ID:
      legacy_event->set_global_id(trace_event->id());
      break;
    default:
      break;
  }

  if (id_flags && trace_event->scope() != trace_event_internal::kGlobalScope) {
    legacy_event->set_id_scope(trace_event->scope());
  }

  if (flags & TRACE_EVENT_FLAG_ASYNC_TTS) {
    legacy_event->set_use_async_tts(true);
  }

  uint32_t flow_flags =
      flags & (TRACE_EVENT_FLAG_FLOW_OUT | TRACE_EVENT_FLAG_FLOW_IN);
  switch (flow_flags) {
    case TRACE_EVENT_FLAG_FLOW_OUT | TRACE_EVENT_FLAG_FLOW_IN:
      legacy_event->set_flow_direction(TrackEvent::LegacyEvent::FLOW_INOUT);
      break;
    case TRACE_EVENT_FLAG_FLOW_OUT:
      legacy_event->set_flow_direction(TrackEvent::LegacyEvent::FLOW_OUT);
      break;
    case TRACE_EVENT_FLAG_FLOW_IN:
      legacy_event->set_flow_direction(TrackEvent::LegacyEvent::FLOW_IN);
      break;
    default:
      break;
  }

  if (flow_flags) {
    legacy_event->set_bind_id(trace_event->bind_id());
  }

  if (flags & TRACE_EVENT_FLAG_BIND_TO_ENCLOSING) {
    legacy_event->set_bind_to_enclosing(true);
  }

  if ((flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID) &&
      trace_event->process_id() != base::kNullProcessId) {
    legacy_event->set_pid_override(trace_event->process_id());
    legacy_event->set_tid_override(-1);
  } else if (thread_id_ != trace_event->thread_id()) {
    legacy_event->set_tid_override(trace_event->thread_id());
  }

  // Emit any new interned data entries into the packet.
  auto* interned_data = trace_packet->set_interned_data();
  if (!interned_category->was_emitted) {
    auto* category_entry = interned_data->add_event_categories();
    category_entry->set_iid(interned_category->id);
    category_entry->set_name(category_name);
    interned_category->was_emitted = true;
  }

  if (!interned_name->was_emitted) {
    auto* name_entry = interned_data->add_legacy_event_names();
    name_entry->set_iid(interned_name->id);
    name_entry->set_name(trace_event->name());
    interned_name->was_emitted = true;
  }

  for (size_t i = 0; i < trace_event->arg_size() && trace_event->arg_name(i);
       ++i) {
    if (!interned_annotation_names[i]->was_emitted) {
      auto* name_entry = interned_data->add_debug_annotation_names();
      name_entry->set_iid(interned_annotation_names[i]->id);
      name_entry->set_name(trace_event->arg_name(i));
      interned_annotation_names[i]->was_emitted = true;
    }
  }

  if (disable_interning_) {
    interned_event_categories_.Clear();
    interned_event_names_.Clear();
    interned_annotation_names_.Clear();
    interned_source_locations_.Clear();
  }
}

void TrackEventThreadLocalEventSink::UpdateDuration(
    base::trace_event::TraceEventHandle handle,
    const base::TimeTicks& now,
    const base::ThreadTicks& thread_now) {
  if (!handle.event_index || handle.chunk_index != kMagicChunkIndex ||
      handle.chunk_seq != session_id_) {
    return;
  }

  DCHECK_GE(current_stack_depth_, 1u);
  // During trace shutdown, as the list of enabled categories are
  // non-monotonically shut down, there's the possibility that events higher in
  // the stack will have their category disabled prior to events lower in the
  // stack, hence we get misaligned here. In this case, as we know we're
  // shutting down, we leave the events unfinished.
  if (handle.event_index != current_stack_depth_) {
    DCHECK(handle.event_index > 0 &&
           handle.event_index < current_stack_depth_ &&
           !base::trace_event::TraceLog::GetInstance()->IsEnabled());
    current_stack_depth_ = handle.event_index - 1;
    return;
  }

  current_stack_depth_--;
  complete_event_stack_[current_stack_depth_].UpdateDuration(now, thread_now);
  AddTraceEvent(&complete_event_stack_[current_stack_depth_], nullptr);

#if defined(OS_ANDROID)
  complete_event_stack_[current_stack_depth_].SendToATrace();
#endif
}

void TrackEventThreadLocalEventSink::Flush() {
  trace_writer_->Flush();
}

}  // namespace tracing
