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