Skip to content

Commit ec7881d

Browse files
committed
Merge remote-tracking branch 'upstream/master' into empty
2 parents f06a672 + f355557 commit ec7881d

File tree

98 files changed

+4309
-2008
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+4309
-2008
lines changed

docs/telemetry.md

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -142,20 +142,23 @@ Finally, if `setupStep2()` was the thing that failed we would see a metric like:
142142

143143
## Adding a "Stack Trace" to your metric
144144

145-
### Problem
145+
When errors are thrown we do not attach the stack trace in telemetry. We only know about the error itself, but
146+
not the path it took to get there. We sometimes need this stack trace to debug, and only have telemetry to get insight on what happened since we do not have access to logs.
147+
148+
### Scenario
146149

147150
Common example: _"I have a function, `thisFailsSometimes()` that is called in multiple places. The function sometimes fails, I know from telemetry, but I do not know if it is failing when it is a specific caller. If I knew the call stack/trace that it took to call my function that would help me debug."_
148151

149152
```typescript
150-
function outerA() {
153+
function runsSuccessfully() {
151154
thisFailsSometimes(1) // this succeeds
152155
}
153156

154-
function outerB() {
157+
function thisThrows() {
155158
thisFailsSometimes(0) // this fails
156159
}
157160

158-
function thisFailsSometimes(num: number) {
161+
function failsDependingOnInput(num: number) {
159162
return telemetry.my_Metric.run(() => {
160163
if (number === 0) {
161164
throw Error('Cannot be 0')
@@ -167,31 +170,61 @@ function thisFailsSometimes(num: number) {
167170

168171
### Solution
169172

170-
Add a value to `function` in the options of a `run()`. This will result in a stack of functions identifiers that were previously called
171-
before `thisFailsSometimes()` was run. You can then retrieve the stack in the `run()` of your final metric using `getFunctionStack()`.
173+
On class methods, use the `@withTelemetryContext()` decorator to add context to the execution. Depending on the args set, it provides features like emitting the result, or adding it's context to errors.
174+
175+
> NOTE: Decorators are currently only supported for methods and not functions
176+
177+
```typescript
178+
class MyClass {
179+
@withTelemetryContext({ name: 'runsSuccessfully', class: 'MyClass' })
180+
public runsSuccessfully() {
181+
failsDependingOnInput(1)
182+
}
183+
184+
@withTelemetryContext({ name: 'thisThrows', class: 'MyClass', errorCtx: true })
185+
public thisThrows() {
186+
failsDependingOnInput(0)
187+
}
188+
189+
@withTelemetryContext({ name: 'failsDependingOnInput' class: 'MyClass', emit: true, errorCtx: true})
190+
private failsDependingOnInput(num: number) {
191+
if (number === 0) {
192+
throw Error('Cannot be 0')
193+
}
194+
...
195+
}
196+
}
197+
198+
// Results in a metric: { source: 'MyClass#thisThrows,failsDependingOnInput', result: 'Failed' }
199+
// Results in an error that has context about the methods that lead up to it.
200+
new MyClass().thisThrows()
201+
```
202+
203+
Separately if you must use a function, add a value to `function` in the options of a `run()`. This will result in a stack of functions identifiers that were previously called
204+
before `failsDependingOnInput()` was run. You can then retrieve the stack in the `run()` of your final metric using `getFunctionStack()`.
172205

173206
```typescript
174-
function outerA() {
175-
telemetry.my_Metric.run(() => thisFailsSometimes(1), { functionId: { name: 'outerA' }})
207+
function runsSuccessfully() {
208+
telemetry.my_Metric.run(() => failsDependingOnInput(1), { functionId: { name: 'runsSuccessfully' }})
176209
}
177210

178-
function outerB() {
179-
telemetry.my_Metric.run(() => thisFailsSometimes(0), { functionId: { source: 'outerB' }})
211+
function thisThrows() {
212+
telemetry.my_Metric.run(() => failsDependingOnInput(0), { functionId: { source: 'thisThrows' }})
180213
}
181214

182-
function thisFailsSometimes(num: number) {
215+
function failsDependingOnInput(num: number) {
183216
return telemetry.my_Metric.run(() => {
184217
telemetry.record({ theCallStack: asStringifiedStack(telemetry.getFunctionStack())})
185218
if (number === 0) {
186219
throw Error('Cannot be 0')
187220
}
188221
...
189-
}, { functionId: { name: 'thisFailsSometimes' }})
222+
}, { functionId: { name: 'failsDependingOnInput' }})
190223
}
191224

192-
// Results in a metric: { theCallStack: 'outerB:thisFailsSometimes', result: 'Failed' }
193-
// { theCallStack: 'outerB:thisFailsSometimes' } implies 'outerB' was run first, then 'thisFailsSometimes'. See docstrings for more info.
194-
outerB()
225+
// Results in a metric: { theCallStack: 'thisThrows:failsDependingOnInput', result: 'Failed' }
226+
// { theCallStack: 'thisThrows:failsDependingOnInput' } implies 'thisThrows' was run first, then 'failsDependingOnInput'. See docstrings for more info.
227+
thisThrows()
195228
```
196229

197230
### Important Notes
@@ -216,25 +249,6 @@ outerB()
216249
c() // result: 'a:c', note that 'b' is not included
217250
```
218251

219-
- If you are using `run()` with a class method, you can also add the class to the entry for more context
220-
221-
```typescript
222-
class A {
223-
a() {
224-
return telemetry.my_Metric.run(() => this.b(), { functionId: { name: 'a', class: 'A' } })
225-
}
226-
227-
b() {
228-
return telemetry.my_Metric.run(() => asStringifiedStack(telemetry.getFunctionStack()), {
229-
functionId: { name: 'b', class: 'A' },
230-
})
231-
}
232-
}
233-
234-
const inst = new A()
235-
inst.a() // 'A#a,b'
236-
```
237-
238252
- If you do not want your `run()` to emit telemetry, set `emit: false` in the options
239253

240254
```typescript

package-lock.json

Lines changed: 11 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "Amazon Q chat: `@workspace` command shown in all tab types"
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "Chat container exceeds width of container"
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "amazon q inline: skip indexing when no workspace folders are found"
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "file details and name unneccessary cropping"
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "Amazon Q /dev: update diff window behavior after a change is accepted"
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Feature",
3+
"description": "Feature(Amazon Q Code Transformation): support conversions of embedded SQL from Oracle to PostgreSQL"
4+
}

packages/amazonq/src/extensionNode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ async function activateAmazonQNode(context: vscode.ExtensionContext) {
7575
...authState,
7676
})
7777

78-
await activateNotifications(context, authState, getAuthState)
78+
void activateNotifications(context, authState, getAuthState)
7979
}
8080

8181
async function getAuthState(): Promise<Omit<AuthUserState, 'source'>> {

packages/amazonq/test/unit/amazonqFeatureDev/session/session.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ describe('session', () => {
109109
it('only insert non rejected files', async () => {
110110
const fsSpyWriteFile = sinon.spy(fs, 'writeFile')
111111
const session = await createCodeGenState()
112+
sinon.stub(session, 'sendLinesOfCodeAcceptedTelemetry').resolves()
112113
await sessionWriteFile(session, uri, encodedContent)
113114
await session.insertChanges()
114115

0 commit comments

Comments
 (0)