Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
9a543b59
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
9a543b59
编写于
6月 08, 2016
作者:
J
Joao Moreno
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
isolate telemetry in vs/platform/telemetry
上级
19c1af1b
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
196 addition
and
354 deletion
+196
-354
src/vs/base/parts/ai/node/ai.app.ts
src/vs/base/parts/ai/node/ai.app.ts
+0
-51
src/vs/base/parts/ai/node/ai.ipc.ts
src/vs/base/parts/ai/node/ai.ipc.ts
+0
-16
src/vs/base/parts/ai/node/ai.ts
src/vs/base/parts/ai/node/ai.ts
+0
-53
src/vs/code/node/sharedProcessMain.ts
src/vs/code/node/sharedProcessMain.ts
+25
-24
src/vs/platform/telemetry/common/telemetry.ts
src/vs/platform/telemetry/common/telemetry.ts
+4
-7
src/vs/platform/telemetry/common/telemetryIpc.ts
src/vs/platform/telemetry/common/telemetryIpc.ts
+2
-1
src/vs/platform/telemetry/node/aiAdapter.ts
src/vs/platform/telemetry/node/aiAdapter.ts
+0
-151
src/vs/platform/telemetry/node/appInsightsAppender.ts
src/vs/platform/telemetry/node/appInsightsAppender.ts
+137
-12
src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts
.../platform/telemetry/test/node/appInsightsAppender.test.ts
+1
-1
src/vs/workbench/electron-browser/shell.ts
src/vs/workbench/electron-browser/shell.ts
+16
-24
src/vs/workbench/parts/debug/electron-browser/debugService.ts
...vs/workbench/parts/debug/electron-browser/debugService.ts
+9
-11
src/vs/workbench/parts/debug/node/rawDebugSession.ts
src/vs/workbench/parts/debug/node/rawDebugSession.ts
+2
-3
未找到文件。
src/vs/base/parts/ai/node/ai.app.ts
已删除
100644 → 0
浏览文件 @
19c1af1b
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
IServer
}
from
'
vs/base/parts/ipc/common/ipc
'
;
import
{
AppInsightsAppender
}
from
'
vs/platform/telemetry/node/aiAdapter
'
;
import
{
IAIChannel
}
from
'
./ai.ipc
'
;
const
adapter
:
{
[
handle
:
number
]:
AppInsightsAppender
}
=
Object
.
create
(
null
);
let
idPool
=
0
;
export
function
registerAIChannel
(
server
:
IServer
)
{
server
.
registerChannel
(
'
ai
'
,
<
IAIChannel
>
{
call
(
command
:
string
,
arg
:
any
):
TPromise
<
any
>
{
switch
(
command
)
{
case
'
create
'
:
{
let
handle
=
idPool
++
;
let
{
key
,
eventPrefix
,
data
}
=
arg
;
adapter
[
handle
]
=
new
AppInsightsAppender
(
eventPrefix
,
data
,
key
);
return
TPromise
.
as
(
handle
);
}
case
'
log
'
:
{
let
{
handle
,
eventName
,
data
}
=
arg
;
adapter
[
handle
].
log
(
eventName
,
data
);
return
TPromise
.
as
(
undefined
);
}
case
'
dispose
'
:
{
let
{
handle
}
=
arg
;
adapter
[
handle
].
dispose
();
delete
adapter
[
handle
];
return
TPromise
.
as
(
undefined
);
}
}
}
});
}
// It is important to dispose the AI adapter properly because
// only then they flush remaining data.
process
.
on
(
'
SIGTERM
'
,
function
()
{
let
promises
:
TPromise
<
any
>
[]
=
[];
for
(
let
handle
in
adapter
)
{
let
ai
=
adapter
[
handle
];
promises
.
push
(
ai
.
dispose
());
}
TPromise
.
join
(
promises
).
then
(
_
=>
process
.
exit
(
0
));
});
src/vs/base/parts/ai/node/ai.ipc.ts
已删除
100644 → 0
浏览文件 @
19c1af1b
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
IChannel
}
from
'
vs/base/parts/ipc/common/ipc
'
;
export
interface
IAIChannel
extends
IChannel
{
call
(
command
:
'
create
'
,
data
:
{
key
:
string
;
eventPrefix
:
string
;
data
:
{
[
k
:
string
]:
any
};
}):
TPromise
<
number
>
;
call
(
command
:
'
log
'
,
data
:
{
handle
:
number
;
eventName
:
string
;
data
:
{
[
k
:
string
]:
any
};
}):
TPromise
<
any
>
;
call
(
command
:
'
dispose
'
,
data
:
{
handle
:
number
;
}):
TPromise
<
any
>
;
call
(
command
:
string
,
arg
:
any
):
TPromise
<
any
>
;
}
src/vs/base/parts/ai/node/ai.ts
已删除
100644 → 0
浏览文件 @
19c1af1b
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
IAIChannel
}
from
'
./ai.ipc
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
connect
}
from
'
vs/base/parts/ipc/node/ipc.net
'
;
export
interface
IAIAdapter
{
log
(
eventName
:
string
,
data
?:
any
):
void
;
dispose
():
void
;
}
export
function
createAIAdapter
(
key
:
string
,
eventPrefix
:
string
,
data
:
{
[
key
:
string
]:
any
}):
IAIAdapter
{
let
beforeReadyMessages
:
{
type
:
string
;
args
:
any
}[]
=
[];
let
handle
:
number
=
undefined
;
let
channel
:
IAIChannel
=
{
call
(
type
:
string
,
args
:
any
):
TPromise
<
any
>
{
beforeReadyMessages
.
push
({
type
,
args
});
return
TPromise
.
as
(
void
0
);
}
};
connect
(
process
.
env
[
'
VSCODE_SHARED_IPC_HOOK
'
]).
then
(
client
=>
client
.
getChannel
<
IAIChannel
>
(
'
ai
'
)).
then
(
actualChannel
=>
{
return
actualChannel
.
call
(
'
create
'
,
{
key
,
eventPrefix
,
data
}).
then
(
actualHandle
=>
{
// channel has been created, store handle etc,
// and flush all early messages
handle
=
actualHandle
;
channel
=
actualChannel
;
for
(
let
m
of
beforeReadyMessages
)
{
let
{
type
,
args
}
=
m
;
args
.
handle
=
handle
;
channel
.
call
(
type
,
args
);
}
beforeReadyMessages
.
length
=
0
;
});
});
return
<
IAIAdapter
>
{
log
(
eventName
:
string
,
data
?:
any
)
{
channel
.
call
(
'
log
'
,
{
handle
,
eventName
,
data
});
},
dispose
()
{
channel
.
call
(
'
dispose
'
,
{
handle
});
}
};
}
src/vs/code/node/sharedProcessMain.ts
浏览文件 @
9a543b59
...
...
@@ -7,7 +7,6 @@ import * as fs from 'fs';
import
*
as
platform
from
'
vs/base/common/platform
'
;
import
{
serve
,
Server
,
connect
}
from
'
vs/base/parts/ipc/node/ipc.net
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
registerAIChannel
}
from
'
vs/base/parts/ai/node/ai.app
'
;
import
{
ServiceCollection
}
from
'
vs/platform/instantiation/common/serviceCollection
'
;
import
{
SyncDescriptor
}
from
'
vs/platform/instantiation/common/descriptors
'
;
import
{
InstantiationService
}
from
'
vs/platform/instantiation/common/instantiationService
'
;
...
...
@@ -22,9 +21,10 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import
{
NodeConfigurationService
}
from
'
vs/platform/configuration/node/nodeConfigurationService
'
;
import
product
from
'
vs/platform/product
'
;
import
{
ITelemetryAppender
,
combinedAppender
,
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
ITelemetryAppender
,
ITelemetryService
,
combinedAppender
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
TelemetryAppenderChannel
}
from
'
vs/platform/telemetry/common/telemetryIpc
'
;
import
{
TelemetryService
,
ITelemetryServiceConfig
}
from
'
vs/platform/telemetry/common/telemetryService
'
;
import
{
AppInsightsAppender
}
from
'
vs/platform/telemetry/node/a
iAdapt
er
'
;
import
{
AppInsightsAppender
}
from
'
vs/platform/telemetry/node/a
ppInsightsAppend
er
'
;
function
quit
(
err
?:
Error
)
{
if
(
err
)
{
...
...
@@ -49,21 +49,6 @@ function setupPlanB(parentPid: number): void {
const
eventPrefix
=
'
monacoworkbench
'
;
function
createAppender
():
ITelemetryAppender
{
const
result
:
ITelemetryAppender
[]
=
[];
const
{
key
,
asimovKey
}
=
product
.
aiConfig
||
{
key
:
null
,
asimovKey
:
null
};
if
(
key
)
{
result
.
push
(
new
AppInsightsAppender
(
eventPrefix
,
null
,
key
));
}
if
(
asimovKey
)
{
result
.
push
(
new
AppInsightsAppender
(
eventPrefix
,
null
,
asimovKey
));
}
return
combinedAppender
(...
result
);
}
function
main
(
server
:
Server
):
void
{
const
services
=
new
ServiceCollection
();
...
...
@@ -75,12 +60,30 @@ function main(server: Server): void {
const
instantiationService
=
new
InstantiationService
(
services
);
instantiationService
.
invokeFunction
(
accessor
=>
{
const
{
appRoot
,
extensionsPath
}
=
accessor
.
get
(
IEnvironmentService
)
;
const
aiAppenders
:
AppInsightsAppender
[]
=
[]
;
const
appender
=
createAppender
();
if
(
product
.
aiConfig
&&
product
.
aiConfig
.
key
)
{
aiAppenders
.
push
(
new
AppInsightsAppender
(
eventPrefix
,
null
,
product
.
aiConfig
.
key
));
}
if
(
product
.
aiConfig
&&
product
.
aiConfig
.
asimovKey
)
{
aiAppenders
.
push
(
new
AppInsightsAppender
(
eventPrefix
,
null
,
product
.
aiConfig
.
asimovKey
));
}
const
appenders
:
ITelemetryAppender
[]
=
aiAppenders
.
slice
();
appenders
.
push
({
log
:
(
e
,
d
)
=>
console
.
log
(
`Telemetry event:
${
e
}
\n
${
JSON
.
stringify
(
d
)
}
`
)
});
// It is important to dispose the AI adapter properly because
// only then they flush remaining data.
process
.
once
(
'
exit
'
,
()
=>
aiAppenders
.
forEach
(
a
=>
a
.
dispose
()));
const
appender
=
combinedAppender
(...
appenders
);
server
.
registerChannel
(
'
telemetryAppender
'
,
new
TelemetryAppenderChannel
(
appender
));
const
{
appRoot
,
extensionsPath
}
=
accessor
.
get
(
IEnvironmentService
);
const
config
:
ITelemetryServiceConfig
=
{
appender
,
commonProperties
:
TPromise
.
as
({}),
//resolveCommonProperties(storageService, contextService),
commonProperties
:
TPromise
.
as
({}),
piiPaths
:
[
appRoot
,
extensionsPath
]
};
...
...
@@ -89,13 +92,11 @@ function main(server: Server): void {
const
instantiationService2
=
instantiationService
.
createChild
(
services
);
instantiationService2
.
invokeFunction
(
accessor
=>
{
const
telemetryService
=
accessor
.
get
(
ITelemetryService
);
console
.
log
(
telemetryService
);
// const telemetryService = accessor.get(ITelemetryService);
const
extensionManagementService
=
accessor
.
get
(
IExtensionManagementService
);
const
channel
=
new
ExtensionManagementChannel
(
extensionManagementService
);
server
.
registerChannel
(
'
extensions
'
,
channel
);
registerAIChannel
(
server
);
// eventually clean up old extensions
setTimeout
(()
=>
(
extensionManagementService
as
ExtensionManagementService
).
removeDeprecatedExtensions
(),
5000
);
...
...
src/vs/platform/telemetry/common/telemetry.ts
浏览文件 @
9a543b59
...
...
@@ -5,7 +5,6 @@
'
use strict
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
ITimerEvent
,
nullEvent
}
from
'
vs/base/common/timer
'
;
import
{
createDecorator
,
ServiceIdentifier
}
from
'
vs/platform/instantiation/common/instantiation
'
;
...
...
@@ -51,17 +50,15 @@ export const NullTelemetryService: ITelemetryService = {
}
};
export
interface
ITelemetryAppender
extends
IDisposable
{
log
(
eventName
:
string
,
data
?:
any
):
any
;
export
interface
ITelemetryAppender
{
log
(
eventName
:
string
,
data
:
any
):
void
;
}
export
function
combinedAppender
(...
appenders
:
ITelemetryAppender
[]):
ITelemetryAppender
{
const
log
=
(
e
,
d
)
=>
appenders
.
forEach
(
a
=>
a
.
log
(
e
,
d
));
const
dispose
=
()
=>
appenders
.
forEach
(
a
=>
a
.
dispose
());
return
{
log
,
dispose
};
return
{
log
:
(
e
,
d
)
=>
appenders
.
forEach
(
a
=>
a
.
log
(
e
,
d
))
};
}
export
const
NullAppender
=
combinedAppender
()
;
export
const
NullAppender
:
ITelemetryAppender
=
{
log
:
()
=>
null
}
;
// --- util
...
...
src/vs/platform/telemetry/common/telemetryIpc.ts
浏览文件 @
9a543b59
...
...
@@ -24,7 +24,8 @@ export class TelemetryAppenderChannel implements ITelemetryAppenderChannel {
constructor
(
private
appender
:
ITelemetryAppender
)
{
}
call
(
command
:
string
,
{
eventName
,
data
}:
ITelemetryLog
):
TPromise
<
any
>
{
return
this
.
appender
.
log
(
eventName
,
data
);
this
.
appender
.
log
(
eventName
,
data
);
return
TPromise
.
as
(
null
);
}
}
...
...
src/vs/platform/telemetry/node/aiAdapter.ts
已删除
100644 → 0
浏览文件 @
19c1af1b
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
*
as
appInsights
from
'
applicationinsights
'
;
import
{
isObject
}
from
'
vs/base/common/types
'
;
import
{
safeStringify
,
mixin
}
from
'
vs/base/common/objects
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
ITelemetryAppender
}
from
'
../common/telemetry
'
;
let
_initialized
=
false
;
function
ensureAIEngineIsInitialized
():
void
{
if
(
_initialized
===
false
)
{
// we need to pass some fake key, otherwise AI throws an exception
appInsights
.
setup
(
'
2588e01f-f6c9-4cd6-a348-143741f8d702
'
)
.
setAutoCollectConsole
(
false
)
.
setAutoCollectExceptions
(
false
)
.
setAutoCollectPerformance
(
false
)
.
setAutoCollectRequests
(
false
);
_initialized
=
true
;
}
}
function
getClient
(
aiKey
:
string
):
typeof
appInsights
.
client
{
ensureAIEngineIsInitialized
();
const
client
=
appInsights
.
getClient
(
aiKey
);
client
.
channel
.
setOfflineMode
(
true
);
client
.
context
.
tags
[
client
.
context
.
keys
.
deviceMachineName
]
=
''
;
//prevent App Insights from reporting machine name
if
(
aiKey
.
indexOf
(
'
AIF-
'
)
===
0
)
{
client
.
config
.
endpointUrl
=
'
https://vortex.data.microsoft.com/collect/v1
'
;
}
return
client
;
}
interface
Properties
{
[
key
:
string
]:
string
;
}
interface
Measurements
{
[
key
:
string
]:
number
;
}
export
class
AppInsightsAppender
implements
ITelemetryAppender
{
private
_aiClient
:
typeof
appInsights
.
client
;
constructor
(
private
_eventPrefix
:
string
,
private
_defaultData
:
{
[
key
:
string
]:
any
},
aiKeyOrClientFactory
:
string
|
(()
=>
typeof
appInsights
.
client
)
// allow factory function for testing
)
{
if
(
!
this
.
_defaultData
)
{
this
.
_defaultData
=
Object
.
create
(
null
);
}
if
(
typeof
aiKeyOrClientFactory
===
'
string
'
)
{
this
.
_aiClient
=
getClient
(
aiKeyOrClientFactory
);
}
else
if
(
typeof
aiKeyOrClientFactory
===
'
function
'
)
{
this
.
_aiClient
=
aiKeyOrClientFactory
();
}
}
private
static
_getData
(
data
?:
any
):
{
properties
:
Properties
,
measurements
:
Measurements
}
{
const
properties
:
Properties
=
Object
.
create
(
null
);
const
measurements
:
Measurements
=
Object
.
create
(
null
);
const
flat
=
Object
.
create
(
null
);
AppInsightsAppender
.
_flaten
(
data
,
flat
);
for
(
let
prop
in
flat
)
{
// enforce property names less than 150 char, take the last 150 char
prop
=
prop
.
length
>
150
?
prop
.
substr
(
prop
.
length
-
149
)
:
prop
;
var
value
=
flat
[
prop
];
if
(
typeof
value
===
'
number
'
)
{
measurements
[
prop
]
=
value
;
}
else
if
(
typeof
value
===
'
boolean
'
)
{
measurements
[
prop
]
=
value
?
1
:
0
;
}
else
if
(
typeof
value
===
'
string
'
)
{
//enforce property value to be less than 1024 char, take the first 1024 char
properties
[
prop
]
=
value
.
substring
(
0
,
1023
);
}
else
if
(
typeof
value
!==
'
undefined
'
&&
value
!==
null
)
{
properties
[
prop
]
=
value
;
}
}
return
{
properties
,
measurements
};
}
private
static
_flaten
(
obj
:
any
,
result
:
{[
key
:
string
]:
any
},
order
:
number
=
0
,
prefix
?:
string
):
void
{
if
(
!
obj
)
{
return
;
}
for
(
var
item
of
Object
.
getOwnPropertyNames
(
obj
)){
const
value
=
obj
[
item
];
const
index
=
prefix
?
prefix
+
item
:
item
;
if
(
Array
.
isArray
(
value
))
{
result
[
index
]
=
safeStringify
(
value
);
}
else
if
(
value
instanceof
Date
)
{
// TODO unsure why this is here and not in _getData
result
[
index
]
=
value
.
toISOString
();
}
else
if
(
isObject
(
value
))
{
if
(
order
<
2
)
{
AppInsightsAppender
.
_flaten
(
value
,
result
,
order
+
1
,
index
+
'
.
'
);
}
else
{
result
[
index
]
=
safeStringify
(
value
);
}
}
else
{
result
[
index
]
=
value
;
}
}
}
public
log
(
eventName
:
string
,
data
?:
any
):
void
{
if
(
!
this
.
_aiClient
)
{
return
;
}
data
=
mixin
(
data
,
this
.
_defaultData
);
let
{
properties
,
measurements
}
=
AppInsightsAppender
.
_getData
(
data
);
this
.
_aiClient
.
trackEvent
(
this
.
_eventPrefix
+
'
/
'
+
eventName
,
properties
,
measurements
);
}
public
dispose
():
TPromise
<
any
>
{
if
(
this
.
_aiClient
)
{
return
new
TPromise
(
resolve
=>
{
this
.
_aiClient
.
sendPendingData
(()
=>
{
// all data flushed
this
.
_aiClient
=
undefined
;
resolve
(
void
0
);
});
});
}
}
}
\ No newline at end of file
src/vs/platform/telemetry/node/appInsightsAppender.ts
浏览文件 @
9a543b59
...
...
@@ -4,23 +4,148 @@
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
IEnvironment
}
from
'
vs/platform/workspace/common/workspace
'
;
import
{
ITelemetryAppender
,
combinedAppender
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
createAIAdapter
}
from
'
vs/base/parts/ai/node/ai
'
;
import
*
as
appInsights
from
'
applicationinsights
'
;
import
{
isObject
}
from
'
vs/base/common/types
'
;
import
{
safeStringify
,
mixin
}
from
'
vs/base/common/objects
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
ITelemetryAppender
}
from
'
../common/telemetry
'
;
const
eventPrefix
=
'
monacoworkbench
'
;
let
_initialized
=
false
;
export
function
createAppender
(
env
:
IEnvironment
):
ITelemetryAppender
{
const
result
:
ITelemetryAppender
[]
=
[];
const
{
key
,
asimovKey
}
=
env
.
aiConfig
;
function
ensureAIEngineIsInitialized
():
void
{
if
(
_initialized
===
false
)
{
// we need to pass some fake key, otherwise AI throws an exception
appInsights
.
setup
(
'
2588e01f-f6c9-4cd6-a348-143741f8d702
'
)
.
setAutoCollectConsole
(
false
)
.
setAutoCollectExceptions
(
false
)
.
setAutoCollectPerformance
(
false
)
.
setAutoCollectRequests
(
false
);
if
(
key
)
{
result
.
push
(
createAIAdapter
(
key
,
eventPrefix
,
undefined
));
_initialized
=
true
;
}
}
function
getClient
(
aiKey
:
string
):
typeof
appInsights
.
client
{
if
(
asimovKey
)
{
result
.
push
(
createAIAdapter
(
asimovKey
,
eventPrefix
,
undefined
));
ensureAIEngineIsInitialized
();
const
client
=
appInsights
.
getClient
(
aiKey
);
client
.
channel
.
setOfflineMode
(
true
);
client
.
context
.
tags
[
client
.
context
.
keys
.
deviceMachineName
]
=
''
;
//prevent App Insights from reporting machine name
if
(
aiKey
.
indexOf
(
'
AIF-
'
)
===
0
)
{
client
.
config
.
endpointUrl
=
'
https://vortex.data.microsoft.com/collect/v1
'
;
}
return
client
;
}
return
combinedAppender
(...
result
);
interface
Properties
{
[
key
:
string
]:
string
;
}
interface
Measurements
{
[
key
:
string
]:
number
;
}
export
class
AppInsightsAppender
implements
ITelemetryAppender
{
private
_aiClient
:
typeof
appInsights
.
client
;
constructor
(
private
_eventPrefix
:
string
,
private
_defaultData
:
{
[
key
:
string
]:
any
},
aiKeyOrClientFactory
:
string
|
(()
=>
typeof
appInsights
.
client
)
// allow factory function for testing
)
{
if
(
!
this
.
_defaultData
)
{
this
.
_defaultData
=
Object
.
create
(
null
);
}
if
(
typeof
aiKeyOrClientFactory
===
'
string
'
)
{
this
.
_aiClient
=
getClient
(
aiKeyOrClientFactory
);
}
else
if
(
typeof
aiKeyOrClientFactory
===
'
function
'
)
{
this
.
_aiClient
=
aiKeyOrClientFactory
();
}
}
private
static
_getData
(
data
?:
any
):
{
properties
:
Properties
,
measurements
:
Measurements
}
{
const
properties
:
Properties
=
Object
.
create
(
null
);
const
measurements
:
Measurements
=
Object
.
create
(
null
);
const
flat
=
Object
.
create
(
null
);
AppInsightsAppender
.
_flaten
(
data
,
flat
);
for
(
let
prop
in
flat
)
{
// enforce property names less than 150 char, take the last 150 char
prop
=
prop
.
length
>
150
?
prop
.
substr
(
prop
.
length
-
149
)
:
prop
;
var
value
=
flat
[
prop
];
if
(
typeof
value
===
'
number
'
)
{
measurements
[
prop
]
=
value
;
}
else
if
(
typeof
value
===
'
boolean
'
)
{
measurements
[
prop
]
=
value
?
1
:
0
;
}
else
if
(
typeof
value
===
'
string
'
)
{
//enforce property value to be less than 1024 char, take the first 1024 char
properties
[
prop
]
=
value
.
substring
(
0
,
1023
);
}
else
if
(
typeof
value
!==
'
undefined
'
&&
value
!==
null
)
{
properties
[
prop
]
=
value
;
}
}
return
{
properties
,
measurements
};
}
private
static
_flaten
(
obj
:
any
,
result
:
{[
key
:
string
]:
any
},
order
:
number
=
0
,
prefix
?:
string
):
void
{
if
(
!
obj
)
{
return
;
}
for
(
var
item
of
Object
.
getOwnPropertyNames
(
obj
)){
const
value
=
obj
[
item
];
const
index
=
prefix
?
prefix
+
item
:
item
;
if
(
Array
.
isArray
(
value
))
{
result
[
index
]
=
safeStringify
(
value
);
}
else
if
(
value
instanceof
Date
)
{
// TODO unsure why this is here and not in _getData
result
[
index
]
=
value
.
toISOString
();
}
else
if
(
isObject
(
value
))
{
if
(
order
<
2
)
{
AppInsightsAppender
.
_flaten
(
value
,
result
,
order
+
1
,
index
+
'
.
'
);
}
else
{
result
[
index
]
=
safeStringify
(
value
);
}
}
else
{
result
[
index
]
=
value
;
}
}
}
log
(
eventName
:
string
,
data
?:
any
):
void
{
if
(
!
this
.
_aiClient
)
{
return
;
}
data
=
mixin
(
data
,
this
.
_defaultData
);
let
{
properties
,
measurements
}
=
AppInsightsAppender
.
_getData
(
data
);
this
.
_aiClient
.
trackEvent
(
this
.
_eventPrefix
+
'
/
'
+
eventName
,
properties
,
measurements
);
}
dispose
():
TPromise
<
any
>
{
if
(
this
.
_aiClient
)
{
return
new
TPromise
(
resolve
=>
{
this
.
_aiClient
.
sendPendingData
(()
=>
{
// all data flushed
this
.
_aiClient
=
undefined
;
resolve
(
void
0
);
});
});
}
}
}
\ No newline at end of file
src/vs/platform/telemetry/test/node/a
iAdapt
er.test.ts
→
src/vs/platform/telemetry/test/node/a
ppInsightsAppend
er.test.ts
浏览文件 @
9a543b59
...
...
@@ -5,7 +5,7 @@
'
use strict
'
;
import
*
as
assert
from
'
assert
'
;
import
{
AppInsightsAppender
}
from
'
vs/platform/telemetry/node/a
iAdapt
er
'
;
import
{
AppInsightsAppender
}
from
'
vs/platform/telemetry/node/a
ppInsightsAppend
er
'
;
interface
IAppInsightsEvent
{
eventName
:
string
;
...
...
src/vs/workbench/electron-browser/shell.ts
浏览文件 @
9a543b59
...
...
@@ -20,10 +20,10 @@ import timer = require('vs/base/common/timer');
import
{
Workbench
}
from
'
vs/workbench/browser/workbench
'
;
import
{
Storage
,
inMemoryLocalStorageInstance
}
from
'
vs/workbench/common/storage
'
;
import
{
ITelemetryService
,
NullTelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
ITelemetryAppenderChannel
,
TelemetryAppenderClient
}
from
'
vs/platform/telemetry/common/telemetryIpc
'
;
import
{
TelemetryService
,
ITelemetryServiceConfig
}
from
'
vs/platform/telemetry/common/telemetryService
'
;
import
{
IdleMonitor
,
UserStatus
}
from
'
vs/platform/telemetry/browser/idleMonitor
'
;
import
ErrorTelemetry
from
'
vs/platform/telemetry/browser/errorTelemetry
'
;
import
{
createAppender
}
from
'
vs/platform/telemetry/node/appInsightsAppender
'
;
import
{
resolveCommonProperties
}
from
'
vs/platform/telemetry/node/commonProperties
'
;
import
{
ElectronIntegration
}
from
'
vs/workbench/electron-browser/integration
'
;
import
{
Update
}
from
'
vs/workbench/electron-browser/update
'
;
...
...
@@ -48,7 +48,6 @@ import {IOptions} from 'vs/workbench/common/options';
import
{
IStorageService
}
from
'
vs/platform/storage/common/storage
'
;
import
{
ServiceCollection
}
from
'
vs/platform/instantiation/common/serviceCollection
'
;
import
{
InstantiationService
}
from
'
vs/platform/instantiation/common/instantiationService
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IContextViewService
}
from
'
vs/platform/contextview/browser/contextView
'
;
import
{
IEventService
}
from
'
vs/platform/event/common/event
'
;
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
...
...
@@ -197,6 +196,16 @@ export class WorkbenchShell {
}
private
initServiceCollection
():
[
InstantiationService
,
ServiceCollection
]
{
const
sharedProcess
=
connect
(
process
.
env
[
'
VSCODE_SHARED_IPC_HOOK
'
]);
sharedProcess
.
done
(
service
=>
{
service
.
onClose
(()
=>
{
this
.
messageService
.
show
(
Severity
.
Error
,
{
message
:
nls
.
localize
(
'
sharedProcessCrashed
'
,
"
The shared process terminated unexpectedly. Please reload the window to recover.
"
),
actions
:
[
instantiationService
.
createInstance
(
ReloadWindowAction
,
ReloadWindowAction
.
ID
,
ReloadWindowAction
.
LABEL
)]
});
});
},
errors
.
onUnexpectedError
);
const
serviceCollection
=
new
ServiceCollection
();
serviceCollection
.
set
(
IEventService
,
this
.
eventService
);
serviceCollection
.
set
(
IWorkspaceContextService
,
this
.
contextService
);
...
...
@@ -215,9 +224,9 @@ export class WorkbenchShell {
// Telemetry
if
(
this
.
configuration
.
env
.
isBuilt
&&
!
this
.
configuration
.
env
.
extensionDevelopmentPath
&&
!!
this
.
configuration
.
env
.
enableTelemetry
)
{
const
appender
=
createAppender
(
this
.
configuration
.
env
);
const
channel
=
getDelayedChannel
<
ITelemetryAppenderChannel
>
(
sharedProcess
.
then
(
c
=>
c
.
getChannel
(
'
telemetryAppender
'
))
);
const
config
:
ITelemetryServiceConfig
=
{
appender
,
appender
:
new
TelemetryAppenderClient
(
channel
)
,
commonProperties
:
resolveCommonProperties
(
this
.
storageService
,
this
.
contextService
),
piiPaths
:
[
this
.
configuration
.
env
.
appRoot
,
this
.
configuration
.
env
.
userExtensionsHome
]
};
...
...
@@ -234,7 +243,7 @@ export class WorkbenchShell {
:
TelemetryService
.
IDLE_START_EVENT_NAME
));
disposables
.
add
(
telemetryService
,
errorTelemetry
,
listener
,
idleMonitor
,
appender
);
disposables
.
add
(
telemetryService
,
errorTelemetry
,
listener
,
idleMonitor
);
}
else
{
this
.
telemetryService
=
NullTelemetryService
;
}
...
...
@@ -287,30 +296,13 @@ export class WorkbenchShell {
let
codeEditorService
=
instantiationService
.
createInstance
(
CodeEditorServiceImpl
);
serviceCollection
.
set
(
ICodeEditorService
,
codeEditorService
);
let
extensionManagementChannelClient
=
instantiationService
.
createInstance
(
ExtensionManagementChannelClient
,
this
.
initSharedProcessChannel
(
instantiationService
,
this
.
messageService
));
const
extensionManagementChannel
=
getDelayedChannel
<
IExtensionManagementChannel
>
(
sharedProcess
.
then
(
c
=>
c
.
getChannel
(
'
extensions
'
)));
const
extensionManagementChannelClient
=
instantiationService
.
createInstance
(
ExtensionManagementChannelClient
,
extensionManagementChannel
);
serviceCollection
.
set
(
IExtensionManagementService
,
extensionManagementChannelClient
);
return
[
instantiationService
,
serviceCollection
];
}
private
initSharedProcessChannel
(
instantiationService
:
IInstantiationService
,
messageService
:
IMessageService
):
IExtensionManagementChannel
{
const
sharedProcessClientPromise
=
connect
(
process
.
env
[
'
VSCODE_SHARED_IPC_HOOK
'
]);
sharedProcessClientPromise
.
done
(
service
=>
{
service
.
onClose
(()
=>
{
messageService
.
show
(
Severity
.
Error
,
{
message
:
nls
.
localize
(
'
sharedProcessCrashed
'
,
"
The shared process terminated unexpectedly. Please reload the window to recover.
"
),
actions
:
[
instantiationService
.
createInstance
(
ReloadWindowAction
,
ReloadWindowAction
.
ID
,
ReloadWindowAction
.
LABEL
)]
});
});
},
errors
.
onUnexpectedError
);
const
extensionManagementChannelPromise
=
sharedProcessClientPromise
.
then
(
client
=>
client
.
getChannel
<
IExtensionManagementChannel
>
(
'
extensions
'
));
return
getDelayedChannel
<
IExtensionManagementChannel
>
(
extensionManagementChannelPromise
);
}
public
open
():
void
{
// Listen on unexpected errors
...
...
src/vs/workbench/parts/debug/electron-browser/debugService.ts
浏览文件 @
9a543b59
...
...
@@ -17,7 +17,6 @@ import errors = require('vs/base/common/errors');
import
severity
from
'
vs/base/common/severity
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
aria
=
require
(
'
vs/base/browser/ui/aria/aria
'
);
import
{
IAIAdapter
,
createAIAdapter
}
from
'
vs/base/parts/ai/node/ai
'
;
import
editorbrowser
=
require
(
'
vs/editor/browser/editorBrowser
'
);
import
{
IKeybindingService
,
IKeybindingContextKey
}
from
'
vs/platform/keybinding/common/keybindingService
'
;
import
{
IMarkerService
}
from
'
vs/platform/markers/common/markers
'
;
...
...
@@ -28,6 +27,8 @@ import { IFileService, FileChangesEvent, FileChangeType, EventType } from 'vs/pl
import
{
IEventService
}
from
'
vs/platform/event/common/event
'
;
import
{
IMessageService
,
CloseAction
}
from
'
vs/platform/message/common/message
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
TelemetryService
}
from
'
vs/platform/telemetry/common/telemetryService
'
;
import
{
AppInsightsAppender
}
from
'
vs/platform/telemetry/node/appInsightsAppender
'
;
import
{
IStorageService
,
StorageScope
}
from
'
vs/platform/storage/common/storage
'
;
import
{
IEditorGroupService
}
from
'
vs/workbench/services/group/common/groupService
'
;
import
wbeditorcommon
=
require
(
'
vs/workbench/common/editor
'
);
...
...
@@ -68,7 +69,7 @@ export class DebugService implements debug.IDebugService {
private
model
:
model
.
Model
;
private
viewModel
:
viewmodel
.
ViewModel
;
private
configurationManager
:
ConfigurationManager
;
private
telemetryAdapter
:
IAIAdapter
;
private
customTelemetryService
:
ITelemetryService
;
private
lastTaskEvent
:
TaskEvent
;
private
toDispose
:
lifecycle
.
IDisposable
[];
private
toDisposeOnSessionEnd
:
lifecycle
.
IDisposable
[];
...
...
@@ -292,8 +293,8 @@ export class DebugService implements debug.IDebugService {
if
(
event
.
body
&&
event
.
body
.
category
===
'
telemetry
'
)
{
// only log telemetry events from debug adapter if the adapter provided the telemetry key
// and the user opted in telemetry
if
(
this
.
telemetryAdapter
&&
this
.
telemetryService
.
isOptedIn
)
{
this
.
telemetryAdapter
.
l
og
(
event
.
body
.
output
,
event
.
body
.
data
);
if
(
this
.
customTelemetryService
&&
this
.
telemetryService
.
isOptedIn
)
{
this
.
customTelemetryService
.
publicL
og
(
event
.
body
.
output
,
event
.
body
.
data
);
}
}
else
if
(
event
.
body
&&
typeof
event
.
body
.
output
===
'
string
'
&&
event
.
body
.
output
.
length
>
0
)
{
this
.
onOutput
(
event
);
...
...
@@ -561,11 +562,12 @@ export class DebugService implements debug.IDebugService {
telemetryInfo
[
'
common.vscodesessionid
'
]
=
info
.
sessionId
;
return
telemetryInfo
;
}).
then
(
data
=>
{
let
{
aiKey
,
type
}
=
this
.
configurationManager
.
adapter
;
this
.
telemetryAdapter
=
createAIAdapter
(
aiKey
,
type
,
data
);
const
{
aiKey
,
type
}
=
this
.
configurationManager
.
adapter
;
const
appender
=
new
AppInsightsAppender
(
type
,
data
,
aiKey
);
this
.
customTelemetryService
=
new
TelemetryService
({
appender
},
this
.
configurationService
);
});
this
.
session
=
this
.
instantiationService
.
createInstance
(
session
.
RawDebugSession
,
configuration
.
debugServer
,
this
.
configurationManager
.
adapter
,
this
.
telemetryAdapter
);
this
.
session
=
this
.
instantiationService
.
createInstance
(
session
.
RawDebugSession
,
configuration
.
debugServer
,
this
.
configurationManager
.
adapter
,
this
.
customTelemetryService
);
this
.
registerSessionListeners
();
return
this
.
session
.
initialize
({
...
...
@@ -740,10 +742,6 @@ export class DebugService implements debug.IDebugService {
});
this
.
model
.
updateBreakpoints
(
data
);
if
(
this
.
telemetryAdapter
)
{
this
.
telemetryAdapter
.
dispose
();
this
.
telemetryAdapter
=
null
;
}
this
.
inDebugMode
.
reset
();
}
...
...
src/vs/workbench/parts/debug/node/rawDebugSession.ts
浏览文件 @
9a543b59
...
...
@@ -13,7 +13,6 @@ import { Action } from 'vs/base/common/actions';
import
errors
=
require
(
'
vs/base/common/errors
'
);
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
severity
from
'
vs/base/common/severity
'
;
import
{
IAIAdapter
}
from
'
vs/base/parts/ai/node/ai
'
;
import
stdfork
=
require
(
'
vs/base/node/stdFork
'
);
import
{
IMessageService
,
CloseAction
}
from
'
vs/platform/message/common/message
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
...
...
@@ -66,7 +65,7 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes
constructor
(
private
debugServerPort
:
number
,
private
adapter
:
Adapter
,
private
telemtryAdapter
:
IAIAdapter
,
private
customTelemetryService
:
ITelemetryService
,
@
IMessageService
private
messageService
:
IMessageService
,
@
ITelemetryService
private
telemetryService
:
ITelemetryService
,
@
IOutputService
private
outputService
:
IOutputService
...
...
@@ -146,7 +145,7 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes
const
message
=
error
?
debug
.
formatPII
(
error
.
format
,
false
,
error
.
variables
)
:
errorResponse
.
message
;
if
(
error
&&
error
.
sendTelemetry
)
{
this
.
telemetryService
.
publicLog
(
'
debugProtocolErrorResponse
'
,
{
error
:
message
});
this
.
telemtryAdapter
.
l
og
(
'
debugProtocolErrorResponse
'
,
{
error
:
message
});
this
.
customTelemetryService
.
publicL
og
(
'
debugProtocolErrorResponse
'
,
{
error
:
message
});
}
if
(
error
&&
error
.
showUser
===
false
)
{
return
TPromise
.
as
(
null
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录