mirror of
https://github.com/bitwarden/browser
synced 2026-02-26 09:33:22 +00:00
feat: include callee information
This commit is contained in:
@@ -1641,6 +1641,7 @@ const safeProviders: SafeProvider[] = [
|
||||
ApiServiceAbstraction,
|
||||
StateProvider,
|
||||
ConfigService,
|
||||
LogService,
|
||||
],
|
||||
}),
|
||||
safeProvider({
|
||||
|
||||
@@ -20,6 +20,7 @@ import { UserId } from "../../../types/guid";
|
||||
import { UserKey } from "../../../types/key";
|
||||
import { ConfigService } from "../../abstractions/config/config.service";
|
||||
import { Environment, EnvironmentService } from "../../abstractions/environment.service";
|
||||
import { LogService } from "../../abstractions/log.service";
|
||||
import { PlatformUtilsService } from "../../abstractions/platform-utils.service";
|
||||
import { SdkClientFactory } from "../../abstractions/sdk/sdk-client-factory";
|
||||
import { SdkLoadService } from "../../abstractions/sdk/sdk-load.service";
|
||||
@@ -49,6 +50,7 @@ describe("DefaultSdkService", () => {
|
||||
let service!: DefaultSdkService;
|
||||
let accountService!: FakeAccountService;
|
||||
let fakeStateProvider!: FakeStateProvider;
|
||||
let logService!: MockProxy<LogService>;
|
||||
let apiService!: MockProxy<ApiService>;
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -64,6 +66,7 @@ describe("DefaultSdkService", () => {
|
||||
const mockUserId = Utils.newGuid() as UserId;
|
||||
accountService = mockAccountServiceWith(mockUserId);
|
||||
fakeStateProvider = new FakeStateProvider(accountService);
|
||||
logService = mock<LogService>();
|
||||
configService = mock<ConfigService>();
|
||||
|
||||
configService.serverConfig$ = new BehaviorSubject(null);
|
||||
@@ -82,6 +85,7 @@ describe("DefaultSdkService", () => {
|
||||
apiService,
|
||||
fakeStateProvider,
|
||||
configService,
|
||||
logService,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -23,11 +23,8 @@ import { KeyService, KdfConfigService, KdfConfig, KdfType } from "@bitwarden/key
|
||||
import {
|
||||
PasswordManagerClient,
|
||||
ClientSettings,
|
||||
EventDefinition,
|
||||
FieldValue,
|
||||
DeviceType as SdkDeviceType,
|
||||
Span,
|
||||
SpanDefinition,
|
||||
TokenProvider,
|
||||
TracingLevel,
|
||||
UnsignedSharedKey,
|
||||
@@ -40,6 +37,7 @@ import { EncString } from "../../../key-management/crypto/models/enc-string";
|
||||
import { SecurityStateService } from "../../../key-management/security-state/abstractions/security-state.service";
|
||||
import { OrganizationId, UserId } from "../../../types/guid";
|
||||
import { Environment, EnvironmentService } from "../../abstractions/environment.service";
|
||||
import { LogService } from "../../abstractions/log.service";
|
||||
import { PlatformUtilsService } from "../../abstractions/platform-utils.service";
|
||||
import { SdkClientFactory } from "../../abstractions/sdk/sdk-client-factory";
|
||||
import { SdkLoadService } from "../../abstractions/sdk/sdk-load.service";
|
||||
@@ -55,34 +53,34 @@ import { StateProvider } from "../../state";
|
||||
|
||||
import { initializeState } from "./client-managed-state";
|
||||
|
||||
const UserClientSpan = SdkLoadService.WithSdk(
|
||||
() =>
|
||||
new SpanDefinition("userClient$", "DefaultSdkService", TracingLevel.Info, [
|
||||
"userId",
|
||||
"hasOverride",
|
||||
]),
|
||||
);
|
||||
// const UserClientSpan = SdkLoadService.WithSdk(
|
||||
// () =>
|
||||
// new SpanDefinition("userClient$", "DefaultSdkService", TracingLevel.Info, [
|
||||
// "userId",
|
||||
// "hasOverride",
|
||||
// ]),
|
||||
// );
|
||||
|
||||
const InitializeClientSpan = SdkLoadService.WithSdk(
|
||||
// TODO: We can remove userId because it's already in the parent span
|
||||
() => new SpanDefinition("initializeClient", "DefaultSdkService", TracingLevel.Info, ["userId"]),
|
||||
);
|
||||
// const InitializeClientSpan = SdkLoadService.WithSdk(
|
||||
// // TODO: We can remove userId because it's already in the parent span
|
||||
// () => new SpanDefinition("initializeClient", "DefaultSdkService", TracingLevel.Info, ["userId"]),
|
||||
// );
|
||||
|
||||
const UserCryptoInitializedEvent = SdkLoadService.WithSdk(
|
||||
() => new EventDefinition("User crypto initialized", "DefaultSdkService", TracingLevel.Info, []),
|
||||
);
|
||||
// const UserCryptoInitializedEvent = SdkLoadService.WithSdk(
|
||||
// () => new EventDefinition("User crypto initialized", "DefaultSdkService", TracingLevel.Info, []),
|
||||
// );
|
||||
|
||||
const OrgCryptoInitializedEvent = SdkLoadService.WithSdk(
|
||||
() => new EventDefinition("Org crypto initialized", "DefaultSdkService", TracingLevel.Info, []),
|
||||
);
|
||||
// const OrgCryptoInitializedEvent = SdkLoadService.WithSdk(
|
||||
// () => new EventDefinition("Org crypto initialized", "DefaultSdkService", TracingLevel.Info, []),
|
||||
// );
|
||||
|
||||
const ClientStateInitializedEvent = SdkLoadService.WithSdk(
|
||||
() => new EventDefinition("Client state initialized", "DefaultSdkService", TracingLevel.Info, []),
|
||||
);
|
||||
// const ClientStateInitializedEvent = SdkLoadService.WithSdk(
|
||||
// () => new EventDefinition("Client state initialized", "DefaultSdkService", TracingLevel.Info, []),
|
||||
// );
|
||||
|
||||
const FeatureFlagsLoadedEvent = SdkLoadService.WithSdk(
|
||||
() => new EventDefinition("Feature flags loaded", "DefaultSdkService", TracingLevel.Info, []),
|
||||
);
|
||||
// const FeatureFlagsLoadedEvent = SdkLoadService.WithSdk(
|
||||
// () => new EventDefinition("Feature flags loaded", "DefaultSdkService", TracingLevel.Info, []),
|
||||
// );
|
||||
|
||||
// A symbol that represents an overridden client that is explicitly set to undefined,
|
||||
// blocking the creation of an internal client for that user.
|
||||
@@ -142,11 +140,14 @@ export class DefaultSdkService implements SdkService {
|
||||
private apiService: ApiService,
|
||||
private stateProvider: StateProvider,
|
||||
private configService: ConfigService,
|
||||
private logService: LogService,
|
||||
private userAgent: string | null = null,
|
||||
) {}
|
||||
|
||||
userClient$(userId: UserId): Observable<Rc<PasswordManagerClient>> {
|
||||
const span = UserClientSpan.requiredValue.enter([new FieldValue("userId", userId)]);
|
||||
const span = this.logService.span("userClient$", TracingLevel.Info, [
|
||||
new FieldValue("userId", userId),
|
||||
]);
|
||||
return this.sdkClientOverrides.pipe(
|
||||
takeWhile((clients) => clients[userId] !== UnsetClient, false),
|
||||
map((clients) => {
|
||||
@@ -320,7 +321,10 @@ export class DefaultSdkService implements SdkService {
|
||||
orgKeys: Record<OrganizationId, EncString>,
|
||||
parent: Span,
|
||||
) {
|
||||
using span = (await InitializeClientSpan).enter_with_parent(parent, [
|
||||
// using span = (await InitializeClientSpan).enter_with_parent(parent, [
|
||||
// new FieldValue("userId", userId),
|
||||
// ]);
|
||||
using span = this.logService.span("initializeClient", TracingLevel.Info, [
|
||||
new FieldValue("userId", userId),
|
||||
]);
|
||||
|
||||
@@ -340,7 +344,14 @@ export class DefaultSdkService implements SdkService {
|
||||
},
|
||||
accountCryptographicState: accountCryptographicState,
|
||||
});
|
||||
span.event(await UserCryptoInitializedEvent, `User crypto initialized for user`);
|
||||
// span.event(await UserCryptoInitializedEvent, `User crypto initialized for user`);
|
||||
this.logService.event(
|
||||
span,
|
||||
"cryptoInitialized",
|
||||
`User crypto initialized for user`,
|
||||
TracingLevel.Info,
|
||||
[],
|
||||
);
|
||||
|
||||
// We initialize the org crypto even if the org_keys are
|
||||
// null to make sure any existing org keys are cleared.
|
||||
@@ -349,14 +360,32 @@ export class DefaultSdkService implements SdkService {
|
||||
Object.entries(orgKeys).map(([k, v]) => [asUuid(k), v.toJSON() as UnsignedSharedKey]),
|
||||
),
|
||||
});
|
||||
span.event(await OrgCryptoInitializedEvent, `Org crypto initialized for user`);
|
||||
this.logService.event(
|
||||
span,
|
||||
"orgCryptoInitialized",
|
||||
`Org crypto initialized for user`,
|
||||
TracingLevel.Info,
|
||||
[],
|
||||
);
|
||||
|
||||
// Initialize the SDK managed database and the client managed repositories.
|
||||
await initializeState(userId, client.platform().state(), this.stateProvider);
|
||||
span.event(await ClientStateInitializedEvent, "Client state initialized");
|
||||
this.logService.event(
|
||||
span,
|
||||
"clientStateInitialized",
|
||||
`Client state initialized`,
|
||||
TracingLevel.Info,
|
||||
[],
|
||||
);
|
||||
|
||||
await this.loadFeatureFlags(client);
|
||||
span.event(await FeatureFlagsLoadedEvent, "Feature flags loaded");
|
||||
this.logService.event(
|
||||
span,
|
||||
"featureFlagsLoaded",
|
||||
`Feature flags loaded`,
|
||||
TracingLevel.Info,
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
private async loadFeatureFlags(client: PasswordManagerClient) {
|
||||
|
||||
@@ -1,14 +1,81 @@
|
||||
// import { parse } from "stacktrace-parser";
|
||||
import StackTrace from "stacktrace-js";
|
||||
|
||||
import {
|
||||
EventDefinition,
|
||||
FieldValue,
|
||||
Span,
|
||||
SpanDefinition,
|
||||
TracingLevel,
|
||||
} from "@bitwarden/sdk-internal";
|
||||
|
||||
import { LogLevel } from "./log-level";
|
||||
import { LogService } from "./log.service";
|
||||
|
||||
export class ConsoleLogService implements LogService {
|
||||
protected timersMap: Map<string, [number, number]> = new Map();
|
||||
protected spanDefinitions = new Map<string, SpanDefinition>();
|
||||
protected eventDefinitions = new Map<string, EventDefinition>();
|
||||
|
||||
constructor(
|
||||
protected isDev: boolean,
|
||||
protected filter: ((level: LogLevel) => boolean) | null = null,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Creates a new span.
|
||||
* @param name Name of the span to create. Must be unique in the application.
|
||||
* // TODO: Consider creating the name as we do state KeyDefinitions.
|
||||
*/
|
||||
span(name: string, level: TracingLevel, fields: FieldValue[]): Span {
|
||||
let definition = this.spanDefinitions.get(name);
|
||||
if (!definition) {
|
||||
// TODO: A better way to get the caller info would be to use Webpack to modify
|
||||
// the code calling logService.span(...) at compile time to inject the file, line, and function name.
|
||||
const stack = StackTrace.getSync();
|
||||
const callee = stack[1];
|
||||
definition = new SpanDefinition(
|
||||
name,
|
||||
"",
|
||||
level,
|
||||
fields.map((f) => f.name),
|
||||
callee.fileName,
|
||||
callee.lineNumber,
|
||||
callee.functionName,
|
||||
);
|
||||
this.spanDefinitions.set(name, definition);
|
||||
}
|
||||
return definition.enter(fields);
|
||||
}
|
||||
|
||||
event(
|
||||
span: Span,
|
||||
name: string,
|
||||
message: string,
|
||||
level: TracingLevel,
|
||||
fields: FieldValue[],
|
||||
): void {
|
||||
let definition = this.eventDefinitions.get(name);
|
||||
if (!definition) {
|
||||
// TODO: A better way to get the caller info would be to use Webpack to modify
|
||||
// the code calling logService.event(...) at compile time to inject the file, line, and function name.
|
||||
const stack = StackTrace.getSync();
|
||||
const callee = stack[1];
|
||||
|
||||
definition = new EventDefinition(
|
||||
name,
|
||||
callee.functionName ?? "",
|
||||
level,
|
||||
fields.map((f) => f.name),
|
||||
callee.fileName,
|
||||
callee.lineNumber,
|
||||
callee.functionName,
|
||||
);
|
||||
this.eventDefinitions.set(name, definition);
|
||||
}
|
||||
span.event(definition, message);
|
||||
}
|
||||
|
||||
debug(message?: any, ...optionalParams: any[]) {
|
||||
if (!this.isDev) {
|
||||
return;
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
import type { FieldValue, Span, TracingLevel } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { LogLevel } from "./log-level";
|
||||
|
||||
export abstract class LogService {
|
||||
abstract span(name: string, level: TracingLevel, fields: FieldValue[]): Span;
|
||||
abstract event(
|
||||
span: Span,
|
||||
name: string,
|
||||
message: string,
|
||||
level: TracingLevel,
|
||||
fields: FieldValue[],
|
||||
): void;
|
||||
abstract debug(message?: any, ...optionalParams: any[]): void;
|
||||
abstract info(message?: any, ...optionalParams: any[]): void;
|
||||
abstract warning(message?: any, ...optionalParams: any[]): void;
|
||||
|
||||
Reference in New Issue
Block a user