1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *     Copyright 2016 Couchbase, Inc
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 */
17/** \file
18 * This file is internal to the inner workings of
19 * Phosphor and is not intended for public consumption.
20 */
21
22#pragma once
23
24#include <array>
25#include <chrono>
26#include <cstdint>
27#include <iostream>
28#include <string>
29#include <thread>
30#include <type_traits>
31
32#include "phosphor/platform/core.h"
33#include "trace_argument.h"
34#include "tracepoint_info.h"
35
36namespace phosphor {
37
38    constexpr auto arg_count = 2;
39
40    class PHOSPHOR_API TraceEvent {
41    public:
42        /**
43         * The enumeration representing the different types of TraceEvents
44         */
45        enum class Type : char {
46            AsyncStart,
47            AsyncEnd,
48            SyncStart,
49            SyncEnd,
50            Instant,
51            GlobalInstant
52        };
53
54        /**
55         * Default constructor for efficient TraceChunk initialisation
56         */
57        TraceEvent() = default;
58
59        /**
60         * Constructor for creating new events
61         *
62         * @param _tpi Tracepoint info for the event
63         * @param _type The event type
64         * @param _args An array of `Value`
65         * @param _arg_types An array of argument types
66         */
67        TraceEvent(const tracepoint_info* _tpi,
68                   Type _type,
69                   uint32_t _thread_id,
70                   std::array<TraceArgument, arg_count>&& _args,
71                   std::array<TraceArgument::Type, arg_count>&& _arg_types);
72
73        /**
74         * Used to get a string representation of the TraceEvent
75         *
76         * @return string representation of the TraceEvent
77         */
78        std::string to_string() const;
79
80        /**
81         * Used to get a JSON object representation of the TraceEvent
82         *
83         * @return JSON object representing the TraceEvent
84         */
85        std::string to_json() const;
86
87        /**
88         * Converts a TraceEvent::Type to a cstring
89         *
90         * @return cstring representing the given event type
91         */
92        static const char* typeToString(Type type);
93
94        /**
95         * @return the name of the event
96         */
97        const char* getName() const;
98
99        /**
100         * @return the category of the event
101         */
102        const char* getCategory() const;
103
104        /**
105         * @return the type of the event
106         */
107        Type getType() const;
108
109        /**
110         * @return the thread id of the event
111         */
112        uint64_t getThreadID() const;
113
114        /**
115         * @return the arguments of the event
116         */
117        const std::array<TraceArgument, arg_count>& getArgs() const;
118
119        /**
120         * @return the types of the arguments of the event
121         */
122        const std::array<TraceArgument::Type, arg_count>& getArgTypes() const;
123
124        /**
125         * @return the names of the arguments of the event
126         */
127        const std::array<RelaxedAtomicCString, arg_count>& getArgNames() const;
128
129        /**
130         * @return the timestamp of the event measured in
131         *         nanoseconds from an undefined epoch
132         */
133        int64_t getTime() const;
134
135    protected:
136        class ToJsonResult {
137        public:
138            const char* type;
139            std::string extras;
140        };
141
142        /**
143         * Get the required JSON parts for the type of the
144         * object. i.e. the event type character and any
145         * bonus strings.
146         *
147         * @return pair where first is the type character and
148         *         the second is any bonus parts of the JSON row
149         */
150        ToJsonResult typeToJSON() const;
151
152    private:
153        const tracepoint_info* tpi;
154        std::array<TraceArgument, arg_count> args;
155        uint64_t time;
156
157        uint32_t thread_id;
158        std::array<TraceArgument::Type, arg_count> arg_types;
159        Type type;
160    };
161
162    /**
163     * ostream operator overload for TraceEvent
164     *
165     * Adds a representation of a TraceEvent to an ostream.
166     *
167     * Used for debugging purposes to stream a TraceEvent to
168     * an output stream like std::cout.
169     *
170     * @param os Output stream to stream to.
171     * @param trace_event TraceEvent to be streamed
172     * @return Output stream passed in
173     */
174    PHOSPHOR_API
175    std::ostream& operator<<(std::ostream& os, const TraceEvent& trace_event);
176
177    static_assert(
178        sizeof(TraceEvent) <= 64,
179        "TraceEvent should fit inside a cache-line for performance reasons");
180}