@openfga/sdk
Advanced tools
Comparing version 0.6.3 to 0.7.0
# Changelog | ||
## v0.7.0 | ||
### [0.7.0](https://github.com/openfga/js-sdk/compare/v0.6.3...v0.7.0) (2024-08-30) | ||
- feat!: enhancements to OpenTelemetry support (#149) | ||
BREAKING CHANGE: | ||
This version changes the way in which telemetry is configured and reported. See #149 for additional information. | ||
## v0.6.3 | ||
### [0.6.3](https://github.com/openfga/js-sdk/compare/v0.6.2...v0.6.3) (2024-08-28) | ||
@@ -4,0 +16,0 @@ |
@@ -54,10 +54,14 @@ /** | ||
export type PromiseResult<T extends ObjectOrVoid> = Promise<CallResult<T>>; | ||
interface WrappedAxiosResponse<R> { | ||
response?: AxiosResponse<R>; | ||
retries: number; | ||
} | ||
export declare function attemptHttpRequest<B, R>(request: AxiosRequestConfig<B>, config: { | ||
maxRetry: number; | ||
minWaitInMs: number; | ||
}, axiosInstance: AxiosInstance): Promise<AxiosResponse<R> | undefined>; | ||
}, axiosInstance: AxiosInstance): Promise<WrappedAxiosResponse<R> | undefined>; | ||
/** | ||
* creates an axios request function | ||
*/ | ||
export declare const createRequestFunction: (axiosArgs: RequestArgs, axiosInstance: AxiosInstance, configuration: Configuration, credentials: Credentials, methodAttributes?: Record<string, unknown>) => (axios?: AxiosInstance) => PromiseResult<any>; | ||
export declare const createRequestFunction: (axiosArgs: RequestArgs, axiosInstance: AxiosInstance, configuration: Configuration, credentials: Credentials, methodAttributes?: Record<string, string | number>) => (axios?: AxiosInstance) => PromiseResult<any>; | ||
export {}; |
@@ -16,15 +16,6 @@ "use strict"; | ||
exports.attemptHttpRequest = attemptHttpRequest; | ||
const api_1 = require("@opentelemetry/api"); | ||
const errors_1 = require("./errors"); | ||
const utils_1 = require("./utils"); | ||
const telemetry_1 = require("./telemetry"); | ||
const meter = api_1.metrics.getMeter("@openfga/sdk", "0.6.3"); | ||
const durationHist = meter.createHistogram("fga-client.request.duration", { | ||
description: "The duration of requests", | ||
unit: "milliseconds", | ||
}); | ||
const queryDurationHist = meter.createHistogram("fga-client.query.duration", { | ||
description: "The duration of queries on the FGA server", | ||
unit: "milliseconds", | ||
}); | ||
const attributes_1 = require("./telemetry/attributes"); | ||
const histograms_1 = require("./telemetry/histograms"); | ||
/** | ||
@@ -123,3 +114,7 @@ * | ||
try { | ||
return await axiosInstance(request); | ||
const response = await axiosInstance(request); | ||
return { | ||
response: response, | ||
retries: iterationCount - 1, | ||
}; | ||
} | ||
@@ -167,22 +162,37 @@ catch (err) { | ||
const minWaitInMs = retryParams ? retryParams.minWaitInMs : 0; | ||
const start = Date.now(); | ||
const start = performance.now(); | ||
return async (axios = axiosInstance) => { | ||
await (0, exports.setBearerAuthToObject)(axiosArgs.options.headers, credentials); | ||
const axiosRequestArgs = { ...axiosArgs.options, url: configuration.getBasePath() + axiosArgs.url }; | ||
const response = await attemptHttpRequest(axiosRequestArgs, { | ||
const url = configuration.getBasePath() + axiosArgs.url; | ||
const axiosRequestArgs = { ...axiosArgs.options, url: url }; | ||
const wrappedResponse = await attemptHttpRequest(axiosRequestArgs, { | ||
maxRetry, | ||
minWaitInMs, | ||
}, axios); | ||
const executionTime = Date.now() - start; | ||
const response = wrappedResponse?.response; | ||
const data = typeof response?.data === "undefined" ? {} : response?.data; | ||
const result = { ...data }; | ||
(0, utils_1.setNotEnumerableProperty)(result, "$response", response); | ||
const attributes = (0, telemetry_1.buildAttributes)(response, configuration.credentials, methodAttributes); | ||
if (response?.headers) { | ||
const duration = response.headers["fga-query-duration-ms"]; | ||
if (duration !== undefined) { | ||
queryDurationHist.record(parseInt(duration, 10), attributes); | ||
} | ||
let attributes = {}; | ||
attributes = attributes_1.TelemetryAttributes.fromRequest({ | ||
userAgent: configuration.baseOptions?.headers["User-Agent"], | ||
httpMethod: axiosArgs.options?.method, | ||
url, | ||
resendCount: wrappedResponse?.retries, | ||
start: start, | ||
credentials: credentials, | ||
attributes: methodAttributes, | ||
}); | ||
attributes = attributes_1.TelemetryAttributes.fromResponse({ | ||
response, | ||
attributes, | ||
}); | ||
// only if hisogramQueryDuration set AND if response header contains fga-query-duration-ms | ||
const serverRequestDuration = attributes[attributes_1.TelemetryAttribute.HttpServerRequestDuration]; | ||
if (configuration.telemetry?.metrics?.histogramQueryDuration && typeof serverRequestDuration !== "undefined") { | ||
configuration.telemetry.recorder.histogram(histograms_1.TelemetryHistograms.queryDuration, parseInt(attributes[attributes_1.TelemetryAttribute.HttpServerRequestDuration], 10), attributes_1.TelemetryAttributes.prepare(attributes, configuration.telemetry.metrics.histogramQueryDuration.attributes)); | ||
} | ||
durationHist.record(executionTime, attributes); | ||
if (configuration.telemetry?.metrics?.histogramRequestDuration) { | ||
configuration.telemetry.recorder.histogram(histograms_1.TelemetryHistograms.requestDuration, attributes[attributes_1.TelemetryAttribute.HttpClientRequestDuration], attributes_1.TelemetryAttributes.prepare(attributes, configuration.telemetry.metrics.histogramRequestDuration.attributes)); | ||
} | ||
return result; | ||
@@ -189,0 +199,0 @@ }; |
@@ -13,2 +13,3 @@ /** | ||
import { ApiTokenConfig, AuthCredentialsConfig, ClientCredentialsConfig, CredentialsMethod } from "./credentials/types"; | ||
import { TelemetryConfig, TelemetryConfiguration } from "./telemetry/configuration"; | ||
export interface RetryParams { | ||
@@ -31,2 +32,3 @@ maxRetry?: number; | ||
retryParams?: RetryParams; | ||
telemetry?: TelemetryConfig; | ||
} | ||
@@ -102,2 +104,9 @@ export declare function GetDefaultRetryParams(maxRetry?: number, minWaitInMs?: number): { | ||
retryParams?: RetryParams; | ||
/** | ||
* telemetry configuration | ||
* | ||
* @type {TelemetryConfiguration} | ||
* @memberof Configuration | ||
*/ | ||
telemetry: TelemetryConfiguration; | ||
constructor(params?: UserConfigurationParams); | ||
@@ -104,0 +113,0 @@ /** |
@@ -19,2 +19,3 @@ "use strict"; | ||
const validation_1 = require("./validation"); | ||
const configuration_1 = require("./telemetry/configuration"); | ||
// default maximum number of retry | ||
@@ -24,3 +25,3 @@ const DEFAULT_MAX_RETRY = 15; | ||
const DEFAULT_MIN_WAIT_MS = 100; | ||
const DEFAULT_USER_AGENT = "openfga-sdk js/0.6.3"; | ||
const DEFAULT_USER_AGENT = "openfga-sdk js/0.7.0"; | ||
function GetDefaultRetryParams(maxRetry = DEFAULT_MAX_RETRY, minWaitInMs = DEFAULT_MIN_WAIT_MS) { | ||
@@ -94,2 +95,3 @@ return { | ||
this.retryParams = params.retryParams; | ||
this.telemetry = new configuration_1.TelemetryConfiguration(params?.telemetry?.metrics); | ||
} | ||
@@ -114,2 +116,3 @@ /** | ||
} | ||
this.telemetry.ensureValid(); | ||
return true; | ||
@@ -126,2 +129,2 @@ } | ||
*/ | ||
Configuration.sdkVersion = "0.6.3"; | ||
Configuration.sdkVersion = "0.7.0"; |
@@ -14,12 +14,16 @@ /** | ||
import { AuthCredentialsConfig } from "./types"; | ||
import { TelemetryConfiguration } from "../telemetry/configuration"; | ||
export declare class Credentials { | ||
private authConfig; | ||
private axios; | ||
private telemetryConfig; | ||
private baseOptions?; | ||
private accessToken?; | ||
private accessTokenExpiryDate?; | ||
private tokenCounter?; | ||
static init(configuration: { | ||
credentials: AuthCredentialsConfig; | ||
telemetry: TelemetryConfiguration; | ||
baseOptions?: any; | ||
}): Credentials; | ||
constructor(authConfig: AuthCredentialsConfig, axios?: AxiosInstance); | ||
constructor(authConfig: AuthCredentialsConfig, axios: AxiosInstance | undefined, telemetryConfig: TelemetryConfiguration, baseOptions?: any); | ||
/** | ||
@@ -26,0 +30,0 @@ * Sets the default config values |
@@ -19,12 +19,14 @@ "use strict"; | ||
const common_1 = require("../common"); | ||
const telemetry_1 = require("../telemetry"); | ||
const types_1 = require("./types"); | ||
const api_1 = require("@opentelemetry/api"); | ||
const attributes_1 = require("../telemetry/attributes"); | ||
const counters_1 = require("../telemetry/counters"); | ||
class Credentials { | ||
static init(configuration) { | ||
return new Credentials(configuration.credentials); | ||
return new Credentials(configuration.credentials, axios_1.default, configuration.telemetry, configuration.baseOptions); | ||
} | ||
constructor(authConfig, axios = axios_1.default) { | ||
constructor(authConfig, axios = axios_1.default, telemetryConfig, baseOptions) { | ||
this.authConfig = authConfig; | ||
this.axios = axios; | ||
this.telemetryConfig = telemetryConfig; | ||
this.baseOptions = baseOptions; | ||
this.initConfig(); | ||
@@ -49,7 +51,2 @@ this.isValid(); | ||
break; | ||
case types_1.CredentialsMethod.ClientCredentials: { | ||
const meter = api_1.metrics.getMeter("@openfga/sdk", "0.6.3"); | ||
this.tokenCounter = meter.createCounter("fga-client.credentials.request"); | ||
break; | ||
} | ||
case types_1.CredentialsMethod.None: | ||
@@ -125,6 +122,7 @@ default: | ||
const clientCredentials = this.authConfig?.config; | ||
const url = `https://${clientCredentials.apiTokenIssuer}/oauth/token`; | ||
try { | ||
const response = await (0, common_1.attemptHttpRequest)({ | ||
url: `https://${clientCredentials.apiTokenIssuer}/oauth/token`, | ||
method: "post", | ||
const wrappedResponse = await (0, common_1.attemptHttpRequest)({ | ||
url, | ||
method: "POST", | ||
data: { | ||
@@ -143,2 +141,3 @@ client_id: clientCredentials.clientId, | ||
}, axios_1.default); | ||
const response = wrappedResponse?.response; | ||
if (response) { | ||
@@ -148,3 +147,21 @@ this.accessToken = response.data.access_token; | ||
} | ||
this.tokenCounter?.add(1, (0, telemetry_1.buildAttributes)(response, this.authConfig)); | ||
if (this.telemetryConfig?.metrics?.counterCredentialsRequest?.attributes) { | ||
let attributes = {}; | ||
attributes = attributes_1.TelemetryAttributes.fromRequest({ | ||
userAgent: this.baseOptions?.headers["User-Agent"], | ||
fgaMethod: "TokenExchange", | ||
url, | ||
resendCount: wrappedResponse?.retries, | ||
httpMethod: "POST", | ||
credentials: clientCredentials, | ||
start: performance.now(), | ||
attributes, | ||
}); | ||
attributes = attributes_1.TelemetryAttributes.fromResponse({ | ||
response, | ||
attributes, | ||
}); | ||
attributes = attributes_1.TelemetryAttributes.prepare(attributes, this.telemetryConfig.metrics?.counterCredentialsRequest?.attributes); | ||
this.telemetryConfig.recorder.counter(counters_1.TelemetryCounters.credentialsRequest, 1, attributes); | ||
} | ||
return this.accessToken; | ||
@@ -151,0 +168,0 @@ } |
@@ -17,2 +17,7 @@ /** | ||
export { Credentials, CredentialsMethod } from "./credentials"; | ||
export * from "./telemetry/attributes"; | ||
export * from "./telemetry/configuration"; | ||
export * from "./telemetry/counters"; | ||
export * from "./telemetry/histograms"; | ||
export * from "./telemetry/metrics"; | ||
export * from "./errors"; |
@@ -40,2 +40,7 @@ "use strict"; | ||
Object.defineProperty(exports, "CredentialsMethod", { enumerable: true, get: function () { return credentials_1.CredentialsMethod; } }); | ||
__exportStar(require("./telemetry/attributes"), exports); | ||
__exportStar(require("./telemetry/configuration"), exports); | ||
__exportStar(require("./telemetry/counters"), exports); | ||
__exportStar(require("./telemetry/histograms"), exports); | ||
__exportStar(require("./telemetry/metrics"), exports); | ||
__exportStar(require("./errors"), exports); |
{ | ||
"name": "@openfga/sdk", | ||
"version": "0.6.3", | ||
"version": "0.7.0", | ||
"description": "JavaScript and Node.js SDK for OpenFGA", | ||
@@ -26,3 +26,2 @@ "author": "OpenFGA", | ||
"@opentelemetry/api": "^1.9.0", | ||
"@opentelemetry/semantic-conventions": "^1.26.0", | ||
"axios": "^1.7.5", | ||
@@ -29,0 +28,0 @@ "tiny-async-pool": "^2.1.0" |
Sorry, the diff of this file is too big to display
1421768
3
51
7191
- Removed@opentelemetry/semantic-conventions@1.30.0(transitive)