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            Complete
53        };
54
55        /**
56         * Default constructor for efficient TraceChunk initialisation
57         */
58        TraceEvent() = default;
59
60        /**
61         * Constructor for creating new events
62         *
63         * @param _tpi Tracepoint info for the event
64         * @param _type The event type
65         * @param _args An array of `Value`
66         * @param _arg_types An array of argument types
67         */
68        TraceEvent(const tracepoint_info* _tpi,
69                   Type _type,
70                   uint32_t _thread_id,
71                   std::array<TraceArgument, arg_count>&& _args,
72                   std::array<TraceArgument::Type, arg_count>&& _arg_types);
73
74        /**
75         * Constructor for Complete events.
76         * 'Complete' event includes both start time + duration; which are
77         * both specified by the caller.
78         */
79        TraceEvent(const tracepoint_info* _tpi,
80                   uint32_t _thread_id,
81                   std::chrono::steady_clock::time_point _start,
82                   std::chrono::steady_clock::duration _duration,
83                   std::array<TraceArgument, arg_count>&& _args,
84                   std::array<TraceArgument::Type, arg_count>&& _arg_types);
85
86        /**
87         * Used to get a string representation of the TraceEvent
88         *
89         * @return string representation of the TraceEvent
90         */
91        std::string to_string() const;
92
93        /**
94         * Used to get a JSON object representation of the TraceEvent
95         *
96         * @return JSON object representing the TraceEvent
97         */
98        std::string to_json() const;
99
100        /**
101         * Converts a TraceEvent::Type to a cstring
102         *
103         * @return cstring representing the given event type
104         */
105        static const char* typeToString(Type type);
106
107        /**
108         * @return the name of the event
109         */
110        const char* getName() const;
111
112        /**
113         * @return the category of the event
114         */
115        const char* getCategory() const;
116
117        /**
118         * @return the type of the event
119         */
120        Type getType() const;
121
122        /**
123         * @return the thread id of the event
124         */
125        uint64_t getThreadID() const;
126
127        /**
128         * @return the arguments of the event
129         */
130        const std::array<TraceArgument, arg_count>& getArgs() const;
131
132        /**
133         * @return the types of the arguments of the event
134         */
135        const std::array<TraceArgument::Type, arg_count>& getArgTypes() const;
136
137        /**
138         * @return the names of the arguments of the event
139         */
140        const std::array<const char*, arg_count>& getArgNames() const;
141
142        /**
143         * @return the timestamp of the event measured in
144         *         nanoseconds from an undefined epoch
145         */
146        int64_t getTime() const;
147
148        /**
149         * @return the duration of the event measured in nanoseconds.
150         */
151        uint64_t getDuration() const;
152
153    protected:
154        class ToJsonResult {
155        public:
156            const char* type;
157            std::string extras;
158        };
159
160        /**
161         * Get the required JSON parts for the type of the
162         * object. i.e. the event type character and any
163         * bonus strings.
164         *
165         * @return pair where first is the type character and
166         *         the second is any bonus parts of the JSON row
167         */
168        ToJsonResult typeToJSON() const;
169
170    private:
171        const tracepoint_info* tpi;
172        std::array<TraceArgument, arg_count> args;
173        uint64_t time;
174
175        /**
176         * Only used by Type::Complete events to specify the duration (in
177         * nanoseconds). Unused by other Types.
178         */
179        uint64_t duration;
180
181        uint32_t thread_id;
182        std::array<TraceArgument::Type, arg_count> arg_types;
183        Type type;
184    };
185
186    /**
187     * ostream operator overload for TraceEvent
188     *
189     * Adds a representation of a TraceEvent to an ostream.
190     *
191     * Used for debugging purposes to stream a TraceEvent to
192     * an output stream like std::cout.
193     *
194     * @param os Output stream to stream to.
195     * @param trace_event TraceEvent to be streamed
196     * @return Output stream passed in
197     */
198    PHOSPHOR_API
199    std::ostream& operator<<(std::ostream& os, const TraceEvent& trace_event);
200
201    static_assert(
202        sizeof(TraceEvent) <= 64,
203        "TraceEvent should fit inside a cache-line for performance reasons");
204    } // namespace phosphor
205