├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── History.md ├── LICENSE ├── Makefile ├── Readme.md ├── client.ts ├── package-lock.json ├── package.json ├── tsconfig.browser.json └── tsconfig.json /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Changes to the generated client should be contributed to the generator [github.com/apex/rpc](https://github.com/apex/rpc/), not the generated file(s) in this repo, thanks! -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .envrc 2 | node_modules 3 | dist 4 | dist.browser 5 | test.ts 6 | test.deno.ts 7 | test.js 8 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2 | v1.2.0 / 2020-10-15 3 | =================== 4 | 5 | * regenerate to add `project.mode` property 6 | 7 | v1.1.0 / 2020-08-06 8 | =================== 9 | 10 | * add exported types 11 | 12 | v1.0.3 / 2020-07-13 13 | =================== 14 | 15 | * revert camel-casing, breaks API :) 16 | 17 | v1.0.2 / 2020-07-13 18 | =================== 19 | 20 | * fix camel-casing of fields 21 | * docs: fix the node example 22 | 23 | v1.0.2 / 2020-07-13 24 | =================== 25 | 26 | * fix package.json dist file references 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2020 TJ Holowaychuk tj@tjholowaychuk.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: dist dist.browser 3 | 4 | dist: client.ts 5 | @tsc --declaration -p tsconfig.json 6 | 7 | dist.browser: client.ts 8 | @tsc --declaration -p tsconfig.browser.json 9 | 10 | client.ts: $(SCHEMA) 11 | @echo "==> create $@" 12 | @rpc-ts-client \ 13 | -schema $(SCHEMA) \ 14 | > $@ 15 | 16 | test: 17 | @ts-node -O '{ "target": "es6" }' test.ts 18 | @deno run --allow-net --allow-env test.deno.ts 19 | .PHONY: test 20 | 21 | clean: 22 | @rm -f client.ts 23 | @rm -fr dist.browser 24 | @rm -fr dist 25 | .PHONY: clean 26 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | JavaScript client for [Apex Logs](https://apex.sh/logs/) with support for Node.js, Deno, and the browser. 4 | 5 | ## Installation 6 | 7 | ``` 8 | npm install --save apex-logs 9 | ``` 10 | 11 | ## Node 12 | 13 | Here's an example of usage in Node or the browser using the `apex-logs` NPM package: 14 | 15 | ```js 16 | const { Client } = require('apex-logs') 17 | 18 | const client = new Client({ 19 | url: '', 20 | authToken: '' 21 | }) 22 | 23 | async function run() { 24 | const { projects } = await client.getProjects() 25 | console.log(projects) 26 | 27 | const { alerts } = await client.getAlerts({ projectId: 'production' }) 28 | console.log(alerts) 29 | } 30 | 31 | run() 32 | ``` 33 | 34 | ## Deno 35 | 36 | Here's an example of usage in Deno: 37 | 38 | ```js 39 | import { Client } from 'https://deno.land/x/apex_logs/client.ts' 40 | 41 | const client = new Client({ 42 | url: '', 43 | authToken: '' 44 | }) 45 | 46 | const { projects } = await client.getProjects() 47 | console.log(projects) 48 | 49 | const { alerts } = await client.getAlerts({ projectId: 'ping_production' }) 50 | console.log(alerts) 51 | ``` 52 | 53 | 54 | ## Resources 55 | 56 | To learn more about Apex Logs visit the [documentation](https://apex.sh/docs/logs/), and to contribute to this client visit the [github.com/apex/rpc](https://github.com/apex/rpc/) project which is used to generate this client. 57 | -------------------------------------------------------------------------------- /client.ts: -------------------------------------------------------------------------------- 1 | // Do not edit, this file was generated by github.com/apex/rpc. 2 | 3 | // Alert represents configuration for performing alerting. 4 | export interface Alert { 5 | // created_at is a timestamp indicating when the alert was created. This field is read-only. 6 | created_at?: Date 7 | 8 | // description is the description of the alert. 9 | description?: string 10 | 11 | // id is the alert id. This field is read-only. 12 | id?: string 13 | 14 | // interval is the interval in minutes for performing the alert. 15 | interval?: number 16 | 17 | // limit is the maximum number of events in the alert notification. 18 | limit?: number 19 | 20 | // muted is a boolean used ignore trigger and resolve notifications. 21 | muted?: boolean 22 | 23 | // name is the name of the alert. This field is required. 24 | name: string 25 | 26 | // notification_id is the notification id for reporting alerts, when omitted the alert will not run. This field is required. 27 | notification_id: string 28 | 29 | // operator is the operator used when comparing against the threshold. This field is required. Must be one of: ">", ">=", "<", "<=". 30 | operator: string 31 | 32 | // project_id is the associated project id. This field is required. 33 | project_id: string 34 | 35 | // query is the query performed by the alert. This field is required. 36 | query: string 37 | 38 | // severity is the severity of the alert. This field is required. Must be one of: "info", "notice", "error", "critical". 39 | severity: string 40 | 41 | // threshold is the threshold for comparison against the selected operator. 42 | threshold?: number 43 | 44 | // updated_at is a timestamp indicating when the alert was last updated. This field is read-only. 45 | updated_at?: Date 46 | } 47 | 48 | // BooleanFieldStat represents a boolean field's stats. 49 | export interface BooleanFieldStat { 50 | // count is the number of times this field occurred in the sampled events. 51 | count?: number 52 | 53 | // percent is the percentage of occurrences in the sampled events. 54 | percent?: number 55 | 56 | // value is the boolean value. 57 | value?: boolean 58 | } 59 | 60 | // DiscoveredField represents a single discovered field. 61 | export interface DiscoveredField { 62 | // count is the number of times this field occurred in the sampled events. 63 | count?: number 64 | 65 | // name is the field name. 66 | name?: string 67 | 68 | // percent is the percentage of occurrences in the sampled events. 69 | percent?: number 70 | 71 | // type is the type of discovered field. Must be one of: "string", "number", "boolean". 72 | type?: string 73 | } 74 | 75 | // Event represents a single log event. 76 | export interface Event { 77 | // fields is the log fields. 78 | fields?: object 79 | 80 | // id is the event id. 81 | id?: string 82 | 83 | // level is the severity level. This field is required. Must be one of: "debug", "info", "notice", "warning", "error", "critical", "alert", "emergency". 84 | level: string 85 | 86 | // message is the log message. This field is required. 87 | message: string 88 | 89 | // timestamp is the creation timestamp. 90 | timestamp?: Date 91 | } 92 | 93 | // InstanceConfig represents an instance's configuration. 94 | export interface InstanceConfig { 95 | // project_id is the Google Cloud project id. 96 | project_id?: string 97 | 98 | // region is the Google Cloud region id. 99 | region?: string 100 | 101 | // team_id is the Apex team id. 102 | team_id?: string 103 | } 104 | 105 | // Notification represents an alert notification. 106 | export interface Notification { 107 | // created_at is a timestamp indicating when the notification was created. This field is read-only. 108 | created_at?: Date 109 | 110 | // email_addresses is the receipients of the alert notifications. 111 | email_addresses?: string[] 112 | 113 | // id is the notification id. This field is read-only. 114 | id?: string 115 | 116 | // name is the name of the notification. This field is required. 117 | name: string 118 | 119 | // pagerduty_service_key is the PagerDuty service key. 120 | pagerduty_service_key?: string 121 | 122 | // project_id is the associated project id. This field is required. 123 | project_id: string 124 | 125 | // slack_channel is the Slack channel name, otherwise the default for the webhook is used. 126 | slack_channel?: string 127 | 128 | // slack_webhook_url is the Slack webhook URL. 129 | slack_webhook_url?: string 130 | 131 | // sms_numbers is the receipients of the alert notifications. 132 | sms_numbers?: string[] 133 | 134 | // type is the type of notification. This field is required. Must be one of: "slack", "pagerduty", "email", "sms", "webhook". 135 | type: string 136 | 137 | // updated_at is a timestamp indicating when the notification was last updated. This field is read-only. 138 | updated_at?: Date 139 | 140 | // webhook_url is the webhook URL which receives the alert payloads. 141 | webhook_url?: string 142 | } 143 | 144 | // Project represents an isolated set of log events and alerts. A project can be created for each application, environment, or team within an organization depending on your preferences. 145 | export interface Project { 146 | // created_at is a timestamp indicating when the project was created. This field is read-only. 147 | created_at?: Date 148 | 149 | // description is the project description. 150 | description?: string 151 | 152 | // id is the project id. This field is read-only. 153 | id?: string 154 | 155 | // location is the geographical location where the log events are stored. This field is required. Must be one of: "us-west2", "northamerica-northeast1", "us-east4", "southamerica-east1", "europe-north1", "europe-west2", "europe-west6", "asia-east2", "asia-south1", "asia-northeast2", "asia-east1", "asia-northeast1", "asia-southeast1", "australia-southeast1". 156 | location: string 157 | 158 | // mode is the storage mode, optimized for plain-text or structured logs. Both options support plain-text and structured logging, however, the structured mode shards on the `message` value, restricting its length to 1024 bytes. This field is required. Must be one of: "plain_text", "structured". 159 | mode: string 160 | 161 | // name is the human-friendly project name. This field is required. 162 | name: string 163 | 164 | // retention is the retention of log events in days. When zero the logs do not expire. 165 | retention?: number 166 | 167 | // updated_at is a timestamp indicating when the project was last updated. This field is read-only. 168 | updated_at?: Date 169 | } 170 | 171 | // QueryStats represents query statistics. 172 | export interface QueryStats { 173 | // cache_hit is a boolean indicating if the query was cached. 174 | cache_hit?: boolean 175 | 176 | // duration is the query duration in milliseconds. 177 | duration?: number 178 | 179 | // total_bytes_billed is the total number of bytes billed by the query. 180 | total_bytes_billed?: number 181 | 182 | // total_bytes_processed is the total number of bytes processed by the query. 183 | total_bytes_processed?: number 184 | } 185 | 186 | // Search represents a saved search query. 187 | export interface Search { 188 | // created_at is a timestamp indicating when the saved search was created. This field is read-only. 189 | created_at?: Date 190 | 191 | // id is the saved search id. This field is read-only. 192 | id?: string 193 | 194 | // name is the name of the saved search. This field is required. 195 | name: string 196 | 197 | // project_id is the associated project id. This field is required. 198 | project_id: string 199 | 200 | // query is the saved search query. This field is required. 201 | query: string 202 | 203 | // updated_at is a timestamp indicating when the saved search was last updated. This field is read-only. 204 | updated_at?: Date 205 | } 206 | 207 | // StringFieldStat represents a string field's stats. 208 | export interface StringFieldStat { 209 | // count is the number of times this field occurred in the sampled events. 210 | count?: number 211 | 212 | // percent is the percentage of occurrences in the sampled events. 213 | percent?: number 214 | 215 | // value is the string value. 216 | value?: string 217 | } 218 | 219 | // TimeseriesPoint represents a single point in a timeseries query. 220 | export interface TimeseriesPoint { 221 | // count is the number of events for this bucket. 222 | count?: number 223 | 224 | // timestamp is the bucket timestamp. 225 | timestamp?: Date 226 | } 227 | 228 | // Token represents an API token. 229 | export interface Token { 230 | // created_at is a timestamp indicating when the token was created. This field is read-only. 231 | created_at?: Date 232 | 233 | // description is the description of the token. 234 | description?: string 235 | 236 | // id is the token. This field is read-only. 237 | id?: string 238 | 239 | // last_used_at is a timestamp indicating when the token was last used. This field is read-only. 240 | last_used_at?: Date 241 | 242 | // scopes is available to this token, permitting access to read and write data. This field is required. Must be one of: "events:read", "events:write", "alerts:read", "alerts:write", "notifications:read", "notifications:write", "projects:read", "projects:write", "tokens:read", "tokens:write", "searches:read", "searches:write". 243 | scopes: string[] 244 | } 245 | 246 | // AddAlertInput params. 247 | interface AddAlertInput { 248 | // alert is the alert. This field is required. 249 | alert: Alert 250 | } 251 | 252 | // AddAlertOutput params. 253 | interface AddAlertOutput { 254 | // id is the alert id. This field is required. 255 | id: string 256 | } 257 | 258 | // AddEventsInput params. 259 | interface AddEventsInput { 260 | // events is the batch of events. This field is required. 261 | events: Event[] 262 | 263 | // project_id is the project id. This field is required. 264 | project_id: string 265 | } 266 | 267 | // AddNotificationInput params. 268 | interface AddNotificationInput { 269 | // notification is the notification. This field is required. 270 | notification: Notification 271 | } 272 | 273 | // AddNotificationOutput params. 274 | interface AddNotificationOutput { 275 | // id is the notification id. This field is required. 276 | id: string 277 | } 278 | 279 | // AddProjectInput params. 280 | interface AddProjectInput { 281 | // project is the project. This field is required. 282 | project: Project 283 | } 284 | 285 | // AddProjectOutput params. 286 | interface AddProjectOutput { 287 | // id is the project id. This field is required. 288 | id: string 289 | } 290 | 291 | // AddSearchInput params. 292 | interface AddSearchInput { 293 | // search is the saved search. This field is required. 294 | search: Search 295 | } 296 | 297 | // AddSearchOutput params. 298 | interface AddSearchOutput { 299 | // id is the saved search id. This field is required. 300 | id: string 301 | } 302 | 303 | // AddTokenInput params. 304 | interface AddTokenInput { 305 | // token is the token. This field is required. 306 | token: Token 307 | } 308 | 309 | // AddTokenOutput params. 310 | interface AddTokenOutput { 311 | // id is the token id. 312 | id?: string 313 | } 314 | 315 | // GetAlertInput params. 316 | interface GetAlertInput { 317 | // alert_id is the alert id. This field is required. 318 | alert_id: string 319 | 320 | // project_id is the project id. This field is required. 321 | project_id: string 322 | } 323 | 324 | // GetAlertOutput params. 325 | interface GetAlertOutput { 326 | // alert is the alert. This field is required. 327 | alert: Alert 328 | } 329 | 330 | // GetAlertsInput params. 331 | interface GetAlertsInput { 332 | // project_id is the project id. This field is required. 333 | project_id: string 334 | } 335 | 336 | // GetAlertsOutput params. 337 | interface GetAlertsOutput { 338 | // alerts is the alerts. This field is required. 339 | alerts: Alert[] 340 | } 341 | 342 | // GetBooleanFieldStatsInput params. 343 | interface GetBooleanFieldStatsInput { 344 | // field is the field name. This field is required. 345 | field: string 346 | 347 | // project_id is the project id. This field is required. 348 | project_id: string 349 | 350 | // query is the search query string. 351 | query?: string 352 | 353 | // start is the start timestamp, events before this time are not included. This field is required. 354 | start: Date 355 | 356 | // stop is the stop timestamp, events after this time are not included. This field is required. 357 | stop: Date 358 | } 359 | 360 | // GetBooleanFieldStatsOutput params. 361 | interface GetBooleanFieldStatsOutput { 362 | // stats is the query statistics. This field is required. 363 | stats: QueryStats 364 | 365 | // values is the boolean values. This field is required. 366 | values: BooleanFieldStat[] 367 | } 368 | 369 | // GetCountInput params. 370 | interface GetCountInput { 371 | // project_id is the project id. This field is required. 372 | project_id: string 373 | 374 | // query is the search query string. 375 | query?: string 376 | 377 | // start is the start timestamp, events before this time are not included. This field is required. 378 | start: Date 379 | 380 | // stop is the stop timestamp, events after this time are not included. This field is required. 381 | stop: Date 382 | } 383 | 384 | // GetCountOutput params. 385 | interface GetCountOutput { 386 | // count is the query result count. This field is required. 387 | count: number 388 | 389 | // stats is the query statistics. This field is required. 390 | stats: QueryStats 391 | } 392 | 393 | // GetDiscoveredFieldsInput params. 394 | interface GetDiscoveredFieldsInput { 395 | // project_id is the project id. This field is required. 396 | project_id: string 397 | 398 | // query is the search query string. 399 | query?: string 400 | 401 | // start is the start timestamp, events before this time are not included. This field is required. 402 | start: Date 403 | 404 | // stop is the stop timestamp, events after this time are not included. This field is required. 405 | stop: Date 406 | } 407 | 408 | // GetDiscoveredFieldsOutput params. 409 | interface GetDiscoveredFieldsOutput { 410 | // fields is the fields discovered. This field is required. 411 | fields: DiscoveredField[] 412 | 413 | // stats is the query statistics. This field is required. 414 | stats: QueryStats 415 | } 416 | 417 | // GetInstanceConfigOutput params. 418 | interface GetInstanceConfigOutput { 419 | // config is the instance configuration. 420 | config?: InstanceConfig 421 | } 422 | 423 | // GetNotificationInput params. 424 | interface GetNotificationInput { 425 | // notification_id is the notification id. This field is required. 426 | notification_id: string 427 | 428 | // project_id is the project id. This field is required. 429 | project_id: string 430 | } 431 | 432 | // GetNotificationOutput params. 433 | interface GetNotificationOutput { 434 | // notification is the notification. This field is required. 435 | notification: Notification 436 | } 437 | 438 | // GetNotificationsInput params. 439 | interface GetNotificationsInput { 440 | // project_id is the project id. This field is required. 441 | project_id: string 442 | } 443 | 444 | // GetNotificationsOutput params. 445 | interface GetNotificationsOutput { 446 | // notifications is the notifications. This field is required. 447 | notifications: Notification[] 448 | } 449 | 450 | // GetNumericFieldStatsInput params. 451 | interface GetNumericFieldStatsInput { 452 | // field is the field name. This field is required. 453 | field: string 454 | 455 | // project_id is the project id. This field is required. 456 | project_id: string 457 | 458 | // query is the search query string. 459 | query?: string 460 | 461 | // start is the start timestamp, events before this time are not included. This field is required. 462 | start: Date 463 | 464 | // stop is the stop timestamp, events after this time are not included. This field is required. 465 | stop: Date 466 | } 467 | 468 | // GetNumericFieldStatsOutput params. 469 | interface GetNumericFieldStatsOutput { 470 | // avg is the avg value. This field is required. 471 | avg: number 472 | 473 | // max is The max value. This field is required. 474 | max: number 475 | 476 | // min is the min value. This field is required. 477 | min: number 478 | 479 | // stats is the query statistics. This field is required. 480 | stats: QueryStats 481 | } 482 | 483 | // GetProjectStatsInput params. 484 | interface GetProjectStatsInput { 485 | // project_id is the project id. This field is required. 486 | project_id: string 487 | } 488 | 489 | // GetProjectStatsOutput params. 490 | interface GetProjectStatsOutput { 491 | // bytes_total is the total number of bytes stored. This field is required. 492 | bytes_total: number 493 | 494 | // events_total is the total number of events stored. This field is required. 495 | events_total: number 496 | } 497 | 498 | // GetProjectsOutput params. 499 | interface GetProjectsOutput { 500 | // projects is the projects. This field is required. 501 | projects: Project[] 502 | } 503 | 504 | // GetSearchesInput params. 505 | interface GetSearchesInput { 506 | // project_id is the project id. This field is required. 507 | project_id: string 508 | } 509 | 510 | // GetSearchesOutput params. 511 | interface GetSearchesOutput { 512 | // searches is the saved searches. 513 | searches?: Search[] 514 | } 515 | 516 | // GetStringFieldStatsInput params. 517 | interface GetStringFieldStatsInput { 518 | // field is the field name. This field is required. 519 | field: string 520 | 521 | // limit is the maximum number of values to return. 522 | limit?: number 523 | 524 | // project_id is the project id. This field is required. 525 | project_id: string 526 | 527 | // query is the search query string. 528 | query?: string 529 | 530 | // start is the start timestamp, events before this time are not included. This field is required. 531 | start: Date 532 | 533 | // stop is the stop timestamp, events after this time are not included. This field is required. 534 | stop: Date 535 | } 536 | 537 | // GetStringFieldStatsOutput params. 538 | interface GetStringFieldStatsOutput { 539 | // stats is the query statistics. This field is required. 540 | stats: QueryStats 541 | 542 | // values is the string values. This field is required. 543 | values: StringFieldStat[] 544 | } 545 | 546 | // GetTimeseriesInput params. 547 | interface GetTimeseriesInput { 548 | // max_points is the maxmimum number of datapoints to return. This field is required. 549 | max_points: number 550 | 551 | // project_id is the project id. This field is required. 552 | project_id: string 553 | 554 | // query is the search query string. 555 | query?: string 556 | 557 | // start is the start timestamp, events before this time are not included. This field is required. 558 | start: Date 559 | 560 | // stop is the stop timestamp, events after this time are not included. This field is required. 561 | stop: Date 562 | } 563 | 564 | // GetTimeseriesOutput params. 565 | interface GetTimeseriesOutput { 566 | // points is the series. This field is required. 567 | points: TimeseriesPoint[] 568 | 569 | // stats is the query statistics. This field is required. 570 | stats: QueryStats 571 | } 572 | 573 | // GetTokensOutput params. 574 | interface GetTokensOutput { 575 | // tokens is the tokens. 576 | tokens?: Token[] 577 | } 578 | 579 | // QueryInput params. 580 | interface QueryInput { 581 | // project_id is the project id. This field is required. 582 | project_id: string 583 | 584 | // query is the SQL query string. This field is required. 585 | query: string 586 | } 587 | 588 | // QueryOutput params. 589 | interface QueryOutput { 590 | // results is the query results. This field is required. 591 | results: object[] 592 | 593 | // stats is the query statistics. This field is required. 594 | stats: QueryStats 595 | } 596 | 597 | // RemoveAlertInput params. 598 | interface RemoveAlertInput { 599 | // alert_id is the alert id. This field is required. 600 | alert_id: string 601 | 602 | // project_id is the project id. This field is required. 603 | project_id: string 604 | } 605 | 606 | // RemoveNotificationInput params. 607 | interface RemoveNotificationInput { 608 | // notification_id is the notification id. This field is required. 609 | notification_id: string 610 | 611 | // project_id is the project id. This field is required. 612 | project_id: string 613 | } 614 | 615 | // RemoveProjectInput params. 616 | interface RemoveProjectInput { 617 | // project_id is the project id. This field is required. 618 | project_id: string 619 | } 620 | 621 | // RemoveSearchInput params. 622 | interface RemoveSearchInput { 623 | // project_id is the project id. This field is required. 624 | project_id: string 625 | 626 | // search_id is the saved search id. This field is required. 627 | search_id: string 628 | } 629 | 630 | // RemoveTokenInput params. 631 | interface RemoveTokenInput { 632 | // token_id is the token id. This field is required. 633 | token_id: string 634 | } 635 | 636 | // SearchInput params. 637 | interface SearchInput { 638 | // limit is the maxmimum number of events to return. 639 | limit?: number 640 | 641 | // order is the query timestamp sort order. Must be one of: "ascending", "descending". 642 | order?: string 643 | 644 | // project_id is the project id. This field is required. 645 | project_id: string 646 | 647 | // query is the search query string. 648 | query?: string 649 | 650 | // start is the start timestamp, events before this time are not included. This field is required. 651 | start: Date 652 | 653 | // stop is the stop timestamp, events after this time are not included. This field is required. 654 | stop: Date 655 | } 656 | 657 | // SearchOutput params. 658 | interface SearchOutput { 659 | // events is the query search results. This field is required. 660 | events: Event[] 661 | 662 | // stats is the query statistics. This field is required. 663 | stats: QueryStats 664 | } 665 | 666 | // TestAlertInput params. 667 | interface TestAlertInput { 668 | // alert is the alert. This field is required. 669 | alert: Alert 670 | } 671 | 672 | // UpdateAlertInput params. 673 | interface UpdateAlertInput { 674 | // alert is the alert. This field is required. 675 | alert: Alert 676 | } 677 | 678 | // UpdateNotificationInput params. 679 | interface UpdateNotificationInput { 680 | // notification is the notification. This field is required. 681 | notification: Notification 682 | } 683 | 684 | // UpdateProjectInput params. 685 | interface UpdateProjectInput { 686 | // project is the project. This field is required. 687 | project: Project 688 | } 689 | 690 | // UpdateSearchInput params. 691 | interface UpdateSearchInput { 692 | // search is the saved search. This field is required. 693 | search: Search 694 | } 695 | 696 | 697 | // fetch for Node 698 | const fetch = (typeof window == 'undefined' || window.fetch == null) 699 | // @ts-ignore 700 | ? require('node-fetch') 701 | : window.fetch 702 | 703 | /** 704 | * ClientError is an API client error providing the HTTP status code and error type. 705 | */ 706 | 707 | class ClientError extends Error { 708 | status: number; 709 | type?: string; 710 | 711 | constructor(status: number, message?: string, type?: string) { 712 | super(message) 713 | this.status = status 714 | this.type = type 715 | } 716 | } 717 | 718 | /** 719 | * Call method with params via a POST request. 720 | */ 721 | 722 | async function call(url: string, method: string, authToken?: string, params?: any): Promise { 723 | const headers: Record = { 724 | 'Content-Type': 'application/json' 725 | } 726 | 727 | if (authToken != null) { 728 | headers['Authorization'] = `Bearer ${authToken}` 729 | } 730 | 731 | const res = await fetch(url + '/' + method, { 732 | method: 'POST', 733 | body: JSON.stringify(params), 734 | headers 735 | }) 736 | 737 | // we have an error, try to parse a well-formed json 738 | // error response, otherwise default to status code 739 | if (res.status >= 300) { 740 | let err 741 | try { 742 | const { type, message } = await res.json() 743 | err = new ClientError(res.status, message, type) 744 | } catch { 745 | err = new ClientError(res.status, res.statusText) 746 | } 747 | throw err 748 | } 749 | 750 | return res.text() 751 | } 752 | 753 | 754 | const reISO8601 = /(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/ 755 | 756 | /** 757 | * Client is the API client. 758 | */ 759 | 760 | export class Client { 761 | 762 | private url: string 763 | private authToken?: string 764 | 765 | /** 766 | * Initialize. 767 | */ 768 | 769 | constructor(params: { url: string, authToken?: string }) { 770 | this.url = params.url 771 | this.authToken = params.authToken 772 | } 773 | 774 | /** 775 | * Decoder is used as the reviver parameter when decoding responses. 776 | */ 777 | 778 | private decoder(key: any, value: any) { 779 | return typeof value == 'string' && reISO8601.test(value) 780 | ? new Date(value) 781 | : value 782 | } 783 | 784 | /** 785 | * addAlert: creates a new alert. 786 | */ 787 | 788 | async addAlert(params: AddAlertInput): Promise { 789 | let res = await call(this.url, 'add_alert', this.authToken, params) 790 | let out: AddAlertOutput = JSON.parse(res, this.decoder) 791 | return out 792 | } 793 | 794 | /** 795 | * addEvents: ingests a batch of events. 796 | */ 797 | 798 | async addEvents(params: AddEventsInput) { 799 | await call(this.url, 'add_events', this.authToken, params) 800 | } 801 | 802 | /** 803 | * addNotification: creates a new notification. 804 | */ 805 | 806 | async addNotification(params: AddNotificationInput): Promise { 807 | let res = await call(this.url, 'add_notification', this.authToken, params) 808 | let out: AddNotificationOutput = JSON.parse(res, this.decoder) 809 | return out 810 | } 811 | 812 | /** 813 | * addProject: creates a new project. 814 | */ 815 | 816 | async addProject(params: AddProjectInput): Promise { 817 | let res = await call(this.url, 'add_project', this.authToken, params) 818 | let out: AddProjectOutput = JSON.parse(res, this.decoder) 819 | return out 820 | } 821 | 822 | /** 823 | * addSearch: creates a new saved search. 824 | */ 825 | 826 | async addSearch(params: AddSearchInput): Promise { 827 | let res = await call(this.url, 'add_search', this.authToken, params) 828 | let out: AddSearchOutput = JSON.parse(res, this.decoder) 829 | return out 830 | } 831 | 832 | /** 833 | * addToken: creates a new token. 834 | */ 835 | 836 | async addToken(params: AddTokenInput): Promise { 837 | let res = await call(this.url, 'add_token', this.authToken, params) 838 | let out: AddTokenOutput = JSON.parse(res, this.decoder) 839 | return out 840 | } 841 | 842 | /** 843 | * getAlert: returns an alert. 844 | */ 845 | 846 | async getAlert(params: GetAlertInput): Promise { 847 | let res = await call(this.url, 'get_alert', this.authToken, params) 848 | let out: GetAlertOutput = JSON.parse(res, this.decoder) 849 | return out 850 | } 851 | 852 | /** 853 | * getAlerts: returns all alerts in a project. 854 | */ 855 | 856 | async getAlerts(params: GetAlertsInput): Promise { 857 | let res = await call(this.url, 'get_alerts', this.authToken, params) 858 | let out: GetAlertsOutput = JSON.parse(res, this.decoder) 859 | return out 860 | } 861 | 862 | /** 863 | * getBooleanFieldStats: returns field statistics for a boolean field. 864 | */ 865 | 866 | async getBooleanFieldStats(params: GetBooleanFieldStatsInput): Promise { 867 | let res = await call(this.url, 'get_boolean_field_stats', this.authToken, params) 868 | let out: GetBooleanFieldStatsOutput = JSON.parse(res, this.decoder) 869 | return out 870 | } 871 | 872 | /** 873 | * getCount: performs a search query against the log events, returning the number of matches. 874 | */ 875 | 876 | async getCount(params: GetCountInput): Promise { 877 | let res = await call(this.url, 'get_count', this.authToken, params) 878 | let out: GetCountOutput = JSON.parse(res, this.decoder) 879 | return out 880 | } 881 | 882 | /** 883 | * getDiscoveredFields: returns fields discovered in the provided time range. 884 | */ 885 | 886 | async getDiscoveredFields(params: GetDiscoveredFieldsInput): Promise { 887 | let res = await call(this.url, 'get_discovered_fields', this.authToken, params) 888 | let out: GetDiscoveredFieldsOutput = JSON.parse(res, this.decoder) 889 | return out 890 | } 891 | 892 | /** 893 | * getInstanceConfig: returns instance configuration. 894 | */ 895 | 896 | async getInstanceConfig(): Promise { 897 | let res = await call(this.url, 'get_instance_config', this.authToken) 898 | let out: GetInstanceConfigOutput = JSON.parse(res, this.decoder) 899 | return out 900 | } 901 | 902 | /** 903 | * getNotification: returns a notification. 904 | */ 905 | 906 | async getNotification(params: GetNotificationInput): Promise { 907 | let res = await call(this.url, 'get_notification', this.authToken, params) 908 | let out: GetNotificationOutput = JSON.parse(res, this.decoder) 909 | return out 910 | } 911 | 912 | /** 913 | * getNotifications: returns all notifications. 914 | */ 915 | 916 | async getNotifications(params: GetNotificationsInput): Promise { 917 | let res = await call(this.url, 'get_notifications', this.authToken, params) 918 | let out: GetNotificationsOutput = JSON.parse(res, this.decoder) 919 | return out 920 | } 921 | 922 | /** 923 | * getNumericFieldStats: returns field statistics for a numeric field. 924 | */ 925 | 926 | async getNumericFieldStats(params: GetNumericFieldStatsInput): Promise { 927 | let res = await call(this.url, 'get_numeric_field_stats', this.authToken, params) 928 | let out: GetNumericFieldStatsOutput = JSON.parse(res, this.decoder) 929 | return out 930 | } 931 | 932 | /** 933 | * getProjectStats: returns project statistics. 934 | */ 935 | 936 | async getProjectStats(params: GetProjectStatsInput): Promise { 937 | let res = await call(this.url, 'get_project_stats', this.authToken, params) 938 | let out: GetProjectStatsOutput = JSON.parse(res, this.decoder) 939 | return out 940 | } 941 | 942 | /** 943 | * getProjects: returns all projects. 944 | */ 945 | 946 | async getProjects(): Promise { 947 | let res = await call(this.url, 'get_projects', this.authToken) 948 | let out: GetProjectsOutput = JSON.parse(res, this.decoder) 949 | return out 950 | } 951 | 952 | /** 953 | * getSearches: returns all saved searches in a project. 954 | */ 955 | 956 | async getSearches(params: GetSearchesInput): Promise { 957 | let res = await call(this.url, 'get_searches', this.authToken, params) 958 | let out: GetSearchesOutput = JSON.parse(res, this.decoder) 959 | return out 960 | } 961 | 962 | /** 963 | * getStringFieldStats: returns field statistics for a string field. 964 | */ 965 | 966 | async getStringFieldStats(params: GetStringFieldStatsInput): Promise { 967 | let res = await call(this.url, 'get_string_field_stats', this.authToken, params) 968 | let out: GetStringFieldStatsOutput = JSON.parse(res, this.decoder) 969 | return out 970 | } 971 | 972 | /** 973 | * getTimeseries: returns a timeseries of event counts in the provided time range. 974 | */ 975 | 976 | async getTimeseries(params: GetTimeseriesInput): Promise { 977 | let res = await call(this.url, 'get_timeseries', this.authToken, params) 978 | let out: GetTimeseriesOutput = JSON.parse(res, this.decoder) 979 | return out 980 | } 981 | 982 | /** 983 | * getTokens: returns all tokens. 984 | */ 985 | 986 | async getTokens(): Promise { 987 | let res = await call(this.url, 'get_tokens', this.authToken) 988 | let out: GetTokensOutput = JSON.parse(res, this.decoder) 989 | return out 990 | } 991 | 992 | /** 993 | * query: performs a SQL query against the log events. 994 | */ 995 | 996 | async query(params: QueryInput): Promise { 997 | let res = await call(this.url, 'query', this.authToken, params) 998 | let out: QueryOutput = JSON.parse(res, this.decoder) 999 | return out 1000 | } 1001 | 1002 | /** 1003 | * removeAlert: removes an alert. 1004 | */ 1005 | 1006 | async removeAlert(params: RemoveAlertInput) { 1007 | await call(this.url, 'remove_alert', this.authToken, params) 1008 | } 1009 | 1010 | /** 1011 | * removeNotification: removes a notification. 1012 | */ 1013 | 1014 | async removeNotification(params: RemoveNotificationInput) { 1015 | await call(this.url, 'remove_notification', this.authToken, params) 1016 | } 1017 | 1018 | /** 1019 | * removeProject: removes a project. 1020 | */ 1021 | 1022 | async removeProject(params: RemoveProjectInput) { 1023 | await call(this.url, 'remove_project', this.authToken, params) 1024 | } 1025 | 1026 | /** 1027 | * removeSearch: removes a saved search. 1028 | */ 1029 | 1030 | async removeSearch(params: RemoveSearchInput) { 1031 | await call(this.url, 'remove_search', this.authToken, params) 1032 | } 1033 | 1034 | /** 1035 | * removeToken: removes a token. 1036 | */ 1037 | 1038 | async removeToken(params: RemoveTokenInput) { 1039 | await call(this.url, 'remove_token', this.authToken, params) 1040 | } 1041 | 1042 | /** 1043 | * search: performs a search query against the log events. 1044 | */ 1045 | 1046 | async search(params: SearchInput): Promise { 1047 | let res = await call(this.url, 'search', this.authToken, params) 1048 | let out: SearchOutput = JSON.parse(res, this.decoder) 1049 | return out 1050 | } 1051 | 1052 | /** 1053 | * testAlert: test the alert configuration. 1054 | */ 1055 | 1056 | async testAlert(params: TestAlertInput) { 1057 | await call(this.url, 'test_alert', this.authToken, params) 1058 | } 1059 | 1060 | /** 1061 | * updateAlert: updates an alert. 1062 | */ 1063 | 1064 | async updateAlert(params: UpdateAlertInput) { 1065 | await call(this.url, 'update_alert', this.authToken, params) 1066 | } 1067 | 1068 | /** 1069 | * updateNotification: updates a notification. 1070 | */ 1071 | 1072 | async updateNotification(params: UpdateNotificationInput) { 1073 | await call(this.url, 'update_notification', this.authToken, params) 1074 | } 1075 | 1076 | /** 1077 | * updateProject: updates a project. 1078 | */ 1079 | 1080 | async updateProject(params: UpdateProjectInput) { 1081 | await call(this.url, 'update_project', this.authToken, params) 1082 | } 1083 | 1084 | /** 1085 | * updateSearch: updates a saved search. 1086 | */ 1087 | 1088 | async updateSearch(params: UpdateSearchInput) { 1089 | await call(this.url, 'update_search', this.authToken, params) 1090 | } 1091 | 1092 | } 1093 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "apex-logs", 3 | "version": "0.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/node": { 8 | "version": "12.0.10", 9 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.10.tgz", 10 | "integrity": "sha512-LcsGbPomWsad6wmMNv7nBLw7YYYyfdYcz6xryKYQhx89c3XXan+8Q6AJ43G5XDIaklaVkK3mE4fCb0SBvMiPSQ==" 11 | }, 12 | "@types/node-fetch": { 13 | "version": "2.3.7", 14 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.3.7.tgz", 15 | "integrity": "sha512-+bKtuxhj/TYSSP1r4CZhfmyA0vm/aDRQNo7vbAgf6/cZajn0SAniGGST07yvI4Q+q169WTa2/x9gEHfJrkcALw==", 16 | "requires": { 17 | "@types/node": "*" 18 | } 19 | }, 20 | "node-fetch": { 21 | "version": "2.6.0", 22 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", 23 | "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "apex-logs", 3 | "version": "1.1.0", 4 | "keywords": [ 5 | "apex", 6 | "log", 7 | "logs", 8 | "logging", 9 | "client", 10 | "api" 11 | ], 12 | "dependencies": { 13 | "@types/node-fetch": "^2.3.7", 14 | "node-fetch": "^2.6.0" 15 | }, 16 | "files": [ 17 | "dist.browser", 18 | "dist" 19 | ], 20 | "main": "dist/client.js", 21 | "browser": "dist.browser/client.js" 22 | } 23 | -------------------------------------------------------------------------------- /tsconfig.browser.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist.browser", 4 | "target": "es5", 5 | "module": "es2015", 6 | "lib": ["es2016", "dom", "es5"] 7 | }, 8 | "include": ["client.ts"] 9 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist", 4 | "target": "es6", 5 | "module": "commonjs", 6 | "moduleResolution": "node" 7 | }, 8 | "include": ["client.ts"], 9 | "exclude": ["node_modules"] 10 | } --------------------------------------------------------------------------------