Skip to content

Commit cbae600

Browse files
gdankelfacebook-github-bot
authored andcommitted
Add support for multiple protocols in client API (#251)
Summary: Pull Request resolved: #251 Add a way to add support for multiple protocols and associated logger objects. Reviewed By: ilia-cher Differential Revision: D28579660 fbshipit-source-id: 497c45eca0529ba0620d635c6605fc0f20172d9c
1 parent 3968183 commit cbae600

11 files changed

+145
-30
lines changed

libkineto/src/AbstractConfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class AbstractConfig {
5252
return timestamp_;
5353
}
5454

55+
// Source config string that this was parsed from
5556
const std::string& source() const {
5657
return source_;
5758
}

libkineto/src/ActivityLoggerFactory.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
* All rights reserved.
4+
* This source code is licensed under the BSD-style license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <algorithm>
11+
#include <fmt/format.h>
12+
#include <functional>
13+
#include <map>
14+
#include <string>
15+
16+
namespace KINETO_NAMESPACE {
17+
18+
class ActivityLogger;
19+
20+
class ActivityLoggerFactory {
21+
22+
public:
23+
using FactoryFunc =
24+
std::function<std::unique_ptr<ActivityLogger>(const std::string& url)>;
25+
26+
// Add logger factory for a protocol prefix
27+
void addProtocol(const std::string& protocol, FactoryFunc f) {
28+
factories_[tolower(protocol)] = f;
29+
}
30+
31+
// Create a logger, invoking the factory for the protocol specified in url
32+
std::unique_ptr<ActivityLogger> makeLogger(const std::string& url) const {
33+
std::string protocol = extractProtocol(url);
34+
auto it = factories_.find(tolower(protocol));
35+
if (it != factories_.end()) {
36+
return it->second(stripProtocol(url));
37+
}
38+
throw std::invalid_argument(fmt::format(
39+
"No logger registered for the {} protocol prefix",
40+
protocol));
41+
return nullptr;
42+
}
43+
44+
private:
45+
static std::string tolower(std::string s) {
46+
std::transform(s.begin(), s.end(), s.begin(),
47+
[](unsigned char c) { return std::tolower(c); }
48+
);
49+
return s;
50+
}
51+
52+
static std::string extractProtocol(std::string url) {
53+
return url.substr(0, url.find("://"));
54+
}
55+
56+
static std::string stripProtocol(std::string url) {
57+
size_t pos = url.find("://");
58+
return pos == url.npos ? url : url.substr(pos + 3);
59+
}
60+
61+
std::map<std::string, FactoryFunc> factories_;
62+
};
63+
64+
} // namespace KINETO_NAMESPACE

libkineto/src/ActivityProfilerController.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <chrono>
1111
#include <thread>
1212

13+
#include "ActivityLoggerFactory.h"
1314
#include "ActivityTrace.h"
1415
#include "CuptiActivityInterface.h"
1516
#include "ThreadUtil.h"
@@ -39,25 +40,29 @@ ActivityProfilerController::~ActivityProfilerController() {
3940
VLOG(0) << "Stopped activity profiler";
4041
}
4142

43+
static ActivityLoggerFactory initLoggerFactory() {
44+
ActivityLoggerFactory factory;
45+
factory.addProtocol("file", [](const std::string& url) {
46+
return std::unique_ptr<ActivityLogger>(new ChromeTraceLogger(url));
47+
});
48+
return factory;
49+
}
50+
4251
static ActivityLoggerFactory& loggerFactory() {
43-
static ActivityLoggerFactory factory{nullptr};
52+
static ActivityLoggerFactory factory = initLoggerFactory();
4453
return factory;
4554
}
4655

47-
void ActivityProfilerController::setLoggerFactory(
48-
const ActivityLoggerFactory& factory) {
49-
loggerFactory() = factory;
56+
void ActivityProfilerController::addLoggerFactory(
57+
const std::string& protocol, ActivityLoggerFactory::FactoryFunc factory) {
58+
loggerFactory().addProtocol(protocol, factory);
5059
}
5160

5261
static std::unique_ptr<ActivityLogger> makeLogger(const Config& config) {
5362
if (config.activitiesLogToMemory()) {
5463
return std::make_unique<MemoryTraceLogger>(config);
5564
}
56-
if (loggerFactory()) {
57-
return loggerFactory()(config);
58-
}
59-
return std::make_unique<ChromeTraceLogger>(
60-
config.activitiesLogFile());
65+
return loggerFactory().makeLogger(config.activitiesLogUrl());
6166
}
6267

6368
void ActivityProfilerController::profilerLoop() {
@@ -137,7 +142,7 @@ std::unique_ptr<ActivityTraceInterface> ActivityProfilerController::stopTrace()
137142
auto logger = std::make_unique<MemoryTraceLogger>(profiler_->config());
138143
profiler_->processTrace(*logger);
139144
profiler_->reset();
140-
return std::make_unique<ActivityTrace>(std::move(logger));
145+
return std::make_unique<ActivityTrace>(std::move(logger), loggerFactory());
141146
}
142147

143148
void ActivityProfilerController::addMetadata(

libkineto/src/ActivityProfilerController.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <memory>
1212
#include <thread>
1313

14+
#include "ActivityLoggerFactory.h"
1415
#include "ActivityProfiler.h"
1516
#include "ActivityProfilerInterface.h"
1617
#include "ActivityTraceInterface.h"
@@ -20,9 +21,6 @@ namespace KINETO_NAMESPACE {
2021

2122
class Config;
2223

23-
using ActivityLoggerFactory =
24-
std::function<std::unique_ptr<ActivityLogger>(const Config&)>;
25-
2624
class ActivityProfilerController {
2725
public:
2826
explicit ActivityProfilerController(bool cpuOnly);
@@ -32,7 +30,9 @@ class ActivityProfilerController {
3230

3331
~ActivityProfilerController();
3432

35-
static void setLoggerFactory(const ActivityLoggerFactory& factory);
33+
static void addLoggerFactory(
34+
const std::string& protocol,
35+
ActivityLoggerFactory::FactoryFunc factory);
3636

3737
void scheduleTrace(const Config& config);
3838

libkineto/src/ActivityTrace.h

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <memory>
1111
#include <string>
1212

13+
#include "ActivityLoggerFactory.h"
1314
#include "ActivityTraceInterface.h"
1415
#include "output_json.h"
1516
#include "output_membuf.h"
@@ -18,20 +19,32 @@ namespace libkineto {
1819

1920
class ActivityTrace : public ActivityTraceInterface {
2021
public:
21-
explicit ActivityTrace(std::unique_ptr<MemoryTraceLogger> logger)
22-
: logger_(std::move(logger)) {}
22+
ActivityTrace(
23+
std::unique_ptr<MemoryTraceLogger> tmpLogger,
24+
const ActivityLoggerFactory& factory)
25+
: memLogger_(std::move(tmpLogger)),
26+
loggerFactory_(factory) {
27+
}
2328

2429
const std::vector<std::unique_ptr<TraceActivity>>* activities() override {
25-
return logger_->traceActivities();
30+
return memLogger_->traceActivities();
2631
};
2732

28-
void save(const std::string& path) override {
29-
ChromeTraceLogger chrome_logger(path);
30-
logger_->log(chrome_logger);
33+
void save(const std::string& url) override {
34+
std::string prefix;
35+
// if no protocol is specified, default to file
36+
if (url.find("://") == url.npos) {
37+
prefix = "file://";
38+
}
39+
memLogger_->log(*loggerFactory_.makeLogger(prefix + url));
3140
};
3241

3342
private:
34-
std::unique_ptr<MemoryTraceLogger> logger_;
43+
// Activities are logged into a buffer
44+
std::unique_ptr<MemoryTraceLogger> memLogger_;
45+
46+
// Alternative logger used by save() if protocol prefix is specified
47+
const ActivityLoggerFactory& loggerFactory_;
3548
};
3649

3750
} // namespace libkineto

libkineto/src/Config.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const string kHeartbeatMonitorPeriodKey =
6161
const string kActivitiesEnabledKey = "ACTIVITIES_ENABLED";
6262
const string kActivityTypesKey = "ACTIVITY_TYPES";
6363
const string kActivitiesLogFileKey = "ACTIVITIES_LOG_FILE";
64+
const string kActivitiesLogUrlKey = "ACTIVITIES_LOG_URL";
6465
const string kActivitiesDurationKey = "ACTIVITIES_DURATION_SECS";
6566
const string kActivitiesDurationMsecsKey = "ACTIVITIES_DURATION_MSECS";
6667
const string kActivitiesIterationsKey = "ACTIVITIES_ITERATIONS";
@@ -118,16 +119,16 @@ const string kConfigFile = "/etc/libkineto.conf";
118119
// Max devices supported on any system
119120
constexpr uint8_t kMaxDevices = 8;
120121

121-
static std::map<std::string, std::function<AbstractConfig*(const Config&)>>&
122+
static std::map<std::string, std::function<AbstractConfig*(Config&)>>&
122123
configFactories() {
123-
static std::map<std::string, std::function<AbstractConfig*(const Config&)>>
124+
static std::map<std::string, std::function<AbstractConfig*(Config&)>>
124125
factories;
125126
return factories;
126127
}
127128

128129
void Config::addConfigFactory(
129130
std::string name,
130-
std::function<AbstractConfig*(const Config&)> factory) {
131+
std::function<AbstractConfig*(Config&)> factory) {
131132
configFactories()[name] = factory;
132133
}
133134

@@ -286,6 +287,7 @@ bool Config::handleOption(const std::string& name, std::string& val) {
286287
activityProfilerEnabled_ = toBool(val);
287288
} else if (name == kActivitiesLogFileKey) {
288289
activitiesLogFile_ = val;
290+
activitiesLogUrl_ = fmt::format("file://{}", val);
289291
activitiesOnDemandTimestamp_ = timestamp();
290292
} else if (name == kActivitiesMaxGpuBufferSizeKey) {
291293
activitiesMaxGpuBufferSize_ = toInt32(val) * 1024 * 1024;

libkineto/src/Config.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ class Config : public AbstractConfig {
5353
return activitiesLogFile_;
5454
}
5555

56+
// Log activitiy trace to this url
57+
const std::string& activitiesLogUrl() const {
58+
return activitiesLogUrl_;
59+
}
60+
61+
void setActivitiesLogUrl(const std::string& url) {
62+
activitiesLogUrl_ = url;
63+
}
64+
5665
bool activitiesLogToMemory() const {
5766
return activitiesLogToMemory_;
5867
}
@@ -272,7 +281,7 @@ class Config : public AbstractConfig {
272281

273282
static void addConfigFactory(
274283
std::string name,
275-
std::function<AbstractConfig*(const Config&)> factory);
284+
std::function<AbstractConfig*(Config&)> factory);
276285

277286
void print(std::ostream& s) const;
278287

@@ -338,6 +347,8 @@ class Config : public AbstractConfig {
338347
// The activity profiler settings are all on-demand
339348
std::string activitiesLogFile_;
340349

350+
std::string activitiesLogUrl_;
351+
341352
// Log activities to memory buffer
342353
bool activitiesLogToMemory_{false};
343354

libkineto/src/init.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ int InitializeInjection(void) {
146146
}
147147

148148
void suppressLibkinetoLogMessages() {
149-
SET_LOG_SEVERITY_LEVEL(ERROR);
149+
//SET_LOG_SEVERITY_LEVEL(ERROR);
150+
SET_LOG_VERBOSITY_LEVEL(2, {});
150151
}
151152

152153
} // extern C

libkineto/src/output_json.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ using namespace libkineto;
3030
namespace KINETO_NAMESPACE {
3131

3232
static constexpr int kSchemaVersion = 1;
33+
#ifdef __linux__
34+
static const std::string kDefaultLogFileFmt =
35+
"/tmp/libkineto_activities_{}.json";
36+
#else
37+
static const std::string kDefaultLogFileFmt = "libkineto_activities_{}.json";
38+
#endif
3339

3440
void ChromeTraceLogger::handleTraceStart(
3541
const std::unordered_map<std::string, std::string>& metadata) {
@@ -52,6 +58,10 @@ void ChromeTraceLogger::handleTraceStart(
5258
"traceEvents": [)JSON";
5359
}
5460

61+
static std::string defaultFileName() {
62+
return fmt::format(kDefaultLogFileFmt, processId());
63+
}
64+
5565
void ChromeTraceLogger::openTraceFile() {
5666
traceOf_.open(fileName_, std::ofstream::out | std::ofstream::trunc);
5767
if (!traceOf_) {
@@ -61,8 +71,8 @@ void ChromeTraceLogger::openTraceFile() {
6171
}
6272
}
6373

64-
ChromeTraceLogger::ChromeTraceLogger(const std::string& traceFileName)
65-
: fileName_(traceFileName) {
74+
ChromeTraceLogger::ChromeTraceLogger(const std::string& traceFileName) {
75+
fileName_ = traceFileName.empty() ? defaultFileName() : traceFileName;
6676
traceOf_.clear(std::ios_base::badbit);
6777
openTraceFile();
6878
}

libkineto/src/output_json.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ class ChromeTraceLogger : public libkineto::ActivityLogger {
6868
std::unique_ptr<ActivityBuffers> buffers,
6969
int64_t endTime) override;
7070

71+
std::string traceFileName() const {
72+
return fileName_;
73+
}
74+
7175
private:
7276

7377
#ifdef HAS_CUPTI

libkineto/test/ActivityProfilerTest.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,15 @@ class ActivityProfilerTest : public ::testing::Test {
164164
profiler_ = std::make_unique<ActivityProfiler>(
165165
cuptiActivities_, /*cpu only*/ false);
166166
cfg_ = std::make_unique<Config>();
167+
loggerFactory.addProtocol("file", [](const std::string& url) {
168+
return std::unique_ptr<ActivityLogger>(new ChromeTraceLogger(url));
169+
});
167170
}
168171

169172
std::unique_ptr<Config> cfg_;
170173
MockCuptiActivities cuptiActivities_;
171174
std::unique_ptr<ActivityProfiler> profiler_;
175+
ActivityLoggerFactory loggerFactory;
172176
};
173177

174178

@@ -282,7 +286,7 @@ TEST_F(ActivityProfilerTest, SyncTrace) {
282286
profiler_->reset();
283287

284288
// Wrapper that allows iterating over the activities
285-
ActivityTrace trace(std::move(logger));
289+
ActivityTrace trace(std::move(logger), loggerFactory);
286290
EXPECT_EQ(trace.activities()->size(), 9);
287291
std::map<std::string, int> activityCounts;
288292
std::map<int64_t, int> resourceIds;
@@ -362,7 +366,7 @@ TEST_F(ActivityProfilerTest, CorrelatedTimestampTest) {
362366
auto logger = std::make_unique<MemoryTraceLogger>(*cfg_);
363367
profiler.processTrace(*logger);
364368

365-
ActivityTrace trace(std::move(logger));
369+
ActivityTrace trace(std::move(logger), loggerFactory);
366370
std::map<std::string, int> counts;
367371
for (auto& activity : *trace.activities()) {
368372
counts[activity->name()]++;

0 commit comments

Comments
 (0)