├── .gitignore ├── LICENSE ├── README.md ├── build.sh ├── chart.ipynb ├── netmon.cpp ├── netmon.sh └── screenshot ├── chart1.png ├── chart2.png └── usage.png /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | data/ 3 | image/ 4 | .ipynb_checkpoints/ 5 | 6 | *.o 7 | *.obj 8 | 9 | .*DS_Store 10 | 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Real time high precision network monitor 2 | 3 | High precision network monitor, for millisecond/microsecond level monitor. 4 | The fastest sampling interval of the program can be 25μs(microsecond) on my i7 PC. 5 | However, the system update period of the network counters seems to be 400μs. 6 | So it is good enough to set the sample cycle to 400μs. 7 | 8 | - Platform: Linux (tested on Ubuntu 18/16) 9 | - Ver: 0.1 10 | - Ref: [Technical details (Chinese)](https://www.jianshu.com/p/3dcd14c58cbf) 11 | - Updated: 2/24/2019 12 | - Created: 1/9/2019 13 | - Author: loblab 14 | 15 | ![Chart1](https://raw.githubusercontent.com/loblab/netmon/master/screenshot/chart1.png) 16 | 17 | ![Chart2](https://raw.githubusercontent.com/loblab/netmon/master/screenshot/chart2.png) 18 | 19 | ## Features 20 | 21 | - monitor any counters Linux supported. e.g. rx/tx bytes, packets, drop, error 22 | - can set sample cycle/interval & total duration 23 | - support trigger: can set threshold & aggregating function 24 | 25 | ## Usage 26 | 27 | - build.sh: to build the program (from just one source file: netmon.cpp) 28 | - netmon.sh: an example to use the program. modify the options, run it, and you will get a CSV file 29 | - chart.ipynb: a script to draw the chart, run in python notebook with pandas. 30 | You can use Excel to draw the charts as well. 31 | 32 | ![Usage](https://raw.githubusercontent.com/loblab/netmon/master/screenshot/usage.png) 33 | 34 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | OUTNAME=netmon 5 | OUTDIR=bin 6 | 7 | test -d $OUTDIR || mkdir $OUTDIR 8 | g++ -std=c++11 netmon.cpp -o $OUTDIR/$OUTNAME 9 | $OUTDIR/$OUTNAME -h 10 | 11 | -------------------------------------------------------------------------------- /chart.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Charts of network monitor\n", 8 | "Use pandas to draw the CSV data from network monitor." 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 178, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "import pandas as pd\n", 18 | "import matplotlib.pyplot as plt\n", 19 | "def plot_csv(title, csvfile, cumsum=False, saveimg=None):\n", 20 | " csv = pd.read_csv(csvfile)\n", 21 | " df = csv.set_index('Time')\n", 22 | " df.index = df.index.map(lambda x: x / 1000.0)\n", 23 | " if cumsum:\n", 24 | " df = df.cumsum()\n", 25 | " ax = df.plot(figsize=(10, 7))\n", 26 | " ax.xaxis.grid(True, which=\"major\")\n", 27 | " ax.yaxis.grid(True, which=\"major\")\n", 28 | " ax.set_xlabel(\"Time(ms)\")\n", 29 | " ax.set_ylabel(\"Value\")\n", 30 | " ax.set_title(title)\n", 31 | " plt.show()\n", 32 | " if saveimg:\n", 33 | " fig = ax.get_figure()\n", 34 | " fig.savefig(saveimg) " 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 179, 40 | "metadata": {}, 41 | "outputs": [ 42 | { 43 | "data": { 44 | "image/png": "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\n", 45 | "text/plain": [ 46 | "" 47 | ] 48 | }, 49 | "metadata": { 50 | "needs_background": "light" 51 | }, 52 | "output_type": "display_data" 53 | } 54 | ], 55 | "source": [ 56 | "plot_csv(\"Received bytes of NICs\", \"data/netmon.csv\", saveimg=\"image/netmon.png\")" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 180, 62 | "metadata": {}, 63 | "outputs": [ 64 | { 65 | "data": { 66 | "image/png": "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\n", 67 | "text/plain": [ 68 | "" 69 | ] 70 | }, 71 | "metadata": { 72 | "needs_background": "light" 73 | }, 74 | "output_type": "display_data" 75 | } 76 | ], 77 | "source": [ 78 | "plot_csv(\"Accumulated received bytes of NICs\", \"data/netmon.csv\", cumsum=True, saveimg=\"image/netmon-cumsum.png\")" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [] 87 | } 88 | ], 89 | "metadata": { 90 | "kernelspec": { 91 | "display_name": "Python 3", 92 | "language": "python", 93 | "name": "python3" 94 | }, 95 | "language_info": { 96 | "codemirror_mode": { 97 | "name": "ipython", 98 | "version": 3 99 | }, 100 | "file_extension": ".py", 101 | "mimetype": "text/x-python", 102 | "name": "python", 103 | "nbconvert_exporter": "python", 104 | "pygments_lexer": "ipython3", 105 | "version": "3.6.7" 106 | } 107 | }, 108 | "nbformat": 4, 109 | "nbformat_minor": 2 110 | } 111 | -------------------------------------------------------------------------------- /netmon.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 loblab 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace std; 25 | using namespace std::chrono; 26 | 27 | typedef long long int TValue; 28 | typedef long long int TTime; 29 | typedef list Strings; 30 | 31 | namespace NWM { 32 | 33 | int g_debug = 0; 34 | 35 | void trace(const char* msg) 36 | { 37 | if (g_debug > 3) 38 | cout << msg << endl; 39 | } 40 | 41 | typedef TValue (*TAggregator)(TValue* items, int count); 42 | 43 | TValue sum(TValue* items, int count) 44 | { 45 | TValue s = 0; 46 | for (int i = 0; i < count; i++) 47 | s += items[i]; 48 | return s; 49 | } 50 | 51 | TValue avg(TValue* items, int count) 52 | { 53 | return sum(items, count) / count; 54 | } 55 | 56 | TValue max(TValue* items, int count) 57 | { 58 | TValue m = 0; 59 | for (int i = 0; i < count; i++) 60 | if (m < items[i]) 61 | m = items[i]; 62 | return m; 63 | } 64 | 65 | TValue min(TValue* items, int count) 66 | { 67 | TValue m = LLONG_MAX; 68 | for (int i = 0; i < count; i++) 69 | if (m > items[i]) 70 | m = items[i]; 71 | return m; 72 | } 73 | 74 | TValue first(TValue* items, int count) 75 | { 76 | return items[0]; 77 | } 78 | 79 | TValue last(TValue* items, int count) 80 | { 81 | return items[count - 1]; 82 | } 83 | 84 | } // namespace NWM 85 | 86 | class Counter 87 | { 88 | private: 89 | const char* PATH = "/sys/class/net/%s/statistics/%s"; 90 | 91 | private: 92 | string m_name; 93 | string m_prop; 94 | TValue m_base; 95 | ifstream m_file; 96 | 97 | public: 98 | Counter(const string& nic, const string& field) 99 | : m_base(0) 100 | { 101 | cout << "Monitor: " << nic << " - " << field << endl; 102 | m_name = nic; 103 | m_prop = field; 104 | m_name += "-"; 105 | m_name += field; 106 | char path[128]; 107 | snprintf(path, sizeof path, PATH, nic.c_str(), field.c_str()); 108 | if (NWM::g_debug > 2) 109 | cout << "path: " << path << endl; 110 | m_file.open(path); 111 | } 112 | 113 | ~Counter() 114 | { 115 | m_file.close(); 116 | } 117 | 118 | TValue rebase() 119 | { 120 | m_base = 0; 121 | m_base = getValue(); 122 | } 123 | 124 | const string& getName() 125 | { 126 | return m_name; 127 | } 128 | 129 | TValue getValue() 130 | { 131 | const int size = 128; 132 | char buffer[size]; 133 | m_file.clear(); 134 | m_file.seekg(0, ios::beg); 135 | m_file.read(buffer, size); 136 | int len = m_file.gcount() - 1; 137 | buffer[len] = 0; 138 | TValue v = stoll(buffer); 139 | TValue r = v - m_base; 140 | m_base = v; 141 | return r; 142 | } 143 | 144 | }; //class Counter 145 | 146 | typedef list Counters; 147 | 148 | class Monitor 149 | { 150 | private: 151 | time_point m_t1; 152 | Counters m_counters; 153 | TValue* m_values; 154 | ofstream m_ofs; 155 | int m_loop; 156 | bool m_start; 157 | 158 | int m_cycle; 159 | int m_duration; 160 | int m_threshold; 161 | NWM::TAggregator m_func; 162 | 163 | public: 164 | Monitor() 165 | : m_values(nullptr) 166 | , m_loop(0) 167 | , m_start(true) 168 | { 169 | } 170 | 171 | ~Monitor() 172 | { 173 | if (m_values) 174 | { 175 | delete[] m_values; 176 | m_values = nullptr; 177 | } 178 | 179 | for (Counters::iterator it = m_counters.begin(); it != m_counters.end(); it++) 180 | { 181 | Counter* item = *it; 182 | delete item; 183 | } 184 | } 185 | 186 | TTime getTime() 187 | { 188 | auto t2 = system_clock::now(); 189 | auto diff = duration_cast(t2 - m_t1); 190 | return diff.count(); 191 | } 192 | 193 | void addNIC(const string& nic, Strings items) 194 | { 195 | for (Strings::iterator it = items.begin(); it != items.end(); it++) 196 | { 197 | Counter* c; 198 | c = new Counter(nic, *it); 199 | m_counters.push_back(c); 200 | } 201 | } 202 | 203 | void setCycle(int cycle) 204 | { 205 | cout << "Sample cycle: " << cycle << "(µs)" << endl; 206 | m_cycle = cycle; 207 | } 208 | 209 | void setDuration(int dur) 210 | { 211 | cout << "Sample duration: " << dur << "(µs)" << endl; 212 | m_duration = dur; 213 | } 214 | 215 | void setTrigger(int th, const string& func) 216 | { 217 | cout << "Trigger function: " << func << endl; 218 | cout << "Trigger threshold: " << th << endl; 219 | m_threshold = th; 220 | if (func == "min") 221 | m_func = NWM::min; 222 | else if (func == "max") 223 | m_func = NWM::max; 224 | else if (func == "sum") 225 | m_func = NWM::sum; 226 | else if (func == "avg") 227 | m_func = NWM::avg; 228 | else if (func == "first") 229 | m_func = NWM::first; 230 | else if (func == "last") 231 | m_func = NWM::last; 232 | else 233 | { 234 | cout << "Warning: unknown function: '" << func << "', use 'max' instead" << endl; 235 | m_func = NWM::max; 236 | } 237 | } 238 | 239 | void setOutput(const string& filepath) 240 | { 241 | cout << "Output data file: " << filepath << endl; 242 | m_ofs.open(filepath, ofstream::out); 243 | } 244 | 245 | void rebase() 246 | { 247 | for (Counters::iterator it = m_counters.begin(); it != m_counters.end(); it++) 248 | { 249 | Counter* item = *it; 250 | item->rebase(); 251 | } 252 | } 253 | 254 | void sample() 255 | { 256 | int i = 0; 257 | for (Counters::iterator it = m_counters.begin(); it != m_counters.end(); it++) 258 | { 259 | Counter* item = *it; 260 | m_values[i++] = item->getValue(); 261 | } 262 | } 263 | 264 | void report_header() 265 | { 266 | m_ofs << "Time"; 267 | for (Counters::iterator it = m_counters.begin(); it != m_counters.end(); it++) 268 | { 269 | Counter* item = *it; 270 | m_ofs << "," << item->getName(); 271 | } 272 | m_ofs << endl; 273 | } 274 | 275 | void report() 276 | { 277 | int size = m_counters.size(); 278 | m_ofs << getTime(); 279 | for (int i = 0; i < size; i++) 280 | { 281 | m_ofs << "," << m_values[i]; 282 | } 283 | m_ofs << endl; 284 | } 285 | 286 | bool check_start() 287 | { 288 | if (m_start) 289 | return true; 290 | TValue agr = m_func(m_values, m_counters.size()); 291 | if (agr > m_threshold) 292 | { 293 | m_start = true; 294 | m_t1 = system_clock::now(); 295 | m_loop = 0; 296 | } 297 | return m_start; 298 | } 299 | 300 | int run() 301 | { 302 | int size = m_counters.size(); 303 | m_values = new TValue[size]; 304 | 305 | report_header(); 306 | 307 | int total = m_duration / m_cycle; 308 | int i = 0; 309 | m_loop = 0; 310 | rebase(); 311 | m_start = false; // trigger reporting by activity 312 | m_t1 = system_clock::now(); 313 | while (!m_start || i < total) 314 | { 315 | sample(); 316 | if (check_start()) 317 | { 318 | report(); 319 | i++; 320 | } 321 | ++m_loop; 322 | auto t2 = m_t1 + chrono::microseconds(m_cycle * m_loop); 323 | auto now = system_clock::now(); 324 | if (t2 > now) 325 | this_thread::sleep_until(t2); 326 | } 327 | return 0; 328 | } 329 | 330 | }; //class Monitor 331 | 332 | class App 333 | { 334 | protected: 335 | Monitor m_monitor; 336 | 337 | protected: 338 | static const char* version_info; 339 | static const char* help_msg; 340 | static const char* short_options; 341 | static const struct option long_options[]; 342 | 343 | struct 344 | { 345 | int debug; 346 | bool absolute; 347 | string output; 348 | int cycle; 349 | int duration; 350 | int threshold; 351 | string aggregator; 352 | Strings counters; 353 | Strings nics; 354 | } m_args; 355 | 356 | protected: 357 | 358 | void help() 359 | { 360 | cout << help_msg << endl; 361 | } 362 | 363 | void version() 364 | { 365 | cout << version_info << endl; 366 | } 367 | 368 | void list() 369 | { 370 | cout << "TODO" << endl; 371 | } 372 | 373 | int parseArguments(int argc, char **argv); 374 | 375 | int init() 376 | { 377 | for (Strings::iterator it = m_args.nics.begin(); it != m_args.nics.end(); it++) 378 | { 379 | m_monitor.addNIC(*it, m_args.counters); 380 | } 381 | m_monitor.setCycle(m_args.cycle); 382 | m_monitor.setDuration(m_args.duration); 383 | m_monitor.setTrigger(m_args.threshold, m_args.aggregator); 384 | m_monitor.setOutput(m_args.output); 385 | return 0; 386 | } 387 | 388 | void done() 389 | { 390 | cout << "Done." << endl; 391 | } 392 | 393 | int run() 394 | { 395 | cout << "Go!" << endl; 396 | return m_monitor.run(); 397 | } 398 | 399 | public: 400 | App() 401 | { 402 | m_args.debug = 0; 403 | m_args.absolute = false; 404 | m_args.output = "netmon.csv"; 405 | m_args.cycle = 200; 406 | m_args.duration = 1000000; 407 | m_args.threshold = 1000; 408 | m_args.aggregator = "max"; 409 | } 410 | 411 | int main(int argc, char **argv) 412 | { 413 | int rc = parseArguments(argc, argv); 414 | if (rc) 415 | return rc; 416 | NWM::g_debug = m_args.debug; 417 | rc = init(); 418 | if (rc) 419 | return rc; 420 | rc = run(); 421 | done(); 422 | return rc; 423 | } 424 | 425 | }; //class App 426 | 427 | 428 | const char* App::version_info = "nwmon ver 0.1 (1/15/2019), loblab"; 429 | 430 | const char* App::help_msg = 431 | "High precision network monitor\n" 432 | "Usage: nwmon [options] [nic1] [nic2] ...\n" 433 | "Options:\n" 434 | " -h|--help : help message\n" 435 | " -v|--version : version info\n" 436 | " -l|--list : list avaiable counters\n" 437 | " -c|--cycle n : sample cycle, in microsecond\n" 438 | " -d|--duration n : sample duration, in microsecond\n" 439 | " -f|--function s : trigger aggregator function, can be min, max, sum, avg, first, last\n" 440 | " -t|--threshold n : trigger level, if function(counters) > threshold, start recording\n" 441 | " -o|--output s : output file, default: netmon.csv\n" 442 | " -n|--counter s : add a counter. to add multiple: -c couter1 -c counter2\n" 443 | " -D|--debug n : debug info level. default 0 for none, greater for more\n" 444 | //" -a|--absolute : output absolute time. default relative timestamp, i.e. start from 0\n" 445 | "nic1, nic2...:\n" 446 | " network interface names\n" 447 | ; 448 | 449 | const char* App::short_options = "hvlac:d:D:t:o:n:f:"; 450 | 451 | const struct option App::long_options[] = 452 | { 453 | {"help", no_argument, 0, 'h'}, 454 | {"version", no_argument, 0, 'v'}, 455 | {"list", no_argument, 0, 'l'}, 456 | {"absolute", no_argument, 0, 'a'}, 457 | {"debug", required_argument, 0, 'D'}, 458 | {"cycle", required_argument, 0, 'c'}, 459 | {"duration", required_argument, 0, 'd'}, 460 | {"threshold",required_argument, 0, 't'}, 461 | {"function", required_argument, 0, 'f'}, 462 | {"output", required_argument, 0, 'o'}, 463 | {"counter", required_argument, 0, 'n'}, 464 | {0, 0, 0, 0} 465 | }; 466 | 467 | int App::parseArguments(int argc, char **argv) 468 | { 469 | while (1) 470 | { 471 | // getopt_long stores the option index here. 472 | int option_index = 0; 473 | int c = getopt_long(argc, argv, short_options, long_options, &option_index); 474 | // Detect the end of the options. 475 | if (c == -1) 476 | break; 477 | 478 | switch (c) 479 | { 480 | case 0: 481 | // If this option set a flag, do nothing else now. 482 | if (long_options[option_index].flag != 0) 483 | break; 484 | cout << "option " << long_options[option_index].name; 485 | if (optarg) 486 | cout << " with arg " << optarg; 487 | cout << endl; 488 | break; 489 | 490 | case 'h': 491 | help(); 492 | exit(0); 493 | 494 | case 'v': 495 | version(); 496 | exit(0); 497 | 498 | case 'l': 499 | list(); 500 | exit(0); 501 | 502 | case 'a': 503 | m_args.absolute = true; 504 | break; 505 | 506 | case 'c': 507 | m_args.cycle = atoi(optarg); 508 | break; 509 | 510 | case 'd': 511 | m_args.duration = atoi(optarg); 512 | break; 513 | 514 | case 't': 515 | m_args.threshold = atoi(optarg); 516 | break; 517 | 518 | case 'o': 519 | m_args.output = optarg; 520 | break; 521 | 522 | case 'f': 523 | m_args.aggregator = optarg; 524 | break; 525 | 526 | case 'n': 527 | m_args.counters.push_back(optarg); 528 | break; 529 | 530 | case 'D': 531 | m_args.debug = atoi(optarg); 532 | if (m_args.debug >= 9) 533 | cout << "Debug level: " << m_args.debug << endl; 534 | break; 535 | 536 | case '?': 537 | //invalid options return as '?' 538 | // getopt_long already printed an error message. 539 | cout << "Invalid options" << endl; 540 | help(); 541 | return -1; 542 | 543 | default: 544 | help(); 545 | return -1; 546 | } 547 | } 548 | 549 | // non-option ARGV items 550 | int item_count = argc - optind; 551 | if (m_args.debug >= 9) 552 | cout << "Positional argument count: " << item_count << endl; 553 | while (optind < argc) 554 | m_args.nics.push_back(argv[optind++]); 555 | 556 | return 0; 557 | } 558 | 559 | 560 | int main (int argc, char** argv) 561 | { 562 | App app; 563 | return app.main(argc, argv); 564 | } 565 | 566 | -------------------------------------------------------------------------------- /netmon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [ -z "$1" ]; then 5 | DATAFILE="netmon.csv" 6 | else 7 | DATAFILE="$1.csv" 8 | fi 9 | 10 | DATADIR=data 11 | test -d $DATADIR || mkdir -p $DATADIR 12 | 13 | OUTPUT="-o $DATADIR/$DATAFILE" 14 | TIMEOPT="-c 500 -d 700000" 15 | TRIGGER="-t 8000 -f min" 16 | #COUNTERS="-n rx_bytes -n tx_bytes -n rx_packets -n tx_packets" 17 | #COUNTERS="-n rx_bytes -n tx_bytes" 18 | COUNTERS="-n rx_bytes" 19 | #NICS="enp1s0" 20 | NICS="enp1s0f0 enp1s0f1 enp1s0f2 enp1s0f3" 21 | DBG="-D 0" 22 | echo bin/netmon $DBG $TIMEOPT $TRIGGER $OUTPUT $COUNTERS $NICS 23 | bin/netmon $DBG $TIMEOPT $TRIGGER $OUTPUT $COUNTERS $NICS 24 | 25 | -------------------------------------------------------------------------------- /screenshot/chart1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loblab/netmon/dfd31bb7a76c7b6b49d0cc7bc2a8a84b54774156/screenshot/chart1.png -------------------------------------------------------------------------------- /screenshot/chart2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loblab/netmon/dfd31bb7a76c7b6b49d0cc7bc2a8a84b54774156/screenshot/chart2.png -------------------------------------------------------------------------------- /screenshot/usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loblab/netmon/dfd31bb7a76c7b6b49d0cc7bc2a8a84b54774156/screenshot/usage.png --------------------------------------------------------------------------------