Skip to content

Commit bee45ab

Browse files
authored
Initial logging implementation (#77)
* started work overhauling validation logic * so much validation * some folder resturcuting * loggign hierarchy * basic logging impl * implement warning events * tests for logging and such
1 parent 4cca38f commit bee45ab

Some content is hidden

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

53 files changed

+1854
-989
lines changed

src/administration/astra-admin.ts

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ import {
2222
ListDatabasesOptions,
2323
} from '@/src/administration/types';
2424
import { AstraDbAdmin } from '@/src/administration/astra-db-admin';
25-
import { DbSpawnOptions, InternalRootClientOpts } from '@/src/client/types';
2625
import { Db } from '@/src/db/db';
27-
import { validateAdminOpts } from '@/src/administration/utils';
2826
import { DEFAULT_DEVOPS_API_ENDPOINTS, DEFAULT_KEYSPACE, HttpMethods } from '@/src/lib/api/constants';
2927
import { DevOpsAPIHttpClient } from '@/src/lib/api/clients/devops-api-http-client';
3028
import { TokenProvider, WithTimeout } from '@/src/lib';
29+
import { parseAdminSpawnOpts } from '@/src/client/parsers/spawn-admin';
30+
import { InternalRootClientOpts } from '@/src/client/types/internal';
31+
import { DbSpawnOptions, Logger } from '@/src/client';
32+
import { buildAstraEndpoint } from '@/src/lib/utils';
3133

3234
/**
3335
* An administrative class for managing Astra databases, including creating, listing, and deleting databases.
@@ -64,24 +66,31 @@ export class AstraAdmin {
6466
*
6567
* @internal
6668
*/
67-
constructor(rootOpts: InternalRootClientOpts, adminOpts?: AdminSpawnOptions) {
68-
validateAdminOpts(adminOpts);
69+
constructor(rootOpts: InternalRootClientOpts, rawAdminOpts?: AdminSpawnOptions) {
70+
const adminOpts = parseAdminSpawnOpts(rawAdminOpts, 'options');
6971

70-
this.#defaultOpts = rootOpts;
72+
const token = TokenProvider.parseToken([adminOpts?.adminToken, rootOpts.adminOptions.adminToken], 'admin token');
7173

72-
const combinedAdminOpts = {
73-
...rootOpts.adminOptions,
74-
...adminOpts,
75-
adminToken: TokenProvider.parseToken(adminOpts?.adminToken ?? rootOpts.adminOptions.adminToken),
74+
this.#defaultOpts = {
75+
...rootOpts,
76+
adminOptions: {
77+
endpointUrl: adminOpts?.endpointUrl || rootOpts.adminOptions.endpointUrl,
78+
adminToken: token,
79+
logging: Logger.advanceConfig(rootOpts.adminOptions.logging, adminOpts?.logging),
80+
},
81+
dbOptions: {
82+
...rootOpts.dbOptions,
83+
token: TokenProvider.parseToken([rootOpts.dbOptions.token, token], 'admin token'),
84+
},
7685
};
7786

7887
this.#httpClient = new DevOpsAPIHttpClient({
79-
baseUrl: combinedAdminOpts.endpointUrl || DEFAULT_DEVOPS_API_ENDPOINTS.prod,
80-
monitorCommands: combinedAdminOpts.monitorCommands,
88+
baseUrl: this.#defaultOpts.adminOptions.endpointUrl || DEFAULT_DEVOPS_API_ENDPOINTS.prod,
89+
logging: this.#defaultOpts.adminOptions.logging,
8190
emitter: rootOpts.emitter,
8291
fetchCtx: rootOpts.fetchCtx,
8392
userAgent: rootOpts.userAgent,
84-
tokenProvider: combinedAdminOpts.adminToken,
93+
tokenProvider: this.#defaultOpts.adminOptions.adminToken,
8594
});
8695
}
8796

@@ -245,7 +254,8 @@ export class AstraAdmin {
245254

246255
public dbAdmin(endpointOrId: string, regionOrOptions?: string | DbSpawnOptions, maybeOptions?: DbSpawnOptions): AstraDbAdmin {
247256
/* @ts-expect-error - calls internal representation of method */
248-
return this.db(endpointOrId, regionOrOptions, maybeOptions).admin(this.#defaultOpts.adminOptions);
257+
return this.db(endpointOrId, regionOrOptions, maybeOptions)
258+
.admin(this.#defaultOpts.adminOptions);
249259
}
250260

251261
/**
@@ -396,8 +406,9 @@ export class AstraAdmin {
396406
options,
397407
});
398408

399-
const db = this.db(resp.headers.location, definition.region, { ...options?.dbOptions, keyspace: definition.keyspace });
400-
return db.admin(this.#defaultOpts.adminOptions);
409+
const endpoint = buildAstraEndpoint(resp.headers.location, definition.region);
410+
const db = this.db(endpoint, { ...options?.dbOptions, keyspace: definition.keyspace });
411+
return new AstraDbAdmin(db, this.#defaultOpts, {}, this.#defaultOpts.adminOptions.adminToken, endpoint);
401412
}
402413

403414
/**
@@ -425,7 +436,7 @@ export class AstraAdmin {
425436
*
426437
* @remarks Use with caution. Wear a harness. Don't say I didn't warn you.
427438
*/
428-
async dropDatabase(db: Db | string, options?: AdminBlockingOptions): Promise<void> {
439+
public async dropDatabase(db: Db | string, options?: AdminBlockingOptions): Promise<void> {
429440
const id = typeof db === 'string' ? db : db.id;
430441

431442
await this.#httpClient.requestLongRunning({
@@ -440,7 +451,7 @@ export class AstraAdmin {
440451
});
441452
}
442453

443-
private get _httpClient() {
454+
public get _httpClient() {
444455
return this.#httpClient;
445456
}
446457
}

src/administration/astra-db-admin.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,24 @@
1313
// limitations under the License.
1414
// noinspection ExceptionCaughtLocallyJS
1515

16-
import { AdminBlockingOptions, AdminSpawnOptions, CreateKeyspaceOptions, FullDatabaseInfo } from '@/src/administration/types';
16+
import {
17+
AdminBlockingOptions,
18+
AdminSpawnOptions,
19+
CreateKeyspaceOptions,
20+
FullDatabaseInfo,
21+
} from '@/src/administration/types';
1722
import { DbAdmin } from '@/src/administration/db-admin';
1823
import { WithTimeout } from '@/src/lib/types';
19-
import { InternalRootClientOpts } from '@/src/client/types';
20-
import { extractAstraEnvironment, validateAdminOpts } from '@/src/administration/utils';
24+
import { extractAstraEnvironment } from '@/src/administration/utils';
2125
import { FindEmbeddingProvidersResult } from '@/src/administration/types/db-admin/find-embedding-providers';
2226
import { DEFAULT_DEVOPS_API_ENDPOINTS, HttpMethods } from '@/src/lib/api/constants';
2327
import { DevOpsAPIHttpClient } from '@/src/lib/api/clients/devops-api-http-client';
2428
import { Db } from '@/src/db';
2529
import { StaticTokenProvider, TokenProvider } from '@/src/lib';
2630
import { isNullish } from '@/src/lib/utils';
31+
import { parseAdminSpawnOpts } from '@/src/client/parsers/spawn-admin';
32+
import { InternalRootClientOpts } from '@/src/client/types/internal';
33+
import { Logger } from '@/src/lib/logging/logger';
2734

2835
/**
2936
* An administrative class for managing Astra databases, including creating, listing, and deleting keyspaces.
@@ -67,17 +74,12 @@ export class AstraDbAdmin extends DbAdmin {
6774
*
6875
* @internal
6976
*/
70-
constructor(db: Db, rootOpts: InternalRootClientOpts, adminOpts: AdminSpawnOptions | undefined, dbToken: TokenProvider, endpoint: string) {
77+
constructor(db: Db, rootOpts: InternalRootClientOpts, rawAdminOpts: AdminSpawnOptions | undefined, dbToken: TokenProvider | undefined, endpoint: string) {
7178
super();
7279

73-
validateAdminOpts(adminOpts);
80+
const adminOpts = parseAdminSpawnOpts(rawAdminOpts, 'options');
7481

75-
const combinedAdminOpts = {
76-
...rootOpts.adminOptions,
77-
...adminOpts,
78-
};
79-
80-
const _adminToken = TokenProvider.parseToken(adminOpts?.adminToken ?? rootOpts.adminOptions.adminToken);
82+
const _adminToken = TokenProvider.parseToken([adminOpts?.adminToken, rootOpts.adminOptions.adminToken], 'admin token');
8183

8284
const adminToken = (_adminToken instanceof StaticTokenProvider && isNullish(_adminToken.getToken()))
8385
? dbToken
@@ -86,8 +88,8 @@ export class AstraDbAdmin extends DbAdmin {
8688
const environment = extractAstraEnvironment(endpoint);
8789

8890
this.#httpClient = new DevOpsAPIHttpClient({
89-
baseUrl: combinedAdminOpts.endpointUrl ?? DEFAULT_DEVOPS_API_ENDPOINTS[environment],
90-
monitorCommands: combinedAdminOpts.monitorCommands,
91+
baseUrl: adminOpts?.endpointUrl ?? rootOpts.adminOptions.endpointUrl ?? DEFAULT_DEVOPS_API_ENDPOINTS[environment],
92+
logging: Logger.advanceConfig(rootOpts.adminOptions.logging, adminOpts?.logging),
9193
fetchCtx: rootOpts.fetchCtx,
9294
emitter: rootOpts.emitter,
9395
userAgent: rootOpts.userAgent,
@@ -317,7 +319,7 @@ export class AstraDbAdmin extends DbAdmin {
317319
});
318320
}
319321

320-
private get _httpClient() {
322+
public get _httpClient() {
321323
return this.#httpClient;
322324
}
323325
}

src/administration/data-api-db-admin.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
import { AdminBlockingOptions, AdminSpawnOptions, LocalCreateKeyspaceOptions } from '@/src/administration/types';
1717
import { DbAdmin } from '@/src/administration/db-admin';
1818
import { WithTimeout } from '@/src/lib/types';
19-
import { validateAdminOpts } from '@/src/administration/utils';
2019
import { FindEmbeddingProvidersResult } from '@/src/administration/types/db-admin/find-embedding-providers';
2120
import { DataAPIHttpClient } from '@/src/lib/api/clients/data-api-http-client';
2221
import { Db } from '@/src/db';
22+
import { parseAdminSpawnOpts } from '@/src/client/parsers/spawn-admin';
2323

2424
/**
2525
* An administrative class for managing non-Astra databases, including creating, listing, and deleting keyspaces.
@@ -34,7 +34,7 @@ import { Db } from '@/src/db';
3434
*
3535
* // Create an admin instance through a Db
3636
* const db = client.db('*ENDPOINT*');
37-
* const dbAdmin1 = db.admin({ environment: 'dse' );
37+
* const dbAdmin1 = db.admin({ environment: 'dse' });
3838
* const dbAdmin2 = db.admin({ environment: 'dse', adminToken: 'stronger-token' });
3939
*
4040
* await admin1.createKeyspace({
@@ -55,18 +55,17 @@ import { Db } from '@/src/db';
5555
* @public
5656
*/
5757
export class DataAPIDbAdmin extends DbAdmin {
58-
readonly #httpClient!: DataAPIHttpClient;
59-
readonly #db!: Db;
58+
readonly #httpClient: DataAPIHttpClient;
59+
readonly #db: Db;
6060

6161
/**
6262
* Use {@link Db.admin} to obtain an instance of this class.
6363
*
6464
* @internal
6565
*/
66-
constructor(db: Db, httpClient: DataAPIHttpClient, adminOpts?: AdminSpawnOptions) {
66+
constructor(db: Db, httpClient: DataAPIHttpClient, rawAdminOpts?: AdminSpawnOptions) {
6767
super();
68-
validateAdminOpts(adminOpts);
69-
68+
const adminOpts = parseAdminSpawnOpts(rawAdminOpts, 'options');
7069
this.#httpClient = httpClient.forDbAdmin(adminOpts);
7170
this.#db = db;
7271
}
@@ -146,7 +145,7 @@ export class DataAPIDbAdmin extends DbAdmin {
146145
* await dbAdmin.createKeyspace('my_keyspace', {
147146
*   replication: {
148147
*   class: 'SimpleStrategy',
149-
*   replicatonFactor: 3,
148+
*   replicationFactor: 3,
150149
*   },
151150
* });
152151
*
@@ -202,7 +201,7 @@ export class DataAPIDbAdmin extends DbAdmin {
202201
await this.#httpClient.executeCommand({ dropKeyspace: { name: keyspace } }, { maxTimeMS: options?.maxTimeMS, keyspace: null });
203202
}
204203

205-
private get _httpClient() {
204+
public get _httpClient() {
206205
return this.#httpClient;
207206
}
208207
}

src/administration/events.ts

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
// limitations under the License.
1414

1515
import { DevOpsAPIRequestInfo } from '@/src/lib/api/clients/devops-api-http-client';
16-
import { hrTimeMs } from '@/src/lib/api/clients/http-client';
16+
import { DataAPIErrorDescriptor } from '@/src/documents';
17+
import { DataAPIClientEvent } from '@/src/lib/logging/events';
1718

1819
/**
1920
* The events emitted by the {@link DataAPIClient}. These events are emitted at various stages of the
@@ -38,14 +39,15 @@ export type AdminCommandEvents = {
3839
* Emitted when an admin command has errored.
3940
*/
4041
adminCommandFailed: (event: AdminCommandFailedEvent) => void,
42+
adminCommandWarnings: (event: AdminCommandWarningsEvent) => void,
4143
}
4244

4345
/**
4446
* Common base class for all admin command events.
4547
*
4648
* @public
4749
*/
48-
export abstract class AdminCommandEvent {
50+
export abstract class AdminCommandEvent extends DataAPIClientEvent {
4951
/**
5052
* The path for the request, not including the Base URL.
5153
*/
@@ -77,12 +79,17 @@ export abstract class AdminCommandEvent {
7779
* @internal
7880
*/
7981
protected constructor(info: DevOpsAPIRequestInfo, longRunning: boolean) {
82+
super();
8083
this.path = info.path;
8184
this.method = info.method;
8285
this.reqBody = info.data;
8386
this.params = info.params;
8487
this.longRunning = longRunning;
8588
}
89+
90+
formatted(): string {
91+
return JSON.stringify(this);
92+
}
8693
}
8794

8895
/**
@@ -107,6 +114,10 @@ export class AdminCommandStartedEvent extends AdminCommandEvent {
107114
super(info, longRunning);
108115
this.timeout = timeout;
109116
}
117+
118+
formatted(): string {
119+
return JSON.stringify(this);
120+
}
110121
}
111122

112123
/**
@@ -136,9 +147,13 @@ export class AdminCommandPollingEvent extends AdminCommandEvent {
136147
*/
137148
constructor(info: DevOpsAPIRequestInfo, started: number, interval: number) {
138149
super(info, true);
139-
this.elapsed = hrTimeMs() - started;
150+
this.elapsed = performance.now() - started;
140151
this.interval = interval;
141152
}
153+
154+
formatted(): string {
155+
return JSON.stringify(this);
156+
}
142157
}
143158

144159
/**
@@ -159,25 +174,20 @@ export class AdminCommandSucceededEvent extends AdminCommandEvent {
159174
*/
160175
public readonly resBody?: Record<string, any>;
161176

162-
/**
163-
* Any warnings returned from the Data API that may point out deprecated/incorrect practices,
164-
* or any other issues that aren't strictly an error.
165-
*
166-
* Does not apply to Astra users, as the admin classes will use the DevOps API instead.
167-
*/
168-
public readonly warnings: string[];
169-
170177
/**
171178
* Should not be instantiated by the user.
172179
*
173180
* @internal
174181
*/
175-
constructor(info: DevOpsAPIRequestInfo, longRunning: boolean, data: Record<string, any> | undefined, warnings: string[], started: number) {
182+
constructor(info: DevOpsAPIRequestInfo, longRunning: boolean, data: Record<string, any> | undefined, started: number) {
176183
super(info, longRunning);
177-
this.duration = hrTimeMs() - started;
178-
this.warnings = warnings;
184+
this.duration = performance.now() - started;
179185
this.resBody = data || undefined;
180186
}
187+
188+
formatted(): string {
189+
return JSON.stringify(this);
190+
}
181191
}
182192

183193
/**
@@ -208,7 +218,24 @@ export class AdminCommandFailedEvent extends AdminCommandEvent {
208218
*/
209219
constructor(info: DevOpsAPIRequestInfo, longRunning: boolean, error: Error, started: number) {
210220
super(info, longRunning);
211-
this.duration = hrTimeMs() - started;
221+
this.duration = performance.now() - started;
212222
this.error = error;
213223
}
224+
225+
formatted(): string {
226+
return JSON.stringify(this);
227+
}
228+
}
229+
230+
export class AdminCommandWarningsEvent extends AdminCommandEvent {
231+
public readonly warnings: DataAPIErrorDescriptor[];
232+
233+
constructor(info: DevOpsAPIRequestInfo, longRunning: boolean, warnings: DataAPIErrorDescriptor[]) {
234+
super(info, longRunning);
235+
this.warnings = warnings;
236+
}
237+
238+
formatted(): string {
239+
return JSON.stringify(this);
240+
}
214241
}

src/administration/types/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export type {
4444

4545
export type {
4646
AdminSpawnOptions,
47-
} from './admin/spawn-admin';
47+
} from '../../client/types/spawn-admin';
4848

4949
export type {
5050
CreateKeyspaceOptions,

src/administration/utils.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,6 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
import { AdminSpawnOptions } from '@/src/administration/types';
16-
import { validateOption } from '@/src/documents/utils';
17-
18-
/**
19-
* @internal
20-
*/
21-
export function validateAdminOpts(opts: AdminSpawnOptions | undefined) {
22-
validateOption('adminOptions', opts, 'object', false, (opts) => {
23-
validateOption('adminOptions.monitorCommands', opts.monitorCommands, 'boolean');
24-
validateOption('adminOptions.endpointUrl', opts.endpointUrl, 'string');
25-
});
26-
}
27-
2815
/**
2916
* @internal
3017
*/

0 commit comments

Comments
 (0)