Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Telemetry reporting #187

Merged
merged 29 commits into from
Nov 1, 2021
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
60ac13b
basic telemetry
michalbali256 Aug 26, 2021
9dc53fb
telemetry server crash reporting
michalbali256 Sep 2, 2021
8596b81
...
michalbali256 Sep 7, 2021
557acab
...
michalbali256 Sep 16, 2021
8609e1e
metrics reporting
michalbali256 Sep 22, 2021
13936bd
telemetry key in file, injecting during build
michalbali256 Sep 23, 2021
6bafb2a
telemetry not sent through dap anymore
michalbali256 Sep 24, 2021
0bd3358
alpine telemetry key
michalbali256 Sep 24, 2021
dee9be2
DAP telemetry reported through LSP
michalbali256 Sep 29, 2021
bfb433a
refactor
michalbali256 Sep 30, 2021
ccf7162
error reporting through telemetry
michalbali256 Oct 1, 2021
d819a08
format
michalbali256 Oct 1, 2021
bb1baf6
theia fix
michalbali256 Oct 4, 2021
b277e4b
refactor
michalbali256 Oct 4, 2021
a41ac8c
telemetry test
michalbali256 Oct 7, 2021
7cc7d4a
remove telemetry error details to avoid sending sensitive information
michalbali256 Oct 7, 2021
61a5e05
cmake fix & format
michalbali256 Oct 7, 2021
0c9f70d
telemetry events refinement
michalbali256 Oct 8, 2021
3be7c62
privacy notice for telemetry
michalbali256 Oct 8, 2021
56166ec
npm audit fix
michalbali256 Oct 8, 2021
169a661
Merge remote-tracking branch 'origin/development' into mb/telemetry
michalbali256 Oct 8, 2021
1575cf6
build error
michalbali256 Oct 8, 2021
be9bacc
refactoring / sonar issues
michalbali256 Oct 8, 2021
d343b64
telemetry key written directly to typescript source file
michalbali256 Oct 12, 2021
221b93d
telemetry_info struct represetning telemetry data
michalbali256 Oct 20, 2021
86bbcfd
Merge remote-tracking branch 'origin/mb/telemetry' into mb/telemetry
michalbali256 Oct 21, 2021
37197eb
Merge remote-tracking branch 'origin/development' into mb/telemetry
michalbali256 Oct 21, 2021
bf4a6eb
code smells & nullptr fix
michalbali256 Oct 22, 2021
2eff1ee
refactoring
michalbali256 Oct 26, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ jobs:
run: cd clients/vscode-hlasmplugin && npm ci && npx semantic-release --dry-run
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Inject telemetry key
run: |
cd clients/vscode-hlasmplugin/src
export TEL_KEY=`node -e "console.log(Buffer.from('${{ secrets.TELEMETRY_KEY }}').toString('base64'))"`
sed -i "s/const TELEMETRY_KEY_ENCODED = TELEMETRY_DEFAULT_KEY/const TELEMETRY_KEY_ENCODED = '$TEL_KEY'/" telemetry.ts
- name: Package VSIX
run: cd clients/vscode-hlasmplugin/ && npm ci && npm run package
- name: Get VSIX filename
Expand Down Expand Up @@ -231,6 +236,11 @@ jobs:
run: cd clients/vscode-hlasmplugin && npm ci && npx semantic-release --dry-run
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Inject telemetry key
run: |
cd clients/vscode-hlasmplugin/src
export TEL_KEY=`node -e "console.log(Buffer.from('${{ secrets.TELEMETRY_KEY }}').toString('base64'))"`
sed -i "s/const TELEMETRY_KEY_ENCODED = TELEMETRY_DEFAULT_KEY/const TELEMETRY_KEY_ENCODED = '$TEL_KEY'/" telemetry.ts
- name: Configure
run: mkdir build && cd build && cmake -G Ninja ../
- name: Build
Expand Down
4 changes: 3 additions & 1 deletion benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

project(benchmark)

add_executable(benchmark ${PROJECT_SOURCE_DIR}/benchmark.cpp)
add_executable(benchmark
benchmark.cpp
diagnostic_counter.h)

target_link_libraries(benchmark nlohmann_json::nlohmann_json)

Expand Down
101 changes: 24 additions & 77 deletions benchmark/benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
#include <sstream>
#include <unordered_map>

#include "../language_server/src/parsing_metadata_collector.h"
#include "../language_server/src/parsing_metadata_serialization.h"
#include "config/pgm_conf.h"
#include "diagnostic_counter.h"
#include "nlohmann/json.hpp"
#include "workspace_manager.h"
#include "workspaces/file_impl.h"
Expand Down Expand Up @@ -59,47 +62,11 @@
* - Files - total number of parsed files
*/

using json = nlohmann::json;

class diagnostic_counter : public hlasm_plugin::parser_library::diagnostics_consumer
{
public:
void consume_diagnostics(hlasm_plugin::parser_library::diagnostic_list diagnostics) override
{
for (size_t i = 0; i < diagnostics.diagnostics_size(); i++)
{
auto diag_sev = diagnostics.diagnostics(i).severity();
if (diag_sev == hlasm_plugin::parser_library::diagnostic_severity::error)
error_count++;
else if (diag_sev == hlasm_plugin::parser_library::diagnostic_severity::warning)
warning_count++;
message_counts[diagnostics.diagnostics(i).code()]++;
}
}
using namespace hlasm_plugin;

void clear_counters()
{
error_count = 0;
warning_count = 0;
message_counts.clear();
}

size_t error_count = 0;
size_t warning_count = 0;

std::unordered_map<std::string, unsigned> message_counts;
};

class metrics_collector : public hlasm_plugin::parser_library::performance_metrics_consumer
{
public:
void consume_performance_metrics(const hlasm_plugin::parser_library::performance_metrics& metrics) override
{
metrics_ = metrics;
}
using json = nlohmann::json;

hlasm_plugin::parser_library::performance_metrics metrics_;
};
namespace {

struct all_file_stats
{
Expand All @@ -113,21 +80,6 @@ struct all_file_stats
size_t failed_file_opens = 0;
};

json get_top_messages(const std::unordered_map<std::string, unsigned>& msgs, size_t limit = 3)
{
std::vector<std::pair<std::string, unsigned>> top_msgs(limit);

constexpr const auto cmp_msg = [](const auto& a, const auto& b) { return a.second > b.second; };

const auto last = std::partial_sort_copy(msgs.begin(), msgs.end(), top_msgs.begin(), top_msgs.end(), cmp_msg);
top_msgs.erase(last, top_msgs.end());

json result = json::object();
for (auto&& [key, value] : top_msgs)
result[std::move(key)] = value;
return result;
}

json parse_one_file(const std::string& source_file,
const std::string& ws_folder,
all_file_stats& s,
Expand All @@ -150,10 +102,10 @@ json parse_one_file(const std::string& source_file,

// new workspace manager
hlasm_plugin::parser_library::workspace_manager ws;
diagnostic_counter diag_counter;
hlasm_plugin::benchmark::diagnostic_counter diag_counter;
ws.register_diagnostics_consumer(&diag_counter);
metrics_collector collector;
ws.register_performance_metrics_consumer(&collector);
hlasm_plugin::language_server::parsing_metadata_collector collector;
ws.register_parsing_metadata_consumer(&collector);
// input folder as new workspace
ws.add_workspace(ws_folder.c_str(), ws_folder.c_str());

Expand All @@ -179,42 +131,36 @@ json parse_one_file(const std::string& source_file,
return json({ { "File", source_file }, { "Success", false }, { "Reason", "Crash" } });
}

const auto& metrics = collector.data.metrics;

auto c_end = std::clock();
auto end = std::chrono::high_resolution_clock::now();
auto time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
auto exec_statements = collector.metrics_.open_code_statements + collector.metrics_.copy_statements
+ collector.metrics_.macro_statements + collector.metrics_.lookahead_statements
+ collector.metrics_.reparsed_statements;
auto exec_statements = metrics.open_code_statements + metrics.copy_statements + metrics.macro_statements
+ metrics.lookahead_statements + metrics.reparsed_statements;
s.average_stmt_ms += (exec_statements / (double)time);
s.average_line_ms += collector.metrics_.lines / (double)time;
s.all_files += collector.metrics_.files;
s.average_line_ms += metrics.lines / (double)time;
s.all_files += metrics.files;
s.whole_time += time;

auto top_messages = get_top_messages(diag_counter.message_counts);
auto top_messages = hlasm_plugin::benchmark::get_top_messages(diag_counter.message_counts);

json result({ { "File", source_file },
{ "Success", true },
{ "Errors", diag_counter.error_count },
{ "Warnings", diag_counter.warning_count },
{ "Wall Time (ms)", time },
{ "CPU Time (ms/n)", 1000.0 * (c_end - c_start) / CLOCKS_PER_SEC },
{ "Open Code Statements", collector.metrics_.open_code_statements },
{ "Copy Statements", collector.metrics_.copy_statements },
{ "Macro Statements", collector.metrics_.macro_statements },
{ "Copy Def Statements", collector.metrics_.copy_def_statements },
{ "Macro Def Statements", collector.metrics_.macro_def_statements },
{ "Lookahead Statements", collector.metrics_.lookahead_statements },
{ "Reparsed Statements", collector.metrics_.reparsed_statements },
{ "Continued Statements", collector.metrics_.continued_statements },
{ "Non-continued Statements", collector.metrics_.non_continued_statements },
{ "Executed Statements", exec_statements },
{ "Lines", collector.metrics_.lines },
{ "ExecStatement/ms", exec_statements / (double)time },
{ "Line/ms", collector.metrics_.lines / (double)time },
{ "Files", collector.metrics_.files },
{ "Line/ms", metrics.lines / (double)time },
{ "Top messages", std::move(top_messages) } });

auto first_parse_metrics = collector.metrics_;
json metrics_json(metrics);

result.insert(metrics_json.begin(), metrics_json.end());

auto first_parse_metrics = metrics;
auto first_diag_counter = diag_counter;
long long reparse_time = 0;
// Reparse to benchmark macro caching
Expand Down Expand Up @@ -286,6 +232,7 @@ std::string get_file_message(size_t iter, size_t begin, size_t end, const std::s
s << "[" << base_message << " " << iter << "/(" << begin << "-" << end << ")] ";
return s.str();
}
} // namespace

int main(int argc, char** argv)
{
Expand Down Expand Up @@ -449,4 +396,4 @@ int main(int argc, char** argv)
std::clog << "Parse finished\n\n" << std::endl;
}
return 0;
}
}
72 changes: 72 additions & 0 deletions benchmark/diagnostic_counter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2021 Broadcom.
* The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*/

#ifndef HLASMPLUGIN_LANGUAGESERVER_DIAGNOSTIC_COUNTER_H
#define HLASMPLUGIN_LANGUAGESERVER_DIAGNOSTIC_COUNTER_H

#include "nlohmann/json.hpp"
#include "workspace_manager.h"

namespace hlasm_plugin::benchmark {

class diagnostic_counter : public hlasm_plugin::parser_library::diagnostics_consumer
{
public:
void consume_diagnostics(hlasm_plugin::parser_library::diagnostic_list diagnostics) override
{
for (size_t i = 0; i < diagnostics.diagnostics_size(); i++)
{
if (auto diag_sev = diagnostics.diagnostics(i).severity();
diag_sev == hlasm_plugin::parser_library::diagnostic_severity::error)
error_count++;
else if (diag_sev == hlasm_plugin::parser_library::diagnostic_severity::warning)
warning_count++;
message_counts[diagnostics.diagnostics(i).code()]++;
}
}

void clear_counters()
{
error_count = 0;
warning_count = 0;
message_counts.clear();
}

size_t error_count = 0;
size_t warning_count = 0;

std::unordered_map<std::string, unsigned> message_counts;
};

inline nlohmann::json get_top_messages(const std::unordered_map<std::string, unsigned>& msgs, size_t limit = 3)
{
std::vector<std::pair<std::string, unsigned>> top_msgs(limit);

constexpr const auto cmp_msg = [](const auto& a, const auto& b) { return a.second > b.second; };

const auto last = std::partial_sort_copy(msgs.begin(), msgs.end(), top_msgs.begin(), top_msgs.end(), cmp_msg);
top_msgs.erase(last, top_msgs.end());

nlohmann::json result = nlohmann::json::object();
for (auto&& [key, value] : top_msgs)
result[std::move(key)] = value;
return result;
}


} // namespace hlasm_plugin::benchmark



#endif
27 changes: 27 additions & 0 deletions clients/vscode-hlasmplugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,30 @@ It can by configured using the `preprocessor` key in processor group:
- If you have a question about how to accomplish something with the extension, or come across a problem, file an issue on [GitHub](https://github.com/eclipse/che-che4z-lsp-for-hlasm)
- Contributions are always welcome! Please see our [GitHub](https://github.com/eclipse/che-che4z-lsp-for-hlasm) repository for more information.
- Any and all feedback is appreciated and welcome!

## Privacy Notice
The extensions for Visual Studio Code developed by Broadcom Inc., including its corporate affiliates and subsidiaries, ("Broadcom") are provided free of charge, but in order to better understand and meet its users’ needs, Broadcom may collect, use, analyze and retain anonymous users’ metadata and interaction data, (collectively, “Usage Data”) and aggregate such Usage Data with similar Usage Data of other Broadcom customers. Please find more detailed information in [License and Service Terms & Repository](https://www.broadcom.com/company/legal/licensing).

This data collection uses built-in Microsoft VS Code Telemetry, which can be disabled, at your sole discretion, if you do not want to send Usage Data. See the `telemetry.telemetryLevel` and `telemetry.enableTelemetry` (deprecated) settings of VS Code.

The current release of HLASM Language Support collects anonymous data for the following events:
* Activation of this VS Code extension
* Open and close of files
* Invocation of the following features: Autocomplete, Go to definition, Find all references and Hover
* Launch of Macro tracer and subsequent user interactions with the debugging interface (step into, step over, continue, set breakpoints)
* Malfunctions of the extension

Each such event is logged with the following information:
* Event time
* Operating system and version
* Country or region
* Anonymous user and session ID
* Version numbers of Microsoft VS Code and HLASM Language Support
* Extension response time

Additionally, when a file is opened, the following information are logged:
* Number of diagnostics (errors and warnings)
* Number of files that were parsed including macros and COPY files
* Number of parsed lines
* Whether the diagnostics were suppressed
* Whether matching processor group was found in the configuration
23 changes: 13 additions & 10 deletions clients/vscode-hlasmplugin/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions clients/vscode-hlasmplugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"vscode-test": "^1.3.0"
},
"dependencies": {
"vscode-extension-telemetry": "^0.4.2",
"vscode-languageclient": "^5.2.1"
},
"scripts": {
Expand Down
Loading