Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Context building slog sender #10300

Merged
merged 31 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2181df1
some cases with logging to file
usmanmani1122 Oct 18, 2024
aba689a
cases handled, remaining persistence and reporting to otel libraries
usmanmani1122 Oct 20, 2024
b285bf3
Merge branch 'master' into usman/context-aware-slogs
usmanmani1122 Oct 21, 2024
36eeddf
persistence
usmanmani1122 Oct 21, 2024
99cbfa7
otel reporting
usmanmani1122 Oct 21, 2024
f258b97
minor final slog changes and incorporate scaling considerations
usmanmani1122 Oct 22, 2024
1d40420
cleanup
usmanmani1122 Oct 22, 2024
175affb
Merge branch 'master' into usman/context-aware-slogs
usmanmani1122 Oct 22, 2024
7d4a9b4
remove unnecessary async usage
usmanmani1122 Oct 22, 2024
696d937
move context data to labels
usmanmani1122 Oct 22, 2024
43fec2d
address mathieu comments
usmanmani1122 Oct 23, 2024
5b432dd
merge master
usmanmani1122 Oct 23, 2024
00bc5e4
yarn
usmanmani1122 Oct 23, 2024
14deff7
remove async usage
usmanmani1122 Oct 23, 2024
638d536
address mathieu comments 2.0
usmanmani1122 Oct 24, 2024
67d577a
local runner script
usmanmani1122 Oct 24, 2024
bc8baa1
remove local runner script
usmanmani1122 Oct 24, 2024
c92efa1
Merge branch 'master' into usman/context-aware-slogs
usmanmani1122 Oct 25, 2024
5f7c7b8
address mathieu comments 3.0 + fix timestamp issue
usmanmani1122 Oct 25, 2024
4cb1b6f
fix timestamp reporting
usmanmani1122 Oct 25, 2024
f5d5722
address mathieu comments 4.0
usmanmani1122 Oct 26, 2024
6b6927f
revert temp file
usmanmani1122 Oct 26, 2024
8eea7b9
Merge branch 'master' into usman/context-aware-slogs
usmanmani1122 Oct 26, 2024
f47d99c
address mathieu comments 4.1
usmanmani1122 Oct 27, 2024
d432dea
Merge branch 'master' into usman/context-aware-slogs
usmanmani1122 Oct 27, 2024
d10fccd
address mathieu comments 4.0
usmanmani1122 Oct 28, 2024
e292196
Merge branch 'master' into usman/context-aware-slogs
usmanmani1122 Oct 28, 2024
301e3bf
Merge branch 'master' into usman/context-aware-slogs
usmanmani1122 Oct 28, 2024
4392faa
address mathien comments 6.0
usmanmani1122 Oct 28, 2024
25723d6
Merge branch 'master' into usman/context-aware-slogs
usmanmani1122 Oct 28, 2024
3ddcc6d
bound methods
usmanmani1122 Oct 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/telemetry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@
"@endo/marshal": "^1.6.1",
"@endo/stream": "^1.2.7",
"@opentelemetry/api": "~1.3.0",
"@opentelemetry/api-logs": "0.53.0",
"@opentelemetry/exporter-prometheus": "~0.35.0",
"@opentelemetry/exporter-logs-otlp-http": "0.53.0",
"@opentelemetry/exporter-trace-otlp-http": "~0.35.0",
"@opentelemetry/resources": "~1.9.0",
"@opentelemetry/sdk-logs": "0.53.0",
"@opentelemetry/sdk-metrics": "~1.9.0",
"@opentelemetry/sdk-trace-base": "~1.9.0",
"@opentelemetry/semantic-conventions": "~1.27.0",
Expand Down
348 changes: 348 additions & 0 deletions packages/telemetry/src/context-aware-slog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,348 @@
/* eslint-env node */

/**
* @typedef {Partial<{
* 'block.height': Slog['blockHeight'];
* 'block.time': Slog['blockTime'];
* 'crank.deliveryNum': Slog['deliveryNum'];
* 'crank.num': Slog['crankNum'];
* 'crank.type': Slog['crankType'];
* 'crank.vatID': Slog['vatID'];
* init: boolean;
* replay: boolean;
* 'run.id': string;
* 'run.num': string | null;
* 'run.trigger.blockHeight': Slog['blockHeight'];
* 'run.trigger.msgIdx': number;
* 'run.trigger.sender': Slog['sender'];
* 'run.trigger.source': Slog['source'];
* 'run.trigger.time': Slog['blockTime'];
* 'run.trigger.txHash': string;
* 'run.trigger.type': string;
* }>
* } Context
*
* @typedef {{
* 'crank.syscallNum'?: Slog['syscallNum'];
* 'process.uptime': Slog['monotime'];
* } & Context} LogAttributes
*
* @typedef {{
* blockHeight?: number;
* blockTime?: number;
* crankNum?: bigint;
* crankType?: string;
* deliveryNum?: bigint;
* inboundNum?: string;
* monotime: number;
* replay?: boolean;
* runNum?: number;
* sender?: string;
* source?: string;
* syscallNum?: number;
* time: number;
* type: string;
* vatID?: string;
* }} Slog
*/

const SLOG_TYPES = {
CLIST: 'clist',
CONSOLE: 'console',
COSMIC_SWINGSET: {
AFTER_COMMIT_STATS: 'cosmic-swingset-after-commit-stats',
BEGIN_BLOCK: 'cosmic-swingset-begin-block',
BOOTSTRAP_BLOCK: {
FINISH: 'cosmic-swingset-bootstrap-block-finish',
START: 'cosmic-swingset-bootstrap-block-start',
},
BRIDGE_INBOUND: 'cosmic-swingset-bridge-inbound',
COMMIT: {
FINISH: 'cosmic-swingset-commit-finish',
START: 'cosmic-swingset-commit-start',
},
DELIVER_INBOUND: 'cosmic-swingset-deliver-inbound',
END_BLOCK: {
FINISH: 'cosmic-swingset-end-block-finish',
START: 'cosmic-swingset-end-block-start',
},
// eslint-disable-next-line no-restricted-syntax
RUN: {
FINISH: 'cosmic-swingset-run-finish',
START: 'cosmic-swingset-run-start',
},
},
CRANK: {
RESULT: 'crank-result',
mhofman marked this conversation as resolved.
Show resolved Hide resolved
START: 'crank-start',
},
DELIVER: 'deliver',
DELIVER_RESULT: 'deliver-result',
KERNEL: {
INIT: {
FINISH: 'kernel-init-finish',
START: 'kernel-init-start',
},
},
REPLAY: {
FINISH: 'finish-replay',
START: 'start-replay',
},
SYSCALL: 'syscall',
SYSCALL_RESULT: 'syscall-result',
};

/**
* @template {Record<string, any>} [T={}]
* @param {T} [staticContext]
* @param {Partial<{ persistContext: (context: Context) => void; restoreContext: () => Context | null; }>} [persistenceUtils]
*/
export const makeContextualSlogProcessor = (
staticContext,
persistenceUtils = {},
) => {
/** @type Array<Context | null> */
let [
blockContext,
crankContext,
initContext,
lastPersistedTriggerContext,
replayContext,
triggerContext,
] = [null, null, null, null, null, null];

/**
* @param {Context} context
*/
const persistContext = context => {
lastPersistedTriggerContext = context;
return persistenceUtils?.persistContext?.(context);
};

const restoreContext = () => {
if (!lastPersistedTriggerContext)
lastPersistedTriggerContext =
persistenceUtils?.restoreContext?.() || null;
return lastPersistedTriggerContext;
mhofman marked this conversation as resolved.
Show resolved Hide resolved
};

/**
* @param {Slog} slog
* @returns {{ attributes: T & LogAttributes, body: Partial<Slog>; timestamp: Slog['time'] }}
*/
const slogProcessor = ({ monotime, time: timestamp, ...body }) => {
const finalBody = { ...body };

/** @type {{'crank.syscallNum'?: Slog['syscallNum']}} */
const eventLogAttributes = {};

/**
* Add any before report operations here
* like setting context data
*/
switch (body.type) {
mhofman marked this conversation as resolved.
Show resolved Hide resolved
case SLOG_TYPES.KERNEL.INIT.START: {
initContext = { init: true };
break;
}
case SLOG_TYPES.COSMIC_SWINGSET.BEGIN_BLOCK: {
blockContext = {
'block.height': finalBody.blockHeight,
'block.time': finalBody.blockTime,
};
break;
}
case SLOG_TYPES.COSMIC_SWINGSET.BOOTSTRAP_BLOCK.START: {
mhofman marked this conversation as resolved.
Show resolved Hide resolved
blockContext = {
'block.height': finalBody.blockHeight || 0,
'block.time': finalBody.blockTime,
};
triggerContext = {
'run.num': null,
'run.id': `bootstrap-${finalBody.blockTime}`,
'run.trigger.type': 'bootstrap',
'run.trigger.time': finalBody.blockTime,
};
mhofman marked this conversation as resolved.
Show resolved Hide resolved
break;
}
case SLOG_TYPES.COSMIC_SWINGSET.END_BLOCK.START: {
assert(!!blockContext);
break;
}
mhofman marked this conversation as resolved.
Show resolved Hide resolved
case SLOG_TYPES.COSMIC_SWINGSET.END_BLOCK.FINISH:
case SLOG_TYPES.COSMIC_SWINGSET.BOOTSTRAP_BLOCK.FINISH:
case SLOG_TYPES.COSMIC_SWINGSET.COMMIT.START:
case SLOG_TYPES.COSMIC_SWINGSET.COMMIT.FINISH:
case SLOG_TYPES.COSMIC_SWINGSET.AFTER_COMMIT_STATS: {
assert(!!blockContext && !triggerContext);
break;
}
case SLOG_TYPES.COSMIC_SWINGSET.BRIDGE_INBOUND:
case SLOG_TYPES.COSMIC_SWINGSET.DELIVER_INBOUND: {
const [blockHeight, txHash, msgIdx] = (
finalBody.inboundNum || ''
).split('-');
const [, triggerType] =
/cosmic-swingset-([^-]+)-inbound/.exec(body.type) || [];

triggerContext = {
'run.num': null,
mhofman marked this conversation as resolved.
Show resolved Hide resolved
'run.id': `${triggerType}-${finalBody.inboundNum}`,
'run.trigger.type': triggerType,
'run.trigger.source': finalBody.source,
'run.trigger.sender': finalBody.sender,
'run.trigger.blockHeight': Number(blockHeight),
'run.trigger.txHash': txHash,
'run.trigger.msgIdx': Number(msgIdx),
};
persistContext(triggerContext);
mhofman marked this conversation as resolved.
Show resolved Hide resolved
break;
}
// eslint-disable-next-line no-restricted-syntax
case SLOG_TYPES.COSMIC_SWINGSET.RUN.START: {
if (!triggerContext && finalBody.runNum !== 0) {
mhofman marked this conversation as resolved.
Show resolved Hide resolved
assert(!!blockContext);
// TODO: add explicit slog events of both timer poll and install bundle
// https://github.com/Agoric/agoric-sdk/issues/10332
triggerContext = {
'run.num': null,
'run.id': `unknown-${finalBody.blockHeight}-${finalBody.runNum}`,
'run.trigger.type': 'unknown',
'run.trigger.time': blockContext['block.time'],
mhofman marked this conversation as resolved.
Show resolved Hide resolved
'run.trigger.blockHeight': finalBody.blockHeight,
};
persistContext(triggerContext);
mhofman marked this conversation as resolved.
Show resolved Hide resolved
}

if (!triggerContext) triggerContext = {};
triggerContext['run.num'] = `${finalBody.runNum}`;

break;
}
case SLOG_TYPES.CRANK.START: {
crankContext = {
'crank.num': finalBody.crankNum,
'crank.type': finalBody.crankType,
};
break;
}
case SLOG_TYPES.CLIST: {
assert(!!crankContext);
crankContext['crank.vatID'] = finalBody.vatID;
break;
}
case SLOG_TYPES.REPLAY.START: {
replayContext = { replay: true };
mhofman marked this conversation as resolved.
Show resolved Hide resolved
break;
}
case SLOG_TYPES.DELIVER: {
if (replayContext) {
assert(finalBody.replay);
replayContext = {
...replayContext,
'crank.vatID': finalBody.vatID,
'crank.deliveryNum': finalBody.deliveryNum,
};
} else {
assert(!!crankContext && !finalBody.replay);
crankContext = {
...crankContext,
'crank.vatID': finalBody.vatID,
'crank.deliveryNum': finalBody.deliveryNum,
};
}

delete finalBody.deliveryNum;
delete finalBody.replay;

break;
}
case SLOG_TYPES.DELIVER_RESULT: {
delete finalBody.deliveryNum;
delete finalBody.replay;

break;
}
case SLOG_TYPES.SYSCALL:
case SLOG_TYPES.SYSCALL_RESULT: {
eventLogAttributes['crank.syscallNum'] = finalBody.syscallNum;

delete finalBody.deliveryNum;
delete finalBody.replay;
delete finalBody.syscallNum;

break;
}
case SLOG_TYPES.CONSOLE: {
delete finalBody.crankNum;
delete finalBody.deliveryNum;

break;
}
default:
// All other log types are logged as is (using existing contexts) without
// any change to the slogs or any contributions to the contexts. This also
// means that any unexpected slog type will pass through. To fix that, add
// all remaining cases of expected slog types above with a simple break
// statement and log a warning here
break;
mhofman marked this conversation as resolved.
Show resolved Hide resolved
}

const logAttributes = {
'process.uptime': monotime,
...initContext, // Optional prelude
...blockContext, // Block is the first level of execution nesting
...triggerContext, // run and trigger info is nested next
...crankContext, // Finally cranks are the last level of nesting
...replayContext, // Replay is a substitute for crank context during vat page in
...eventLogAttributes,
...staticContext,
mhofman marked this conversation as resolved.
Show resolved Hide resolved
};

/**
* Add any after report operations here
* like resetting context data
*/
switch (body.type) {
case SLOG_TYPES.KERNEL.INIT.FINISH: {
initContext = null;
break;
}
mhofman marked this conversation as resolved.
Show resolved Hide resolved
case SLOG_TYPES.COSMIC_SWINGSET.END_BLOCK.START: {
triggerContext = restoreContext();
break;
}
mhofman marked this conversation as resolved.
Show resolved Hide resolved
case SLOG_TYPES.COSMIC_SWINGSET.AFTER_COMMIT_STATS: {
blockContext = null;
break;
}
mhofman marked this conversation as resolved.
Show resolved Hide resolved
case SLOG_TYPES.COSMIC_SWINGSET.BOOTSTRAP_BLOCK.FINISH: {
blockContext = null;
break;
}
// eslint-disable-next-line no-restricted-syntax
case SLOG_TYPES.COSMIC_SWINGSET.RUN.FINISH: {
triggerContext = null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a mistake on the logic of the trigger context persistence. We need to conditionally persist the context here:

Suggested change
triggerContext = null;
persistContext(finalBody.remainingBeans > 0 ? null : triggerContext);
triggerContext = null;

Then we can simply restore the context on run start for runNum === 0 I think.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I think we can persist an empty context instead (so you can keep null as missing).

Suggested change
triggerContext = null;
persistContext(finalBody.remainingBeans > 0 ? {} : triggerContext);
triggerContext = null;

Copy link
Contributor Author

@usmanmani1122 usmanmani1122 Oct 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have no assertion on triggerContext here, it could be null at this point. So I think we should either do

persistContext(finalBody.remainingBeans || !triggerContext ? {} : triggerContext);

Or have an assertion:

assert(!!triggerContext);
persistContext(finalBody.remainingBeans ? {} : triggerContext)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a trigger context by this point. Let's add an assertion

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized that in the final version the > 0 part of the check was dropped, which causes the persisted context to always be empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we are missing the context in case of negative remaining beans right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are missing the persisted context roughly always because the remaining beans is almost never 0.

break;
}
case SLOG_TYPES.CRANK.RESULT: {
crankContext = null;
break;
}
case SLOG_TYPES.REPLAY.FINISH: {
replayContext = null;
break;
}
default:
break;
}

return {
attributes: /** @type {T & LogAttributes} */ (logAttributes),
body: finalBody,
timestamp,
};
};
mhofman marked this conversation as resolved.
Show resolved Hide resolved

return slogProcessor;
};
Loading
Loading