Skip to content

Commit

Permalink
feat: start capturing onboarded status also from register endpoint (#…
Browse files Browse the repository at this point in the history
…8386)

1. Remove all customer intervals
2. Start capturing onboarded status also from register endpoint
sjaanus authored Oct 8, 2024
1 parent e8c73c7 commit 8f44540
Showing 14 changed files with 66 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -18,7 +18,6 @@ public class Program
{
AppName = "unleash-onboarding-dotnet",
UnleashApi = new Uri("<YOUR_API_URL>"),
SendMetricsInterval = TimeSpan.FromSeconds(1), // in production remove this or increase to >=15s
CustomHttpHeaders = new Dictionary<string, string>()
{
{"Authorization","<YOUR_API_TOKEN>"} // in production use environment variable
1 change: 0 additions & 1 deletion frontend/src/component/onboarding/dialog/snippets/go.md
Original file line number Diff line number Diff line change
@@ -19,7 +19,6 @@ func init() {
unleash.WithAppName("unleash-onboarding-golang"),
unleash.WithUrl("<YOUR_API_URL>"),
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
)
}

1 change: 0 additions & 1 deletion frontend/src/component/onboarding/dialog/snippets/java.md
Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@ UnleashConfig config = UnleashConfig.builder()
.instanceId("unleash-onboarding-instance")
.unleashAPI("<YOUR_API_URL>")
.apiKey("<YOUR_API_TOKEN>") // in production use environment variable
.sendMetricsInterval(1) // in production remove this or increase to >=15
.build();

Unleash unleash = new DefaultUnleash(config);
Original file line number Diff line number Diff line change
@@ -11,7 +11,6 @@ const unleash = new UnleashClient({
url: '<YOUR_API_URL>',
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
appName: 'unleash-onboarding-javascript',
metricsInterval: 1000, // in production remove this or increase to >=15000
});

unleash.start();
Original file line number Diff line number Diff line change
@@ -13,7 +13,6 @@ const unleash = initialize({
customHeaders: {
Authorization: '<YOUR_API_TOKEN>' // in production use environment variable
},
metricsInterval: 1000, // in production remove this or increase to >=15000
});

setInterval(() => {
1 change: 0 additions & 1 deletion frontend/src/component/onboarding/dialog/snippets/php.md
Original file line number Diff line number Diff line change
@@ -16,7 +16,6 @@ $unleash = UnleashBuilder::create()
->withAppUrl('<YOUR_API_URL>')
->withHeader('Authorization', '<YOUR_API_TOKEN>') // in production use environment variable
->withInstanceId('unleash-onboarding-instance')
->withMetricsInterval(1000) // in production remove this or increase to >=15000
->build();

while (true) {
Original file line number Diff line number Diff line change
@@ -11,7 +11,6 @@ import asyncio
client = UnleashClient(
url="<YOUR_API_URL>",
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

client.initialize_client()
1 change: 0 additions & 1 deletion frontend/src/component/onboarding/dialog/snippets/react.md
Original file line number Diff line number Diff line change
@@ -11,7 +11,6 @@ import { FlagProvider } from '@unleash/proxy-client-react';
const config = {
url: '<YOUR_API_URL>',
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
metricsInterval: 1, // In production use interval of >15s
appName: 'unleash-onboarding-react',
};

1 change: 0 additions & 1 deletion frontend/src/component/onboarding/dialog/snippets/ruby.md
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@ require 'unleash'
custom_http_headers: { 'Authorization': "<YOUR_API_TOKEN>" }, # in production use environment variable
app_name: 'unleash-onboarding-ruby',
instance_id: 'unleash-onboarding-ruby',
metrics_interval: 3, # In production use interval of >15s
)

while true
2 changes: 0 additions & 2 deletions frontend/src/component/onboarding/dialog/snippets/rust.md
Original file line number Diff line number Diff line change
@@ -26,7 +26,6 @@ enum Flags {
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
let client: Client<Flags, reqwest::Client> = ClientBuilder::default()
.interval(1000) // in production remove this or increase to >=15000
.into_client(
"<YOUR_API_URL>",
"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 client: Client<Flags, reqwest::Client> = ClientBuilder::default()
.interval(1000) // Polling & metrics interval - default 15000 (ms)
.into_client(
"<YOUR_API_URL>",
"unleash-onboarding-rust",
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@ npm install @unleash/proxy-client-svelte
url: '<YOUR_API_URL>',
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
appName: 'unleash-onboarding-svelte',
metricsInterval: 1, // in production remove this or increase to >=15
};
</script>
1 change: 0 additions & 1 deletion frontend/src/component/onboarding/dialog/snippets/vue.md
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@ npm install @unleash/proxy-client-vue
url: '<YOUR_API_URL>',
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
appName: 'unleash-onboarding-vue',
metricsInterval: 1, // in production remove this or increase to >=15
}
</script>
57 changes: 57 additions & 0 deletions src/lib/features/onboarding/onboarding-read-model.test.ts
Original file line number Diff line number Diff line change
@@ -7,21 +7,43 @@ import {
SYSTEM_USER,
} from '../../types';
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 onboardingReadModel: IOnboardingReadModel;
let onBoardingStore: IOnboardingStore;
let featureToggleStore: IFeatureToggleStore;
let lastSeenStore: ILastSeenStore;
let instanceService: ClientInstanceService;
let app: IUnleashTest;

beforeAll(async () => {
db = await dbInit('onboarding_read_model', getLogger, {
experimental: { flags: { onboardingMetrics: true } },
});

app = await setupAppWithCustomConfig(
db.stores,
{
experimental: {
flags: {
strictSchemaValidation: true,
},
},
},
db.rawDatabase,
);

onboardingReadModel = db.stores.onboardingReadModel;
onBoardingStore = db.stores.onboardingStore;
featureToggleStore = db.stores.featureToggleStore;
lastSeenStore = db.stores.lastSeenStore;
instanceService = app.services.clientInstanceService;
});

afterAll(async () => {
@@ -178,3 +200,38 @@ test('archived feature counts as onboarded', async () => {
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',
});
});
11 changes: 9 additions & 2 deletions src/lib/features/onboarding/onboarding-read-model.ts
Original file line number Diff line number Diff line change
@@ -101,11 +101,18 @@ export class OnboardingReadModel implements IOnboardingReadModel {
return { status: 'onboarding-started' };
}

const lastSeen = await this.db('last_seen_at_metrics as lsm')
.select('lsm.feature_name')
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('projects as p', 'p.id', 'f.project')
.where('p.id', projectId)
.union((qb) => {
qb.select(db.raw('1'))
.from('client_applications_usage as cau')
.where('cau.project', projectId);
})
.first();

if (lastSeen) {

0 comments on commit 8f44540

Please sign in to comment.