xref: /6.6.0/phosphor/src/trace_event.cc (revision d380e59b)
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
18#include "phosphor/trace_event.h"
19
20#include "phosphor/platform/thread.h"
21#include "utils/string_utils.h"
22
23namespace phosphor {
24
25    using namespace std::chrono;
26
27    TraceEvent::TraceEvent(
28        const tracepoint_info* _tpi,
29        uint32_t _thread_id,
30        std::array<TraceArgument, arg_count>&& _args)
31        : tpi(_tpi),
32          args(_args),
33          time(
34              duration_cast<nanoseconds>(steady_clock::now().time_since_epoch())
35                  .count()),
36          duration(0),
37          thread_id(_thread_id) {
38    }
39
40    TraceEvent::TraceEvent(
41            const tracepoint_info* _tpi,
42            uint32_t _thread_id,
43            std::chrono::steady_clock::time_point _start,
44            std::chrono::steady_clock::duration _duration,
45            std::array<TraceArgument, arg_count>&& _args)
46        : tpi(_tpi),
47          args(_args),
48          time(_start.time_since_epoch().count()),
49          duration(_duration.count()),
50          thread_id(_thread_id) {
51    }
52
53    std::string TraceEvent::to_string() const {
54        typedef std::chrono::duration<
55            int,
56            std::ratio_multiply<hours::period, std::ratio<24> >::type>
57            days;
58
59        nanoseconds ttime(time);
60        auto d = duration_cast<days>(ttime);
61        ttime -= d;
62        auto h = duration_cast<hours>(ttime);
63        ttime -= h;
64        auto m = duration_cast<minutes>(ttime);
65        ttime -= m;
66        auto s = duration_cast<seconds>(ttime);
67        ttime -= s;
68        auto us = duration_cast<nanoseconds>(ttime);
69
70        return utils::format_string(
71            "TraceEvent<%dd %02ld:%02ld:%02lld.%09lld, %s, %s, type=%s, "
72            "thread_id=%d, arg1=%s, arg2=%s>",
73            d.count(),
74            h.count(),
75            m.count(),
76            s.count(),
77            us.count(),
78            getCategory(),
79            getName(),
80            typeToString(tpi->type),
81            thread_id,
82            args[0].to_string(tpi->argument_types[0]).c_str(),
83            args[1].to_string(tpi->argument_types[1]).c_str());
84    }
85
86    std::string TraceEvent::to_json() const {
87        std::string output;
88        output += "{\"name\":" + utils::to_json(getName());
89        output += ",\"cat\":" + utils::to_json(getCategory());
90
91        auto type_converted = typeToJSON();
92        output += ",\"ph\":\"" + std::string(type_converted.type) + "\"";
93        output += type_converted.extras;
94
95        output += ",\"ts\":" + std::to_string(time / 1000);
96        output += ",\"pid\":" + std::to_string(platform::getCurrentProcessID()),
97        output += ",\"tid\":" + std::to_string(thread_id);
98
99        output += ",\"args\":{";
100        for (int i = 0; i < arg_count; ++i) {
101            if (tpi->argument_types[i] == TraceArgument::Type::is_none) {
102                break;
103            }
104            if (i != 0) {
105                output += ",";
106            }
107
108            output += utils::to_json(tpi->argument_names[i]) + ":";
109            output += args[i].to_string(tpi->argument_types[i]);
110        }
111        output += "}";
112
113        output += "}";
114        return output;
115    }
116
117    const char* TraceEvent::typeToString(Type type) {
118        switch (type) {
119        case Type::AsyncStart:
120            return "AsyncStart";
121        case Type::AsyncEnd:
122            return "AsyncEnd";
123        case Type::SyncStart:
124            return "SyncStart";
125        case Type::SyncEnd:
126            return "SyncEnd";
127        case Type::Instant:
128            return "Instant";
129        case Type::GlobalInstant:
130            return "GlobalInstant";
131        case Type::Complete:
132            return "Complete";
133        }
134        throw std::invalid_argument(
135            "TraceEvent::typeToString: "
136            "Invalid TraceEvent type");
137    }
138
139    const char* TraceEvent::getName() const {
140        return tpi->name;
141    }
142
143    const char* TraceEvent::getCategory() const {
144        return tpi->category;
145    }
146
147    TraceEvent::Type TraceEvent::getType() const {
148        return tpi->type;
149    }
150
151    uint64_t TraceEvent::getThreadID() const {
152        return thread_id;
153    }
154
155    const std::array<TraceArgument, arg_count>& TraceEvent::getArgs() const {
156        return args;
157    }
158
159    const std::array<TraceArgument::Type, arg_count>& TraceEvent::getArgTypes() const {
160        return tpi->argument_types;
161    }
162
163    const std::array<const char*, arg_count>&
164            TraceEvent::getArgNames() const {
165        return tpi->argument_names;
166    }
167
168    int64_t TraceEvent::getTime() const {
169        return time;
170    }
171
172    uint64_t TraceEvent::getDuration() const {
173        return duration;
174    }
175
176    TraceEvent::ToJsonResult TraceEvent::typeToJSON() const {
177        TraceEvent::ToJsonResult res;
178
179        switch (tpi->type) {
180        case Type::AsyncStart:
181            res.type = "b";
182            res.extras =
183                utils::format_string(",\"id\": \"0x%X\"", args[0].as_int);
184            return res;
185        case Type::AsyncEnd:
186            res.type = "e";
187            res.extras =
188                utils::format_string(",\"id\": \"0x%X\"", args[0].as_int);
189            return res;
190        case Type::SyncStart:
191            res.type = "B";
192            res.extras = "";
193            return res;
194        case Type::SyncEnd:
195            res.type = "E";
196            res.extras = "";
197            return res;
198        case Type::Instant:
199            res.type = "i";
200            res.extras = ",\"s\":\"t\"";
201            return res;
202        case Type::GlobalInstant:
203            res.type = "i";
204            res.extras = ",\"s\":\"g\"";
205            return res;
206        case Type::Complete:
207            res.type = "X";
208            const double duration_us = duration / 1000.0;
209            res.extras = utils::format_string(",\"dur\":%.3f", duration_us);
210            return res;
211        }
212        throw std::invalid_argument(
213            "TraceEvent::typeToJSON: Invalid TraceArgument type");
214    }
215
216    std::ostream& operator<<(std::ostream& os, const TraceEvent& te) {
217        os << te.to_string();
218        return os;
219    }
220}
221