/*
 *
 * Copyright 2017 gRPC 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.
 *
 */

#ifndef GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_H
#define GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_H

#include <grpc/impl/codegen/port_platform.h>

#include <grpc/grpc.h>
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/json/json.h"

namespace grpc_core {
namespace channelz {

namespace testing {
size_t GetSizeofTraceEvent(void);
}

class BaseNode;

// Object used to hold live data for a channel. This data is exposed via the
// channelz service:
// https://github.com/grpc/proposal/blob/master/A14-channelz.md
class ChannelTrace {
 public:
  ChannelTrace(size_t max_event_memory);
  ~ChannelTrace();

  enum Severity {
    Unset = 0,  // never to be used
    Info,       // we start at 1 to avoid using proto default values
    Warning,
    Error
  };

  // Adds a new trace event to the tracing object
  //
  // NOTE: each ChannelTrace tracks the memory used by its list of trace
  // events, so adding an event with a large amount of data could cause other
  // trace event to be evicted. If a single trace is larger than the limit, it
  // will cause all events to be evicted. The limit is set with the arg:
  // GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE.
  //
  // TODO(ncteisen): as this call is used more and more throughout the gRPC
  // stack, determine if it makes more sense to accept a char* instead of a
  // slice.
  void AddTraceEvent(Severity severity, grpc_slice data);

  // Adds a new trace event to the tracing object. This trace event refers to a
  // an event that concerns a different channelz entity. For example, if this
  // channel has created a new subchannel, then it would record that with
  // a TraceEvent referencing the new subchannel.
  //
  // NOTE: see the note in the method above.
  //
  // TODO(ncteisen): see the todo in the method above.
  void AddTraceEventWithReference(Severity severity, grpc_slice data,
                                  RefCountedPtr<BaseNode> referenced_entity);

  // Creates and returns the raw grpc_json object, so a parent channelz
  // object may incorporate the json before rendering.
  grpc_json* RenderJson() const;

 private:
  friend size_t testing::GetSizeofTraceEvent(void);

  // Private class to encapsulate all the data and bookkeeping needed for a
  // a trace event.
  class TraceEvent {
   public:
    // Constructor for a TraceEvent that references a channel.
    TraceEvent(Severity severity, grpc_slice data,
               RefCountedPtr<BaseNode> referenced_entity_);

    // Constructor for a TraceEvent that does not reverence a different
    // channel.
    TraceEvent(Severity severity, grpc_slice data);

    ~TraceEvent();

    // Renders the data inside of this TraceEvent into a json object. This is
    // used by the ChannelTrace, when it is rendering itself.
    void RenderTraceEvent(grpc_json* json) const;

    // set and get for the next_ pointer.
    TraceEvent* next() const { return next_; }
    void set_next(TraceEvent* next) { next_ = next; }

    size_t memory_usage() const { return memory_usage_; }

   private:
    Severity severity_;
    grpc_slice data_;
    gpr_timespec timestamp_;
    TraceEvent* next_;
    // the tracer object for the (sub)channel that this trace event refers to.
    RefCountedPtr<BaseNode> referenced_entity_;
    size_t memory_usage_;
  };  // TraceEvent

  // Internal helper to add and link in a trace event
  void AddTraceEventHelper(TraceEvent* new_trace_event);

  gpr_mu tracer_mu_;
  uint64_t num_events_logged_;
  size_t event_list_memory_usage_;
  size_t max_event_memory_;
  TraceEvent* head_trace_;
  TraceEvent* tail_trace_;
  gpr_timespec time_created_;
};

}  // namespace channelz
}  // namespace grpc_core

#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_H */
