datadog-traceId

onclick to view logs of a trace id

  1. // ==UserScript==
  2. // @name datadog-traceId
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.8
  5. // @description onclick to view logs of a trace id
  6. // @author greatbody
  7. // @include https://app.datadoghq.com/logs*
  8. // @grant unsafeWindow
  9. // @run-at document-end
  10. // ==/UserScript==
  11.  
  12. // 2019年08月28日15:28:57 update author info, and use include
  13. // 2019年09月10日15:04:16 use Datetime at very top that every log has as a backup source of timestamp
  14.  
  15. const baseURL = 'https://app.datadoghq.com';
  16.  
  17. function buildURL(baseURL, params) {
  18. const paramArr = [];
  19. Object.keys(params).forEach((key) => {
  20. paramArr.push(`${key}=${encodeURIComponent(params[key])}`);
  21. });
  22. return `${baseURL}?${paramArr.join('&')}`;
  23. }
  24.  
  25. function buildAttrbutes() {
  26. const rows = document.querySelectorAll('.log_raw-json tr');
  27. const attrs = {};
  28. for (let i = 0; i < rows.length; i += 1) {
  29. const row = rows[i];
  30. const cells = row.innerText.split(/\s+/ig);
  31. if (cells.length === 2) {
  32. attrs[cells[0]] = {
  33. row: row,
  34. value: cells[1]
  35. };
  36. }
  37. }
  38. return attrs;
  39. }
  40.  
  41. function clearExistButton() {
  42. const btn = document.querySelector('#btnOpenTraceIdView');
  43. if (btn) btn.remove();
  44. }
  45.  
  46. function findTraceId() {
  47. const attributes = buildAttrbutes();
  48. const traceIdObj = attributes['traceId'];
  49. let timestampObj = attributes['@timestamp'];
  50.  
  51. if (!timestampObj) {
  52. const dom = document.querySelector('.log_event-panel_status-date__date span.absolute');
  53. timestampObj = {
  54. row: null,
  55. value: dom.innerHTML.replace('at', '')
  56. };
  57. }
  58.  
  59. if (!traceIdObj || !traceIdObj.row) {
  60. return;
  61. }
  62.  
  63. const timestamp = timestampObj.value;
  64. const traceId = traceIdObj.value;
  65. const traceIdRow = traceIdObj.row;
  66. if (traceIdRow.lastTraceId != traceId) {
  67. clearExistButton();
  68. const button = document.createElement('button');
  69. const divBox = document.querySelector('.ui_layout_expandable-block__content');
  70. const boxPreClass = divBox.childNodes[0];
  71. button.innerHTML = 'Open Logs of traceId<div class="ui_form_button__icon-wrapper"><svg class="ui_icons_icon ui_icons_icon--md ui_icons_icon--is-scaled-down ui_form_button__icon--position-right"><title></title><use xlink:href="#ui_icons_export" fill=""></use></svg></div>';
  72. button.id = 'btnOpenTraceIdView';
  73. button.onclick = () => {
  74. const startMilliSec = new Date(timestamp).getTime() - 10 * 60 * 1000;
  75. const destMilliSec = new Date(timestamp).getTime() + 10 * 60 * 1000;
  76. const url = buildURL(`${baseURL}/logs`, {
  77. cols: 'core_host,core_service',
  78. from_ts: startMilliSec,
  79. index: 'main',
  80. live: 'false',
  81. messageDisplay: 'inline',
  82. query: `@traceId:${traceId}`,
  83. stream_sort: 'desc',
  84. to_ts: destMilliSec
  85. });
  86. // eslint-disable-next-line no-undef
  87. unsafeWindow.open(url, '_blank');
  88. };
  89. button.className = 'ui_form_button ui_form_button--md ui_form_button--default log_export-dropdown ui_dialogs_popover167 ui_dialogs_popover__handle';
  90.  
  91. button.style.marginBottom = '5px';
  92. button.style.backgroundColor = '#28a745';
  93. button.style.color = 'white';
  94.  
  95. divBox.insertBefore(button, boxPreClass);
  96.  
  97. traceIdRow.lastTraceId = traceId;
  98. }
  99. }
  100.  
  101. (function () {
  102. 'use strict';
  103.  
  104. setInterval(() => {
  105. findTraceId();
  106. }, 1000);
  107. })();