@gitpod/gitpod-protocol 0.1.5-se-workspace-for-teams.10 → 0.1.5-se-workspaceid.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/data/gitpod-schema.json +9 -2
  2. package/lib/accounting-protocol.d.ts +0 -1
  3. package/lib/accounting-protocol.d.ts.map +1 -1
  4. package/lib/accounting-protocol.js +10 -11
  5. package/lib/accounting-protocol.js.map +1 -1
  6. package/lib/admin-protocol.d.ts +8 -2
  7. package/lib/admin-protocol.d.ts.map +1 -1
  8. package/lib/admin-protocol.js +2 -13
  9. package/lib/admin-protocol.js.map +1 -1
  10. package/lib/analytics.d.ts +13 -1
  11. package/lib/analytics.d.ts.map +1 -1
  12. package/lib/context-url.js +4 -4
  13. package/lib/context-url.js.map +1 -1
  14. package/lib/context-url.spec.js +45 -48
  15. package/lib/context-url.spec.js.map +1 -1
  16. package/lib/email-protocol.js +4 -4
  17. package/lib/email-protocol.js.map +1 -1
  18. package/lib/encryption/container-module.js +4 -4
  19. package/lib/encryption/container-module.js.map +1 -1
  20. package/lib/encryption/encryption-engine.js +19 -20
  21. package/lib/encryption/encryption-engine.js.map +1 -1
  22. package/lib/encryption/encryption-engine.spec.js +29 -36
  23. package/lib/encryption/encryption-engine.spec.js.map +1 -1
  24. package/lib/encryption/encryption-service.js +29 -43
  25. package/lib/encryption/encryption-service.js.map +1 -1
  26. package/lib/encryption/key-provider.js +25 -30
  27. package/lib/encryption/key-provider.js.map +1 -1
  28. package/lib/env.d.ts +0 -1
  29. package/lib/env.d.ts.map +1 -1
  30. package/lib/env.js +12 -14
  31. package/lib/env.js.map +1 -1
  32. package/lib/gitpod-file-parser.js +25 -41
  33. package/lib/gitpod-file-parser.js.map +1 -1
  34. package/lib/gitpod-file-parser.spec.js +116 -116
  35. package/lib/gitpod-file-parser.spec.js.map +1 -1
  36. package/lib/gitpod-service.d.ts +30 -8
  37. package/lib/gitpod-service.d.ts.map +1 -1
  38. package/lib/gitpod-service.js +149 -295
  39. package/lib/gitpod-service.js.map +1 -1
  40. package/lib/ide-protocol.d.ts +81 -0
  41. package/lib/ide-protocol.d.ts.map +1 -0
  42. package/lib/ide-protocol.js +8 -0
  43. package/lib/ide-protocol.js.map +1 -0
  44. package/lib/index.d.ts +2 -0
  45. package/lib/index.d.ts.map +1 -1
  46. package/lib/index.js +2 -0
  47. package/lib/index.js.map +1 -1
  48. package/lib/messaging/browser/connection.d.ts +3 -3
  49. package/lib/messaging/browser/connection.d.ts.map +1 -1
  50. package/lib/messaging/browser/connection.js +172 -35
  51. package/lib/messaging/browser/connection.js.map +1 -1
  52. package/lib/messaging/browser/window-connection.js +35 -55
  53. package/lib/messaging/browser/window-connection.js.map +1 -1
  54. package/lib/messaging/client-call-metrics.js +17 -18
  55. package/lib/messaging/client-call-metrics.js.map +1 -1
  56. package/lib/messaging/connection-error-handler.js +11 -23
  57. package/lib/messaging/connection-error-handler.js.map +1 -1
  58. package/lib/messaging/error.d.ts +1 -1
  59. package/lib/messaging/error.d.ts.map +1 -1
  60. package/lib/messaging/error.js +2 -2
  61. package/lib/messaging/error.js.map +1 -1
  62. package/lib/messaging/handler.d.ts +10 -0
  63. package/lib/messaging/handler.d.ts.map +1 -1
  64. package/lib/messaging/node/connection.d.ts +0 -10
  65. package/lib/messaging/node/connection.d.ts.map +1 -1
  66. package/lib/messaging/node/connection.js +11 -49
  67. package/lib/messaging/node/connection.js.map +1 -1
  68. package/lib/messaging/proxy-factory.d.ts +2 -0
  69. package/lib/messaging/proxy-factory.d.ts.map +1 -1
  70. package/lib/messaging/proxy-factory.js +73 -160
  71. package/lib/messaging/proxy-factory.js.map +1 -1
  72. package/lib/oss-allowlist.d.ts +14 -0
  73. package/lib/oss-allowlist.d.ts.map +1 -0
  74. package/lib/oss-allowlist.js +8 -0
  75. package/lib/oss-allowlist.js.map +1 -0
  76. package/lib/permission.d.ts +1 -2
  77. package/lib/permission.d.ts.map +1 -1
  78. package/lib/permission.js +12 -13
  79. package/lib/permission.js.map +1 -1
  80. package/lib/plans.d.ts +1 -1
  81. package/lib/plans.d.ts.map +1 -1
  82. package/lib/plans.js +38 -57
  83. package/lib/plans.js.map +1 -1
  84. package/lib/protocol.d.ts +11 -7
  85. package/lib/protocol.d.ts.map +1 -1
  86. package/lib/protocol.js +44 -114
  87. package/lib/protocol.js.map +1 -1
  88. package/lib/snapshot-url.d.ts +14 -0
  89. package/lib/snapshot-url.d.ts.map +1 -0
  90. package/lib/snapshot-url.js +26 -0
  91. package/lib/snapshot-url.js.map +1 -0
  92. package/lib/snapshot-url.spec.d.ts +7 -0
  93. package/lib/snapshot-url.spec.d.ts.map +1 -0
  94. package/lib/snapshot-url.spec.js +41 -0
  95. package/lib/snapshot-url.spec.js.map +1 -0
  96. package/lib/team-subscription-protocol.js +13 -13
  97. package/lib/team-subscription-protocol.js.map +1 -1
  98. package/lib/teams-projects-protocol.d.ts +11 -1
  99. package/lib/teams-projects-protocol.d.ts.map +1 -1
  100. package/lib/teams-projects-protocol.js +4 -15
  101. package/lib/teams-projects-protocol.js.map +1 -1
  102. package/lib/util/analytics.d.ts.map +1 -1
  103. package/lib/util/analytics.js +35 -26
  104. package/lib/util/analytics.js.map +1 -1
  105. package/lib/util/async-iterator.js +55 -133
  106. package/lib/util/async-iterator.js.map +1 -1
  107. package/lib/util/cancelable.js +17 -59
  108. package/lib/util/cancelable.js.map +1 -1
  109. package/lib/util/date-time.js +8 -8
  110. package/lib/util/date-time.js.map +1 -1
  111. package/lib/util/deferred.js +10 -12
  112. package/lib/util/deferred.js.map +1 -1
  113. package/lib/util/disposable.js +26 -39
  114. package/lib/util/disposable.js.map +1 -1
  115. package/lib/util/event.js +58 -74
  116. package/lib/util/event.js.map +1 -1
  117. package/lib/util/garbage-collected-cache.d.ts +1 -0
  118. package/lib/util/garbage-collected-cache.d.ts.map +1 -1
  119. package/lib/util/garbage-collected-cache.js +26 -46
  120. package/lib/util/garbage-collected-cache.js.map +1 -1
  121. package/lib/util/generate-workspace-id.d.ts +1 -1
  122. package/lib/util/generate-workspace-id.d.ts.map +1 -1
  123. package/lib/util/generate-workspace-id.js +28 -68
  124. package/lib/util/generate-workspace-id.js.map +1 -1
  125. package/lib/util/generate-workspace-id.spec.js +56 -78
  126. package/lib/util/generate-workspace-id.spec.js.map +1 -1
  127. package/lib/util/gitpod-cookie.d.ts +20 -0
  128. package/lib/util/gitpod-cookie.d.ts.map +1 -0
  129. package/lib/util/gitpod-cookie.js +44 -0
  130. package/lib/util/gitpod-cookie.js.map +1 -0
  131. package/lib/util/gitpod-host-url.d.ts +1 -0
  132. package/lib/util/gitpod-host-url.d.ts.map +1 -1
  133. package/lib/util/gitpod-host-url.js +96 -103
  134. package/lib/util/gitpod-host-url.js.map +1 -1
  135. package/lib/util/gitpod-host-url.spec.js +87 -135
  136. package/lib/util/gitpod-host-url.spec.js.map +1 -1
  137. package/lib/util/grpc.js +3 -3
  138. package/lib/util/grpc.js.map +1 -1
  139. package/lib/util/jaeger-client-types.d.ts +68 -0
  140. package/lib/util/jaeger-client-types.d.ts.map +1 -0
  141. package/lib/util/jaeger-client-types.js +8 -0
  142. package/lib/util/jaeger-client-types.js.map +1 -0
  143. package/lib/util/logging.d.ts +32 -32
  144. package/lib/util/logging.d.ts.map +1 -1
  145. package/lib/util/logging.js +68 -109
  146. package/lib/util/logging.js.map +1 -1
  147. package/lib/util/make-link.js +2 -2
  148. package/lib/util/make-link.js.map +1 -1
  149. package/lib/util/parse-workspace-id.d.ts +10 -0
  150. package/lib/util/parse-workspace-id.d.ts.map +1 -1
  151. package/lib/util/parse-workspace-id.js +31 -7
  152. package/lib/util/parse-workspace-id.js.map +1 -1
  153. package/lib/util/parse-workspace-id.spec.d.ts +4 -0
  154. package/lib/util/parse-workspace-id.spec.d.ts.map +1 -1
  155. package/lib/util/parse-workspace-id.spec.js +123 -84
  156. package/lib/util/parse-workspace-id.spec.js.map +1 -1
  157. package/lib/util/queue.js +16 -55
  158. package/lib/util/queue.js.map +1 -1
  159. package/lib/util/queue.spec.js +144 -288
  160. package/lib/util/queue.spec.js.map +1 -1
  161. package/lib/util/repeat.d.ts +15 -0
  162. package/lib/util/repeat.d.ts.map +1 -0
  163. package/lib/util/repeat.js +55 -0
  164. package/lib/util/repeat.js.map +1 -0
  165. package/lib/util/safe-promise.js +9 -12
  166. package/lib/util/safe-promise.js.map +1 -1
  167. package/lib/util/semaphore.js +15 -46
  168. package/lib/util/semaphore.js.map +1 -1
  169. package/lib/util/skip-if.js +6 -6
  170. package/lib/util/skip-if.js.map +1 -1
  171. package/lib/util/timeutil.js +16 -16
  172. package/lib/util/timeutil.js.map +1 -1
  173. package/lib/util/timeutil.spec.js +21 -24
  174. package/lib/util/timeutil.spec.js.map +1 -1
  175. package/lib/util/tracing.d.ts +50 -5
  176. package/lib/util/tracing.d.ts.map +1 -1
  177. package/lib/util/tracing.js +171 -63
  178. package/lib/util/tracing.js.map +1 -1
  179. package/lib/util/tracing.spec.d.ts +7 -0
  180. package/lib/util/tracing.spec.d.ts.map +1 -0
  181. package/lib/util/tracing.spec.js +121 -0
  182. package/lib/util/tracing.spec.js.map +1 -0
  183. package/lib/util/workspace-port-authentication.js +2 -2
  184. package/lib/util/workspace-port-authentication.js.map +1 -1
  185. package/lib/workspace-cluster.d.ts +11 -1
  186. package/lib/workspace-cluster.d.ts.map +1 -1
  187. package/lib/workspace-cluster.js +3 -3
  188. package/lib/workspace-cluster.js.map +1 -1
  189. package/lib/workspace-instance.d.ts +4 -2
  190. package/lib/workspace-instance.d.ts.map +1 -1
  191. package/lib/wsready.js +1 -1
  192. package/package.json +20 -12
  193. package/pkg-yarn.lock +12 -7
  194. package/src/accounting-protocol.ts +1 -3
  195. package/src/admin-protocol.ts +9 -3
  196. package/src/analytics.ts +16 -1
  197. package/src/email-protocol.ts +1 -1
  198. package/src/env.ts +0 -1
  199. package/src/gitpod-service.ts +30 -9
  200. package/src/ide-protocol.ts +92 -0
  201. package/src/index.ts +2 -0
  202. package/src/messaging/browser/connection.ts +176 -10
  203. package/src/messaging/error.ts +2 -2
  204. package/src/messaging/handler.ts +12 -0
  205. package/src/messaging/node/connection.ts +1 -45
  206. package/src/messaging/proxy-factory.ts +10 -4
  207. package/src/oss-allowlist.ts +15 -0
  208. package/src/permission.ts +0 -1
  209. package/src/protocol.ts +13 -8
  210. package/src/snapshot-url.spec.ts +25 -0
  211. package/src/snapshot-url.ts +27 -0
  212. package/src/team-subscription-protocol.ts +1 -1
  213. package/src/teams-projects-protocol.ts +14 -2
  214. package/src/util/analytics.ts +17 -1
  215. package/src/util/garbage-collected-cache.ts +7 -1
  216. package/src/util/generate-workspace-id.spec.ts +16 -0
  217. package/src/util/generate-workspace-id.ts +19 -2
  218. package/src/util/gitpod-cookie.ts +39 -0
  219. package/src/util/gitpod-host-url.ts +12 -8
  220. package/src/util/grpc.ts +3 -3
  221. package/src/util/jaeger-client-types.ts +102 -0
  222. package/src/util/logging.ts +65 -52
  223. package/src/util/parse-workspace-id.spec.ts +21 -1
  224. package/src/util/parse-workspace-id.ts +32 -6
  225. package/src/util/repeat.ts +45 -0
  226. package/src/util/tracing.spec.ts +83 -0
  227. package/src/util/tracing.ts +157 -18
  228. package/src/workspace-cluster.ts +8 -1
  229. package/src/workspace-instance.ts +12 -6
  230. package/src/wsready.ts +1 -1
  231. package/lib/util/repeater.d.ts +0 -22
  232. package/lib/util/repeater.d.ts.map +0 -1
  233. package/lib/util/repeater.js +0 -118
  234. package/lib/util/repeater.js.map +0 -1
  235. package/src/util/jaeger-client.d.ts +0 -105
  236. package/src/util/repeater.ts +0 -49
@@ -30,66 +30,66 @@ export interface LogPayload {
30
30
  };
31
31
 
32
32
  export namespace log {
33
- export function error(context: LogContext, message: string, error: Error, payload: LogPayload): void;
34
- export function error(context: LogContext, message: string, error: Error): void;
33
+ export function error(context: LogContext, message: string, error: any, payload: LogPayload): void;
34
+ export function error(context: LogContext, message: string, error: any): void;
35
35
  export function error(context: LogContext, message: string, payload: LogPayload): void;
36
36
  export function error(context: LogContext, message: string): void;
37
- export function error(context: LogContext, error: Error, payload: LogPayload): void;
38
- export function error(context: LogContext, error: Error): void;
39
- export function error(message: string, error: Error, payload: LogPayload): void;
40
- export function error(message: string, error: Error): void;
37
+ export function error(context: LogContext, error: any, payload: LogPayload): void;
38
+ export function error(context: LogContext, error: any): void;
39
+ export function error(message: string, error: any, payload: LogPayload): void;
40
+ export function error(message: string, error: any): void;
41
41
  export function error(message: string, payload: LogPayload): void;
42
42
  export function error(message: string): void;
43
- export function error(error: Error, payload: LogPayload): void;
44
- export function error(error: Error): void;
43
+ export function error(error: any, payload: LogPayload): void;
44
+ export function error(error: any): void;
45
45
  export function error(...args: any[]): void {
46
46
  errorLog(false, args);
47
47
  }
48
48
 
49
- export function warn(context: LogContext, message: string, error: Error, payload: LogPayload): void;
50
- export function warn(context: LogContext, message: string, error: Error): void;
49
+ export function warn(context: LogContext, message: string, error: any, payload: LogPayload): void;
50
+ export function warn(context: LogContext, message: string, error: any): void;
51
51
  export function warn(context: LogContext, message: string, payload: LogPayload): void;
52
52
  export function warn(context: LogContext, message: string): void;
53
- export function warn(context: LogContext, error: Error, payload: LogPayload): void;
54
- export function warn(context: LogContext, error: Error): void;
55
- export function warn(message: string, error: Error, payload: LogPayload): void;
56
- export function warn(message: string, error: Error): void;
53
+ export function warn(context: LogContext, error: any, payload: LogPayload): void;
54
+ export function warn(context: LogContext, error: any): void;
55
+ export function warn(message: string, error: any, payload: LogPayload): void;
56
+ export function warn(message: string, error: any): void;
57
57
  export function warn(message: string, payload: LogPayload): void;
58
58
  export function warn(message: string): void;
59
- export function warn(error: Error, payload: LogPayload): void;
60
- export function warn(error: Error): void;
59
+ export function warn(error: any, payload: LogPayload): void;
60
+ export function warn(error: any): void;
61
61
  export function warn(...args: any[]): void {
62
62
  warnLog(false, args);
63
63
  }
64
64
 
65
- export function info(context: LogContext, message: string, error: Error, payload: LogPayload): void;
66
- export function info(context: LogContext, message: string, error: Error): void;
65
+ export function info(context: LogContext, message: string, error: any, payload: LogPayload): void;
66
+ export function info(context: LogContext, message: string, error: any): void;
67
67
  export function info(context: LogContext, message: string, payload: LogPayload): void;
68
68
  export function info(context: LogContext, message: string): void;
69
- export function info(context: LogContext, error: Error, payload: LogPayload): void;
70
- export function info(context: LogContext, error: Error): void;
71
- export function info(message: string, error: Error, payload: LogPayload): void;
72
- export function info(message: string, error: Error): void;
69
+ export function info(context: LogContext, error: any, payload: LogPayload): void;
70
+ export function info(context: LogContext, error: any): void;
71
+ export function info(message: string, error: any, payload: LogPayload): void;
72
+ export function info(message: string, error: any): void;
73
73
  export function info(message: string, payload: LogPayload): void;
74
74
  export function info(message: string): void;
75
- export function info(error: Error, payload: LogPayload): void;
76
- export function info(error: Error): void;
75
+ export function info(error: any, payload: LogPayload): void;
76
+ export function info(error: any): void;
77
77
  export function info(...args: any[]): void {
78
78
  infoLog(false, args);
79
79
  }
80
80
 
81
- export function debug(context: LogContext, message: string, error: Error, payload: LogPayload): void;
82
- export function debug(context: LogContext, message: string, error: Error): void;
81
+ export function debug(context: LogContext, message: string, error: any, payload: LogPayload): void;
82
+ export function debug(context: LogContext, message: string, error: any): void;
83
83
  export function debug(context: LogContext, message: string, payload: LogPayload): void;
84
84
  export function debug(context: LogContext, message: string): void;
85
- export function debug(context: LogContext, error: Error, payload: LogPayload): void;
86
- export function debug(context: LogContext, error: Error): void;
87
- export function debug(message: string, error: Error, payload: LogPayload): void;
88
- export function debug(message: string, error: Error): void;
85
+ export function debug(context: LogContext, error: any, payload: LogPayload): void;
86
+ export function debug(context: LogContext, error: any): void;
87
+ export function debug(message: string, error: any, payload: LogPayload): void;
88
+ export function debug(message: string, error: any): void;
89
89
  export function debug(message: string, payload: LogPayload): void;
90
90
  export function debug(message: string): void;
91
- export function debug(error: Error, payload: LogPayload): void;
92
- export function debug(error: Error): void;
91
+ export function debug(error: any, payload: LogPayload): void;
92
+ export function debug(error: any): void;
93
93
  export function debug(...args: any[]): void {
94
94
  debugLog(false, args);
95
95
  }
@@ -107,24 +107,32 @@ export namespace log {
107
107
  export function setLogLevel(logLevel: LogrusLogLevel | undefined) {
108
108
  jsonLogging = true;
109
109
 
110
- const noop = () => {};
111
- const setLog = (logFunc: (calleViaConsole: boolean, args: any[]) => void, funcLvl: LogrusLogLevel): (() => void) => {
112
- if (LogrusLogLevel.isGreatherOrEqual(funcLvl, logLevel)) {
113
- return function (...args: any[]): void {
114
- logFunc(true, args);
115
- };
116
- } else {
117
- return noop;
118
- }
119
- };
120
-
121
- console.error = setLog(errorLog, "error");
122
- console.warn = setLog(warnLog, "warning");
123
- console.info = setLog(infoLog, "info");
124
- console.debug = setLog(debugLog, "debug");
110
+ console.error = function (...args: any[]): void {
111
+ errorLog(true, args);
112
+ }
113
+ console.warn = function (...args: any[]): void {
114
+ warnLog(true, args);
115
+ }
116
+ console.info = function (...args: any[]): void {
117
+ infoLog(true, args);
118
+ }
119
+ console.debug = function (...args: any[]): void {
120
+ debugLog(true, args);
121
+ }
125
122
 
126
123
  console.log = console.info;
127
124
  // FIXME wrap also other console methods (e.g. trace())
125
+
126
+ // set/unset log functions based on loglevel so we only have to evaluate once, not every call
127
+ const noop = () => {};
128
+ const setLog = (logFunc: DoLogFunction, funcLevel: LogrusLogLevel): DoLogFunction => {
129
+ return LogrusLogLevel.isGreatherOrEqual(funcLevel, logLevel) ? logFunc : noop;
130
+ };
131
+
132
+ errorLog = setLog(doErrorLog, "error");
133
+ warnLog = setLog(doWarnLog, "warning");
134
+ infoLog = setLog(doInfoLog, "info");
135
+ debugLog = setLog(doDebugLog, "debug");
128
136
  }
129
137
 
130
138
  export function resetToDefaultLogging(): void {
@@ -142,19 +150,25 @@ export namespace log {
142
150
  }
143
151
  }
144
152
 
145
- function errorLog(calledViaConsole: boolean, args: any[]): void {
153
+ type DoLogFunction = (calledViaConsole: boolean, args: any[]) => void;
154
+
155
+ let errorLog = doErrorLog;
156
+ function doErrorLog(calledViaConsole: boolean, args: any[]): void {
146
157
  doLog(calledViaConsole, errorConsoleLog, 'ERROR', args);
147
158
  }
148
159
 
149
- function warnLog(calledViaConsole: boolean, args: any[]): void {
160
+ let warnLog = doWarnLog;
161
+ function doWarnLog(calledViaConsole: boolean, args: any[]): void {
150
162
  doLog(calledViaConsole, warnConsoleLog, 'WARNING', args);
151
163
  }
152
164
 
153
- function infoLog(calledViaConsole: boolean, args: any[]): void {
165
+ let infoLog = doInfoLog;
166
+ function doInfoLog(calledViaConsole: boolean, args: any[]): void {
154
167
  doLog(calledViaConsole, infoConsoleLog, 'INFO', args);
155
168
  }
156
169
 
157
- function debugLog(calledViaConsole: boolean, args: any[]): void {
170
+ let debugLog = doDebugLog;
171
+ function doDebugLog(calledViaConsole: boolean, args: any[]): void {
158
172
  doLog(calledViaConsole, debugConsoleLog, 'DEBUG', args);
159
173
  }
160
174
 
@@ -294,7 +308,6 @@ function makeLogItem(severity: GoogleLogSeverity, context: LogContext | undefine
294
308
  severity,
295
309
  time: new Date().toISOString(),
296
310
  environment: process.env.KUBE_STAGE,
297
- region: process.env.GITPOD_REGION,
298
311
  context,
299
312
  message,
300
313
  error,
@@ -6,7 +6,7 @@
6
6
 
7
7
  import * as chai from 'chai';
8
8
  import { suite, test } from 'mocha-typescript';
9
- import { parseWorkspaceIdFromHostname } from './parse-workspace-id';
9
+ import { matchesInstanceIdOrLegacyWorkspaceIdExactly, matchesNewWorkspaceIdExactly, parseWorkspaceIdFromHostname } from './parse-workspace-id';
10
10
  const expect = chai.expect;
11
11
 
12
12
  @suite
@@ -52,5 +52,25 @@ export class ParseWorkspaceIdTest {
52
52
  const actual = parseWorkspaceIdFromHostname("webview-3000-ca81a50f-09d7-465c-acd9-264a747d5351.ws-eu01.some.subdomain.somehost.com");
53
53
  expect(actual).to.equal("ca81a50f-09d7-465c-acd9-264a747d5351");
54
54
  }
55
+
56
+ // match - instance ID
57
+ @test public matchesInstanceIdOrLegacyWorkspaceIdExactly_positive() {
58
+ const actual = matchesInstanceIdOrLegacyWorkspaceIdExactly("b7e0eaf8-ec73-44ec-81ea-04859263b656");
59
+ expect(actual).to.be.true;
60
+ }
61
+ @test public matchesInstanceIdOrLegacyWorkspaceIdExactly_negative() {
62
+ const actual = matchesInstanceIdOrLegacyWorkspaceIdExactly("b7e0eaf8-ec73-44ec-81a-04859263b656");
63
+ expect(actual).to.be.false;
64
+ }
65
+
66
+ // match - new workspace ID
67
+ @test public matchesWorkspaceIdExactly_new_positive() {
68
+ const actual = matchesNewWorkspaceIdExactly("moccasin-ferret-155799b3");
69
+ expect(actual).to.be.true;
70
+ }
71
+ @test public matchesWorkspaceIdExactly_new_negative() {
72
+ const actual = matchesNewWorkspaceIdExactly("moccasin-ferret-15599b3");
73
+ expect(actual).to.be.false;
74
+ }
55
75
  }
56
76
  module.exports = new ParseWorkspaceIdTest()
@@ -4,6 +4,14 @@
4
4
  * See License-AGPL.txt in the project root for license information.
5
5
  */
6
6
 
7
+ const REGEX_WORKSPACE_ID = /[0-9a-z]{2,16}-[0-9a-z]{2,16}-[0-9a-z]{8}/;
8
+ const REGEX_WORKSPACE_ID_EXACT = new RegExp(`^${REGEX_WORKSPACE_ID.source}$`);
9
+ // We need to parse the workspace id precisely here to get the case '<some-str>-<port>-<wsid>.ws.' right
10
+ const REGEX_WORKSPACE_ID_FROM_HOSTNAME = new RegExp(`(${REGEX_WORKSPACE_ID.source})\.ws`);
11
+
12
+ const REGEX_WORKSPACE_ID_LEGACY = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/;
13
+ const REGEX_WORKSPACE_ID_LEGACY_EXACT = new RegExp(`^${REGEX_WORKSPACE_ID_LEGACY.source}$`);
14
+ const REGEX_WORKSPACE_ID_LEGACY_FROM_HOSTNAME = new RegExp(`(${REGEX_WORKSPACE_ID_LEGACY.source})\.ws`);
7
15
 
8
16
  /**
9
17
  * Hostname may be of the form:
@@ -13,17 +21,35 @@
13
21
  * @param hostname The hostname the request is headed to
14
22
  */
15
23
  export const parseWorkspaceIdFromHostname = function(hostname: string) {
16
- // We need to parse the workspace id precisely here to get the case '<some-str>-<port>-<wsid>.ws.' right
17
- const wsIdExpression = /([0-9a-z]{2,16}-[0-9a-z]{2,16}-[0-9a-z]{8})\.ws/g;
18
- const match = wsIdExpression.exec(hostname);
24
+ const match = REGEX_WORKSPACE_ID_FROM_HOSTNAME.exec(hostname);
19
25
  if (match && match.length >= 2) {
20
26
  return match[1];
21
27
  } else {
22
- const legacyUrlFormat = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.ws/g;
23
- const legacyMatch = legacyUrlFormat.exec(hostname);
28
+ const legacyMatch = REGEX_WORKSPACE_ID_LEGACY_FROM_HOSTNAME.exec(hostname);
24
29
  if (legacyMatch && legacyMatch.length >= 2) {
25
30
  return legacyMatch[1];
26
31
  }
27
32
  return undefined;
28
33
  }
29
- }
34
+ };
35
+
36
+ /** Equalls UUIDv4 (and REGEX_WORKSPACE_ID_LEGACY!) */
37
+ const REGEX_INSTANCE_ID = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/;
38
+ const REGEX_INSTANCE_ID_EXACT = new RegExp(`^${REGEX_INSTANCE_ID.source}$`);
39
+
40
+ /**
41
+ * @param maybeId
42
+ * @returns
43
+ */
44
+ export const matchesInstanceIdOrLegacyWorkspaceIdExactly = function(maybeId: string): boolean {
45
+ return REGEX_INSTANCE_ID_EXACT.test(maybeId)
46
+ || REGEX_WORKSPACE_ID_LEGACY_EXACT.test(maybeId);
47
+ };
48
+
49
+ /**
50
+ * @param maybeWorkspaceId
51
+ * @returns
52
+ */
53
+ export const matchesNewWorkspaceIdExactly = function(maybeWorkspaceId: string): boolean {
54
+ return REGEX_WORKSPACE_ID_EXACT.test(maybeWorkspaceId);
55
+ };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Copyright (c) 2021 Gitpod GmbH. All rights reserved.
3
+ * Licensed under the GNU Affero General Public License (AGPL).
4
+ * See License-AGPL.txt in the project root for license information.
5
+ */
6
+
7
+ import { Disposable } from "..";
8
+ import { log } from "./logging";
9
+
10
+ /**
11
+ * This intends to be a drop-in replacement for 'setInterval' implemented with a 'setTimeout' chain
12
+ * to ensure we're not creating more timeouts than we can process.
13
+ * @param op
14
+ * @param everyMilliseconds
15
+ * @returns
16
+ */
17
+ export function repeat(op: () => Promise<void> | void, everyMilliseconds: number): Disposable {
18
+ let timer: NodeJS.Timeout | undefined = undefined;
19
+ let stopped = false;
20
+ const repeated = () => {
21
+ if (stopped) {
22
+ // in case we missed the clearTimeout i 'await'
23
+ return;
24
+ }
25
+
26
+ timer = setTimeout(async () => {
27
+ try {
28
+ await op();
29
+ } catch (err) {
30
+ // catch error here to
31
+ log.error(err);
32
+ }
33
+
34
+ repeated(); // chain ourselves - after the 'await'
35
+ }, everyMilliseconds);
36
+ };
37
+ repeated();
38
+
39
+ return Disposable.create(() => {
40
+ stopped = true;
41
+ if (timer) {
42
+ clearTimeout(timer);
43
+ }
44
+ });
45
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Copyright (c) 2021 Gitpod GmbH. All rights reserved.
3
+ * Licensed under the GNU Affero General Public License (AGPL).
4
+ * See License-AGPL.txt in the project root for license information.
5
+ */
6
+
7
+ import { suite, test } from "mocha-typescript"
8
+ import * as chai from "chai"
9
+ import { TraceContext } from "./tracing";
10
+ import { MockTracer } from "opentracing";
11
+
12
+ const expect = chai.expect
13
+
14
+ @suite class TestTracing {
15
+
16
+ @test public async testTracingContext_addNestedTags() {
17
+ const tracer = new MockTracer();
18
+ const span = tracer.startSpan('testTracingContext_addNestedTags');
19
+ TraceContext.addNestedTags({ span }, {
20
+ rpc: {
21
+ system: "jsonrpc",
22
+ jsonrpc: {
23
+ version: "1.0",
24
+ method: "test",
25
+ parameters: ["abc", "def"],
26
+ },
27
+ },
28
+ });
29
+
30
+ const mockSpan = tracer.report().spans[0];
31
+ expect(mockSpan.tags()).to.deep.equal({
32
+ "rpc.system": "jsonrpc",
33
+ "rpc.jsonrpc.version": "1.0",
34
+ "rpc.jsonrpc.method": "test",
35
+ "rpc.jsonrpc.parameters.0": "abc",
36
+ "rpc.jsonrpc.parameters.1": "def",
37
+ });
38
+ }
39
+
40
+ @test public async testTracingContext_addNestedTags_null() {
41
+ const tracer = new MockTracer();
42
+ const span = tracer.startSpan('testTracingContext_addNestedTags_null');
43
+ TraceContext.addNestedTags({ span }, {
44
+ someShape: {
45
+ thisIsNull: null,
46
+ thisIsUndefined: undefined,
47
+ },
48
+ });
49
+
50
+ const mockSpan = tracer.report().spans[0];
51
+ expect(mockSpan.tags()).to.deep.equal({
52
+ "someShape.thisIsNull": null,
53
+ "someShape.thisIsUndefined": undefined,
54
+ });
55
+ }
56
+
57
+ @test public async testTracingContext_addJsonRPCParameters() {
58
+ const tracer = new MockTracer();
59
+ const span = tracer.startSpan('testTracingContext_addJsonRPCParameters');
60
+ const ctx = { span };
61
+ TraceContext.addJsonRPCParameters(ctx, {
62
+ one: "one",
63
+ two: {
64
+ name: "two",
65
+ some: "shape",
66
+ containing: "PII",
67
+ },
68
+ three: "three",
69
+ });
70
+
71
+ const mockSpan = tracer.report().spans[0];
72
+ expect(mockSpan.tags()).to.deep.equal({
73
+ "rpc.jsonrpc.parameters.one": "one",
74
+ "rpc.jsonrpc.parameters.two.containing": "PII",
75
+ "rpc.jsonrpc.parameters.two.name": "two",
76
+ "rpc.jsonrpc.parameters.two.some": "shape",
77
+ "rpc.jsonrpc.parameters.three": "three",
78
+ "rpc.system": "jsonrpc",
79
+ });
80
+ }
81
+
82
+ }
83
+ module.exports = new TestTracing()
@@ -6,40 +6,157 @@
6
6
 
7
7
 
8
8
  import * as opentracing from 'opentracing';
9
- import { TracingConfig, initTracerFromEnv, Sampler, SamplingDecision } from 'jaeger-client';
10
- import { initGlobalTracer } from 'opentracing';
9
+ import { TracingConfig, initTracerFromEnv } from 'jaeger-client';
10
+ import { Sampler, SamplingDecision } from './jaeger-client-types';
11
+ import { followsFrom, initGlobalTracer } from 'opentracing';
11
12
  import { injectable } from 'inversify';
13
+ import { ResponseError } from 'vscode-jsonrpc';
14
+ import { log, LogContext } from './logging';
12
15
 
13
16
  export interface TraceContext {
14
17
  span?: opentracing.Span
15
18
  }
19
+ export type TraceContextWithSpan = TraceContext & {
20
+ span: opentracing.Span
21
+ }
22
+
16
23
 
17
24
  export namespace TraceContext {
18
- export function startSpan(operation: string, ctx: TraceContext): opentracing.Span {
19
- const options: opentracing.SpanOptions = {
20
- childOf: ctx.span
25
+ export function startSpan(operation: string, parentCtx?: TraceContext, ...referencedSpans: (opentracing.Span | undefined)[]): opentracing.Span {
26
+ const options: opentracing.SpanOptions = {};
27
+ if (parentCtx) {
28
+ options.childOf = parentCtx.span;
29
+ }
30
+ if (referencedSpans) {
31
+ // note: allthough followsForm's type says it takes 'opentracing.Span | opentracing.SpanContext', it only works with SpanContext (typing mismatch)
32
+ options.references = referencedSpans.filter(s => s !== undefined).map(s => followsFrom(s!.context()));
21
33
  }
34
+
22
35
  return opentracing.globalTracer().startSpan(operation, options);
23
36
  }
24
37
 
25
- export function startAsyncSpan(operation: string, ctx: TraceContext): opentracing.Span {
26
- const options: opentracing.SpanOptions = {};
27
- if (!!ctx.span) {
28
- options.references = [opentracing.followsFrom(ctx.span.context())];
38
+ export function childContext(operation: string, parentCtx: TraceContext): TraceContextWithSpan {
39
+ const span = startSpan(operation, parentCtx);
40
+ return { span };
41
+ }
42
+
43
+ export function setError(ctx: TraceContext, err: Error) {
44
+ if (!ctx.span) {
45
+ return;
29
46
  }
30
- return opentracing.globalTracer().startSpan(operation, options);
47
+
48
+ TraceContext.addNestedTags(ctx, {
49
+ error: {
50
+ message: err.message,
51
+ stacktrace: err.stack,
52
+ },
53
+ });
54
+ ctx.span.setTag("error", true);
55
+ }
56
+
57
+ export function setJsonRPCMetadata(ctx: TraceContext, method?: string) {
58
+ if (!ctx.span) {
59
+ return;
60
+ }
61
+
62
+ const tags: { [key: string]: any } = {
63
+ rpc: {
64
+ system: "jsonrpc",
65
+ // version,
66
+ },
67
+ };
68
+ if (method) {
69
+ tags.rpc.method = method;
70
+ }
71
+ addNestedTags(ctx, tags);
72
+ }
73
+
74
+ export function setJsonRPCError(ctx: TraceContext, method: string, err: ResponseError<any>) {
75
+ if (!ctx.span) {
76
+ return;
77
+ }
78
+ // not use setError bc this is (most likely) a working operation
79
+
80
+ setJsonRPCMetadata(ctx);
81
+ // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/rpc.md#json-rpc
82
+ addNestedTags(ctx, {
83
+ rpc: {
84
+ jsonrpc: {
85
+ error_code: err.code,
86
+ error_message: err.message,
87
+ },
88
+ },
89
+ });
31
90
  }
32
91
 
33
- export function logError(ctx: TraceContext, err: Error) {
92
+ export function addJsonRPCParameters(ctx: TraceContext, params: { [key: string]: any }) {
34
93
  if (!ctx.span) {
35
94
  return;
36
95
  }
37
96
 
38
- ctx.span.log({
39
- "error": err.message,
40
- "stacktrace": err.stack
41
- })
42
- ctx.span.setTag("error", true)
97
+ setJsonRPCMetadata(ctx);
98
+ addNestedTags(ctx, {
99
+ rpc: {
100
+ jsonrpc: {
101
+ parameters: params,
102
+ },
103
+ },
104
+ });
105
+ }
106
+
107
+ /**
108
+ * Does what one would expect from `span.addTags`: Calls `span.addTag` for all keys in map, recursively for objects.
109
+ * Example:
110
+ * ```
111
+ * TraceContext.addNestedTags(ctx, {
112
+ * rpc: {
113
+ * system: "jsonrpc",
114
+ * jsonrpc: {
115
+ * version: "1.0",
116
+ * method: "test",
117
+ * parameters: ["abc", "def"],
118
+ * },
119
+ * },
120
+ * });
121
+ * ```
122
+ * gives
123
+ * rpc.system = "jsonrpc"
124
+ * rpc.jsonrpc.version = "1.0"
125
+ * rpc.jsonrpc.method = "test"
126
+ * rpc.jsonrpc.parameters.0 = "abc"
127
+ * rpc.jsonrpc.parameters.1 = "def"
128
+ * @param ctx
129
+ * @param keyValueMap
130
+ * @returns
131
+ */
132
+ export function addNestedTags(ctx: TraceContext, keyValueMap: { [key: string]: any }, _namespace?: string) {
133
+ if (!ctx.span) {
134
+ return;
135
+ }
136
+ const namespace = _namespace ? `${_namespace}.` : '';
137
+
138
+ try {
139
+ for (const k of Object.keys(keyValueMap)) {
140
+ const v = keyValueMap[k];
141
+ if (v instanceof Object) {
142
+ addNestedTags(ctx, v, `${namespace}${k}`);
143
+ } else {
144
+ ctx.span.setTag(`${namespace}${k}`, v);
145
+ }
146
+ }
147
+ } catch (err) {
148
+ // general resilience against odd shapes/parameters
149
+ log.error("Tracing.addNestedTags", err, { namespace });
150
+ }
151
+ }
152
+
153
+ export function setOWI(ctx: TraceContext, owi: LogContext) {
154
+ if (!ctx.span) {
155
+ return;
156
+ }
157
+ addNestedTags(ctx, {
158
+ context: owi,
159
+ });
43
160
  }
44
161
  }
45
162
 
@@ -56,11 +173,16 @@ export class TracingManager {
56
173
  reporter: {
57
174
  logSpans: false
58
175
  },
59
- serviceName
176
+ serviceName,
60
177
  }
61
178
  const t = initTracerFromEnv(config, {
62
- logger: console
179
+ logger: console,
180
+ tags: {
181
+ 'service.build.commit': process.env.GITPOD_BUILD_GIT_COMMIT,
182
+ 'service.build.version': process.env.GITPOD_BUILD_VERSION,
183
+ }
63
184
  });
185
+
64
186
  if (opts) {
65
187
  if (opts.perOpSampling) {
66
188
  (t as any)._sampler = new PerOperationSampler((t as any)._sampler, opts.perOpSampling);
@@ -132,3 +254,20 @@ export class PerOperationSampler implements Sampler {
132
254
  }
133
255
  }
134
256
  }
257
+
258
+ // Augment interfaces with an leading parameter "TraceContext" on every method
259
+ type IsValidArg<T> = T extends object ? keyof T extends never ? false : true : true;
260
+ type AddTraceContext<T> =
261
+ T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F) => infer R ? (
262
+ IsValidArg<F> extends true ? (ctx: TraceContextWithSpan, a: A, b: B, c: C, d: D, e: E, f: F) => R :
263
+ IsValidArg<E> extends true ? (ctx: TraceContextWithSpan, a: A, b: B, c: C, d: D, e: E) => R :
264
+ IsValidArg<D> extends true ? (ctx: TraceContextWithSpan, a: A, b: B, c: C, d: D) => R :
265
+ IsValidArg<C> extends true ? (ctx: TraceContextWithSpan, a: A, b: B, c: C) => R :
266
+ IsValidArg<B> extends true ? (ctx: TraceContextWithSpan, a: A, b: B) => R :
267
+ IsValidArg<A> extends true ? (ctx: TraceContextWithSpan, a: A) => R :
268
+ (ctx: TraceContextWithSpan) => Promise<R>
269
+ ) : never;
270
+
271
+ export type InterfaceWithTraceContext<T> = {
272
+ [P in keyof T]: AddTraceContext<T[P]>
273
+ };
@@ -35,6 +35,9 @@ export interface WorkspaceCluster {
35
35
 
36
36
  // An optional set of constraints that limit who can start workspaces on the cluster
37
37
  admissionConstraints?: AdmissionConstraint[];
38
+
39
+ // An optional set of admission preferences that guide cluster selection
40
+ admissionPreferences?: AdmissionPreference[];
38
41
  }
39
42
 
40
43
  export type WorkspaceClusterState = "available" | "cordoned" | "draining";
@@ -52,9 +55,13 @@ export namespace TLSConfig {
52
55
  export type WorkspaceClusterWoTLS = Omit<WorkspaceCluster, "tls">;
53
56
  export type WorkspaceManagerConnectionInfo = Pick<WorkspaceCluster, "name" | "url" | "tls">;
54
57
 
55
- export type AdmissionConstraint = AdmissionConstraintFeaturePreview | AdmissionConstraintHasRole;
58
+ export type AdmissionConstraint = AdmissionConstraintFeaturePreview | AdmissionConstraintHasRole | AdmissionConstraintHasUserLevel;
56
59
  export type AdmissionConstraintFeaturePreview = { type: "has-feature-preview" };
57
60
  export type AdmissionConstraintHasRole = { type: "has-permission", permission: PermissionName };
61
+ export type AdmissionConstraintHasUserLevel = { type: "has-user-level", level: string };
62
+
63
+ export type AdmissionPreference = AdmissionPreferenceUserLevel;
64
+ export type AdmissionPreferenceUserLevel = { type: 'user-level', level: string };
58
65
 
59
66
 
60
67
  export const WorkspaceClusterDB = Symbol("WorkspaceClusterDB");