mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-17 01:17:29 +02:00
feat: start capturing onboarded status also from register endpoint
This commit is contained in:
parent
9c22658b5d
commit
c42093b7b3
@ -18,7 +18,6 @@ public class Program
|
|||||||
{
|
{
|
||||||
AppName = "unleash-onboarding-dotnet",
|
AppName = "unleash-onboarding-dotnet",
|
||||||
UnleashApi = new Uri("<YOUR_API_URL>"),
|
UnleashApi = new Uri("<YOUR_API_URL>"),
|
||||||
SendMetricsInterval = TimeSpan.FromSeconds(1), // in production remove this or increase to >=15s
|
|
||||||
CustomHttpHeaders = new Dictionary<string, string>()
|
CustomHttpHeaders = new Dictionary<string, string>()
|
||||||
{
|
{
|
||||||
{"Authorization","<YOUR_API_TOKEN>"} // in production use environment variable
|
{"Authorization","<YOUR_API_TOKEN>"} // in production use environment variable
|
||||||
|
@ -19,7 +19,6 @@ func init() {
|
|||||||
unleash.WithAppName("unleash-onboarding-golang"),
|
unleash.WithAppName("unleash-onboarding-golang"),
|
||||||
unleash.WithUrl("<YOUR_API_URL>"),
|
unleash.WithUrl("<YOUR_API_URL>"),
|
||||||
unleash.WithCustomHeaders(http.Header{"Authorization": {"<YOUR_API_TOKEN>"}}), // in production use environment variable
|
unleash.WithCustomHeaders(http.Header{"Authorization": {"<YOUR_API_TOKEN>"}}), // in production use environment variable
|
||||||
unleash.WithMetricsInterval(1*time.Second), // in production remove this or increase to >=15s
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ UnleashConfig config = UnleashConfig.builder()
|
|||||||
.instanceId("unleash-onboarding-instance")
|
.instanceId("unleash-onboarding-instance")
|
||||||
.unleashAPI("<YOUR_API_URL>")
|
.unleashAPI("<YOUR_API_URL>")
|
||||||
.apiKey("<YOUR_API_TOKEN>") // in production use environment variable
|
.apiKey("<YOUR_API_TOKEN>") // in production use environment variable
|
||||||
.sendMetricsInterval(1) // in production remove this or increase to >=15
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Unleash unleash = new DefaultUnleash(config);
|
Unleash unleash = new DefaultUnleash(config);
|
||||||
|
@ -11,7 +11,6 @@ const unleash = new UnleashClient({
|
|||||||
url: '<YOUR_API_URL>',
|
url: '<YOUR_API_URL>',
|
||||||
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
||||||
appName: 'unleash-onboarding-javascript',
|
appName: 'unleash-onboarding-javascript',
|
||||||
metricsInterval: 1000, // in production remove this or increase to >=15000
|
|
||||||
});
|
});
|
||||||
|
|
||||||
unleash.start();
|
unleash.start();
|
||||||
|
@ -13,7 +13,6 @@ const unleash = initialize({
|
|||||||
customHeaders: {
|
customHeaders: {
|
||||||
Authorization: '<YOUR_API_TOKEN>' // in production use environment variable
|
Authorization: '<YOUR_API_TOKEN>' // in production use environment variable
|
||||||
},
|
},
|
||||||
metricsInterval: 1000, // in production remove this or increase to >=15000
|
|
||||||
});
|
});
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
|
@ -16,7 +16,6 @@ $unleash = UnleashBuilder::create()
|
|||||||
->withAppUrl('<YOUR_API_URL>')
|
->withAppUrl('<YOUR_API_URL>')
|
||||||
->withHeader('Authorization', '<YOUR_API_TOKEN>') // in production use environment variable
|
->withHeader('Authorization', '<YOUR_API_TOKEN>') // in production use environment variable
|
||||||
->withInstanceId('unleash-onboarding-instance')
|
->withInstanceId('unleash-onboarding-instance')
|
||||||
->withMetricsInterval(1000) // in production remove this or increase to >=15000
|
|
||||||
->build();
|
->build();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -11,7 +11,6 @@ import asyncio
|
|||||||
client = UnleashClient(
|
client = UnleashClient(
|
||||||
url="<YOUR_API_URL>",
|
url="<YOUR_API_URL>",
|
||||||
app_name="unleash-onboarding-python",
|
app_name="unleash-onboarding-python",
|
||||||
metrics_interval=1, # in production remove this or increase to >=15
|
|
||||||
custom_headers={'Authorization': '<YOUR_API_TOKEN>'}) # in production use environment variable
|
custom_headers={'Authorization': '<YOUR_API_TOKEN>'}) # in production use environment variable
|
||||||
|
|
||||||
client.initialize_client()
|
client.initialize_client()
|
||||||
|
@ -11,7 +11,6 @@ import { FlagProvider } from '@unleash/proxy-client-react';
|
|||||||
const config = {
|
const config = {
|
||||||
url: '<YOUR_API_URL>',
|
url: '<YOUR_API_URL>',
|
||||||
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
||||||
metricsInterval: 1, // In production use interval of >15s
|
|
||||||
appName: 'unleash-onboarding-react',
|
appName: 'unleash-onboarding-react',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ require 'unleash'
|
|||||||
custom_http_headers: { 'Authorization': "<YOUR_API_TOKEN>" }, # in production use environment variable
|
custom_http_headers: { 'Authorization': "<YOUR_API_TOKEN>" }, # in production use environment variable
|
||||||
app_name: 'unleash-onboarding-ruby',
|
app_name: 'unleash-onboarding-ruby',
|
||||||
instance_id: 'unleash-onboarding-ruby',
|
instance_id: 'unleash-onboarding-ruby',
|
||||||
metrics_interval: 3, # In production use interval of >15s
|
|
||||||
)
|
)
|
||||||
|
|
||||||
while true
|
while true
|
||||||
|
@ -26,7 +26,6 @@ enum Flags {
|
|||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let client: Client<Flags, reqwest::Client> = ClientBuilder::default()
|
let client: Client<Flags, reqwest::Client> = ClientBuilder::default()
|
||||||
.interval(1000) // in production remove this or increase to >=15000
|
|
||||||
.into_client(
|
.into_client(
|
||||||
"<YOUR_API_URL>",
|
"<YOUR_API_URL>",
|
||||||
"unleash-onboarding-rust",
|
"unleash-onboarding-rust",
|
||||||
@ -55,7 +54,6 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
|||||||
let api_token = env::var("UNLEASH_API_TOKEN").expect("UNLEASH_API_TOKEN environment variable not set");
|
let api_token = env::var("UNLEASH_API_TOKEN").expect("UNLEASH_API_TOKEN environment variable not set");
|
||||||
|
|
||||||
let client: Client<Flags, reqwest::Client> = ClientBuilder::default()
|
let client: Client<Flags, reqwest::Client> = ClientBuilder::default()
|
||||||
.interval(1000) // Polling & metrics interval - default 15000 (ms)
|
|
||||||
.into_client(
|
.into_client(
|
||||||
"<YOUR_API_URL>",
|
"<YOUR_API_URL>",
|
||||||
"unleash-onboarding-rust",
|
"unleash-onboarding-rust",
|
||||||
|
@ -12,7 +12,6 @@ npm install @unleash/proxy-client-svelte
|
|||||||
url: '<YOUR_API_URL>',
|
url: '<YOUR_API_URL>',
|
||||||
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
||||||
appName: 'unleash-onboarding-svelte',
|
appName: 'unleash-onboarding-svelte',
|
||||||
metricsInterval: 1, // in production remove this or increase to >=15
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ npm install @unleash/proxy-client-vue
|
|||||||
url: '<YOUR_API_URL>',
|
url: '<YOUR_API_URL>',
|
||||||
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
||||||
appName: 'unleash-onboarding-vue',
|
appName: 'unleash-onboarding-vue',
|
||||||
metricsInterval: 1, // in production remove this or increase to >=15
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -7,21 +7,43 @@ import {
|
|||||||
SYSTEM_USER,
|
SYSTEM_USER,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
import type { IOnboardingReadModel } from './onboarding-read-model-type';
|
import type { IOnboardingReadModel } from './onboarding-read-model-type';
|
||||||
|
import type ClientInstanceService from '../metrics/instance/instance-service';
|
||||||
|
import {
|
||||||
|
type IUnleashTest,
|
||||||
|
setupAppWithCustomConfig,
|
||||||
|
} from '../../../test/e2e/helpers/test-helper';
|
||||||
|
import { ApiTokenType } from '../../types/models/api-token';
|
||||||
|
|
||||||
let db: ITestDb;
|
let db: ITestDb;
|
||||||
let onboardingReadModel: IOnboardingReadModel;
|
let onboardingReadModel: IOnboardingReadModel;
|
||||||
let onBoardingStore: IOnboardingStore;
|
let onBoardingStore: IOnboardingStore;
|
||||||
let featureToggleStore: IFeatureToggleStore;
|
let featureToggleStore: IFeatureToggleStore;
|
||||||
let lastSeenStore: ILastSeenStore;
|
let lastSeenStore: ILastSeenStore;
|
||||||
|
let instanceService: ClientInstanceService;
|
||||||
|
let app: IUnleashTest;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
db = await dbInit('onboarding_read_model', getLogger, {
|
db = await dbInit('onboarding_read_model', getLogger, {
|
||||||
experimental: { flags: { onboardingMetrics: true } },
|
experimental: { flags: { onboardingMetrics: true } },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app = await setupAppWithCustomConfig(
|
||||||
|
db.stores,
|
||||||
|
{
|
||||||
|
experimental: {
|
||||||
|
flags: {
|
||||||
|
strictSchemaValidation: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
db.rawDatabase,
|
||||||
|
);
|
||||||
|
|
||||||
onboardingReadModel = db.stores.onboardingReadModel;
|
onboardingReadModel = db.stores.onboardingReadModel;
|
||||||
onBoardingStore = db.stores.onboardingStore;
|
onBoardingStore = db.stores.onboardingStore;
|
||||||
featureToggleStore = db.stores.featureToggleStore;
|
featureToggleStore = db.stores.featureToggleStore;
|
||||||
lastSeenStore = db.stores.lastSeenStore;
|
lastSeenStore = db.stores.lastSeenStore;
|
||||||
|
instanceService = app.services.clientInstanceService;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@ -178,3 +200,38 @@ test('archived feature counts as onboarded', async () => {
|
|||||||
status: 'onboarded',
|
status: 'onboarded',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('sdk register also onboards a project', async () => {
|
||||||
|
await featureToggleStore.create('default', {
|
||||||
|
name: 'my-flag',
|
||||||
|
createdByUserId: SYSTEM_USER.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultProjectToken =
|
||||||
|
await app.services.apiTokenService.createApiTokenWithProjects({
|
||||||
|
type: ApiTokenType.CLIENT,
|
||||||
|
projects: ['default'],
|
||||||
|
environment: 'default',
|
||||||
|
tokenName: 'tester',
|
||||||
|
});
|
||||||
|
|
||||||
|
await app.request
|
||||||
|
.post('/api/client/register')
|
||||||
|
.set('Authorization', defaultProjectToken.secret)
|
||||||
|
.send({
|
||||||
|
appName: 'multi-project-app',
|
||||||
|
instanceId: 'instance-1',
|
||||||
|
strategies: ['default'],
|
||||||
|
started: Date.now(),
|
||||||
|
interval: 10,
|
||||||
|
});
|
||||||
|
|
||||||
|
await instanceService.bulkAdd();
|
||||||
|
|
||||||
|
const onboardedResult =
|
||||||
|
await onboardingReadModel.getOnboardingStatusForProject('default');
|
||||||
|
|
||||||
|
expect(onboardedResult).toMatchObject({
|
||||||
|
status: 'onboarded',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -101,11 +101,25 @@ export class OnboardingReadModel implements IOnboardingReadModel {
|
|||||||
return { status: 'onboarding-started' };
|
return { status: 'onboarding-started' };
|
||||||
}
|
}
|
||||||
|
|
||||||
const lastSeen = await this.db('last_seen_at_metrics as lsm')
|
// const lastSeen = await this.db('last_seen_at_metrics as lsm')
|
||||||
.select('lsm.feature_name')
|
// .select('lsm.feature_name')
|
||||||
|
// .innerJoin('features as f', 'f.name', 'lsm.feature_name')
|
||||||
|
// .innerJoin('projects as p', 'p.id', 'f.project')
|
||||||
|
// .where('p.id', projectId)
|
||||||
|
// .first();
|
||||||
|
|
||||||
|
const db = this.db;
|
||||||
|
const lastSeen = await db
|
||||||
|
.select(db.raw('1'))
|
||||||
|
.from('last_seen_at_metrics as lsm')
|
||||||
.innerJoin('features as f', 'f.name', 'lsm.feature_name')
|
.innerJoin('features as f', 'f.name', 'lsm.feature_name')
|
||||||
.innerJoin('projects as p', 'p.id', 'f.project')
|
.innerJoin('projects as p', 'p.id', 'f.project')
|
||||||
.where('p.id', projectId)
|
.where('p.id', projectId)
|
||||||
|
.union((qb) => {
|
||||||
|
qb.select(db.raw('1'))
|
||||||
|
.from('client_applications_usage as cau')
|
||||||
|
.where('cau.project', projectId);
|
||||||
|
})
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (lastSeen) {
|
if (lastSeen) {
|
||||||
|
Loading…
Reference in New Issue
Block a user