telemetry.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. const _ = require('lodash')
  2. const { createApolloFetch } = require('apollo-fetch')
  3. const bugsnag = require('@bugsnag/node')
  4. const { v4: uuid } = require('uuid')
  5. const os = require('os')
  6. const fs = require('fs-extra')
  7. /* global WIKI */
  8. module.exports = {
  9. client: null,
  10. enabled: false,
  11. init() {
  12. this.client = bugsnag({
  13. apiKey: WIKI.data.telemetry.BUGSNAG_ID,
  14. appType: 'server',
  15. appVersion: WIKI.version,
  16. autoNotify: false,
  17. collectUserIp: false,
  18. hostname: _.get(WIKI.config, 'telemetry.clientId', uuid()),
  19. notifyReleaseStages: ['production'],
  20. releaseStage: WIKI.IS_DEBUG ? 'development' : 'production',
  21. projectRoot: WIKI.ROOTPATH,
  22. logger: null,
  23. beforeSend: (report) => {
  24. if (!WIKI.telemetry.enabled) { return false }
  25. }
  26. })
  27. WIKI.telemetry = this
  28. if (_.get(WIKI.config, 'telemetry.isEnabled', false) === true && WIKI.config.offline !== true) {
  29. this.enabled = true
  30. this.sendInstanceEvent('STARTUP')
  31. }
  32. },
  33. sendError(err) {
  34. this.client.notify(err)
  35. },
  36. sendEvent(eventCategory, eventAction, eventLabel) {
  37. // TODO
  38. },
  39. async sendInstanceEvent(eventType) {
  40. if (WIKI.devMode) { return }
  41. try {
  42. const apollo = createApolloFetch({
  43. uri: WIKI.config.graphEndpoint
  44. })
  45. // Platform detection
  46. let platform = 'LINUX'
  47. let isDockerized = false
  48. let osname = `${os.type()} ${os.release()}`
  49. switch (os.platform()) {
  50. case 'win32':
  51. platform = 'WINDOWS'
  52. break
  53. case 'darwin':
  54. platform = 'MACOS'
  55. break
  56. default:
  57. platform = 'LINUX'
  58. isDockerized = await fs.pathExists('/.dockerenv')
  59. if (isDockerized) {
  60. osname = 'Docker'
  61. }
  62. break
  63. }
  64. // DB Version detection
  65. let dbVersion = 'Unknown'
  66. switch (WIKI.config.db.type) {
  67. case 'mariadb':
  68. case 'mysql':
  69. const resultMYSQL = await WIKI.models.knex.raw('SELECT VERSION() as version;')
  70. dbVersion = _.get(resultMYSQL, '[0][0].version', 'Unknown')
  71. break
  72. case 'mssql':
  73. const resultMSSQL = await WIKI.models.knex.raw('SELECT @@VERSION as version;')
  74. dbVersion = _.get(resultMSSQL, '[0].version', 'Unknown')
  75. break
  76. case 'postgres':
  77. dbVersion = _.get(WIKI.models, 'knex.client.version', 'Unknown')
  78. break
  79. case 'sqlite':
  80. dbVersion = _.get(WIKI.models, 'knex.client.driver.VERSION', 'Unknown')
  81. break
  82. }
  83. let arch = os.arch().toUpperCase()
  84. if (['ARM', 'ARM64', 'X32', 'X64'].indexOf(arch) < 0) {
  85. arch = 'OTHER'
  86. }
  87. // Send Event
  88. const respStrings = await apollo({
  89. query: `mutation (
  90. $version: String!
  91. $platform: TelemetryPlatform!
  92. $os: String!
  93. $architecture: TelemetryArchitecture!
  94. $dbType: TelemetryDBType!
  95. $dbVersion: String!
  96. $nodeVersion: String!
  97. $cpuCores: Int!
  98. $ramMBytes: Int!,
  99. $clientId: String!,
  100. $event: TelemetryInstanceEvent!
  101. ) {
  102. telemetry {
  103. instance(
  104. version: $version
  105. platform: $platform
  106. os: $os
  107. architecture: $architecture
  108. dbType: $dbType
  109. dbVersion: $dbVersion
  110. nodeVersion: $nodeVersion
  111. cpuCores: $cpuCores
  112. ramMBytes: $ramMBytes
  113. clientId: $clientId
  114. event: $event
  115. ) {
  116. responseResult {
  117. succeeded
  118. errorCode
  119. slug
  120. message
  121. }
  122. }
  123. }
  124. }`,
  125. variables: {
  126. version: WIKI.version,
  127. platform,
  128. os: osname,
  129. architecture: arch,
  130. dbType: WIKI.config.db.type.toUpperCase(),
  131. dbVersion,
  132. nodeVersion: process.version.substr(1),
  133. cpuCores: os.cpus().length,
  134. ramMBytes: Math.round(os.totalmem() / 1024 / 1024),
  135. clientId: WIKI.config.telemetry.clientId,
  136. event: eventType
  137. }
  138. })
  139. const telemetryResponse = _.get(respStrings, 'data.telemetry.instance.responseResult', { succeeded: false, message: 'Unexpected Error' })
  140. if (!telemetryResponse.succeeded) {
  141. WIKI.logger.warn('Failed to send instance telemetry: ' + telemetryResponse.message)
  142. } else {
  143. WIKI.logger.info('Telemetry is active: [ OK ]')
  144. }
  145. } catch (err) {
  146. WIKI.logger.warn(err)
  147. }
  148. },
  149. generateClientId() {
  150. _.set(WIKI.config, 'telemetry.clientId', uuid())
  151. return WIKI.config.telemetry.clientId
  152. }
  153. }