Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EMB-3907 Android side for tracer provider #36

Draft
wants to merge 30 commits into
base: feature-react-native-tracer-provider
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
24583da
EMB-3907 tracer provider package with android implementation
jpmunz Jun 17, 2024
ed35345
EMBR-3907 android build and test setup
jpmunz Jun 27, 2024
da9e062
EMBR-3907 review comments, kotlin lint
jpmunz Jun 28, 2024
a867da7
EMBR-3907 pass schemaUrl correctly, remove web-trace package dependency
jpmunz Jun 28, 2024
4d616d5
EBMR-3907 embrace sdk dependency
jpmunz Jun 28, 2024
1ae3190
EMBR-3907 linting
jpmunz Jun 28, 2024
6f12ff8
EMBR-3907 pushd not on build server
jpmunz Jun 28, 2024
3b1a088
EMBR-3907 setup Java in CI
jpmunz Jul 3, 2024
3f6ba0e
Merge branch 'feature-react-native-tracer-provider' into jpmunz/EMBR-…
jpmunz Jul 8, 2024
b9acad8
Merge branch 'feature-react-native-tracer-provider' into jpmunz/EMBR-…
jpmunz Jul 8, 2024
48d2569
Merge branch 'feature-react-native-tracer-provider' into jpmunz/EMBR-…
jpmunz Jul 8, 2024
eb883b8
EBMR-4247 JS layer for tracer provider
jpmunz Jul 8, 2024
d747459
Merge branch 'jpmunz/EMBR-4247-rn-tracer-provider-js-layer' into jpmu…
jpmunz Jul 8, 2024
5c02c5b
EMBR-3907 renaming
jpmunz Jul 8, 2024
d1112ad
EMBR-4247 rename module
jpmunz Jul 8, 2024
ff273ef
Merge branch 'jpmunz/EMBR-4247-rn-tracer-provider-js-layer' into jpmu…
jpmunz Jul 8, 2024
fbe0dc8
EMBR-4247 linting updates
jpmunz Jul 8, 2024
812c675
Merge branch 'feature-react-native-tracer-provider' into jpmunz/EMBR-…
jpmunz Jul 8, 2024
550c79e
EMBR-4247 typo on mock
jpmunz Jul 8, 2024
3ef8ceb
Merge branch 'jpmunz/EMBR-4247-rn-tracer-provider-js-layer' into jpmu…
jpmunz Jul 8, 2024
7bc73a7
EMBR-3907 fix scripts constraint
jpmunz Jul 8, 2024
1175f53
EMBR-3907 yarn update
jpmunz Jul 8, 2024
fea24ae
EMBR-3907 tests passing with Embracer tracer provider
jpmunz Jul 9, 2024
be45048
Merge branch 'feature-react-native-tracer-provider' into jpmunz/EMBR-…
jpmunz Jul 9, 2024
4cbb2c8
Merge branch 'jpmunz/EMBR-4247-rn-tracer-provider-js-layer' into jpmu…
jpmunz Jul 9, 2024
0c5258b
Merge branch 'feature-react-native-tracer-provider' into jpmunz/EMBR-…
jpmunz Jul 9, 2024
e26e52f
Merge branch 'jpmunz/EMBR-4247-rn-tracer-provider-js-layer' into jpmu…
jpmunz Jul 9, 2024
efd4e59
EMBR-4247 update how package is built
jpmunz Jul 9, 2024
1e109a0
Merge branch 'jpmunz/EMBR-4247-rn-tracer-provider-js-layer' into jpmu…
jpmunz Jul 9, 2024
d67d409
Merge branch 'feature-react-native-tracer-provider' into jpmunz/EMBR-…
jpmunz Jul 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
EMB-3907 tracer provider package with android implementation
  • Loading branch information
jpmunz committed Jun 17, 2024
commit 24583daadae894f680f60f0ff7b25a0f9a42a2c2
31 changes: 13 additions & 18 deletions integration-tests/basic-test-app/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,29 @@
import { Tabs } from 'expo-router';
import React from 'react';
import { Tabs } from "expo-router";
import React from "react";

import { TabBarIcon } from '@/components/navigation/TabBarIcon';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
import { TabBarIcon } from "@/components/navigation/TabBarIcon";
import { Colors } from "@/constants/Colors";
import { useColorScheme } from "@/hooks/useColorScheme";

export default function TabLayout() {
const colorScheme = useColorScheme();

return (
<Tabs
screenOptions={{
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
tabBarActiveTintColor: Colors[colorScheme ?? "light"].tint,
headerShown: false,
}}>
}}
>
<Tabs.Screen
name="index"
options={{
title: 'Home',
title: "HOME",
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'home' : 'home-outline'} color={color} />
),
}}
/>
<Tabs.Screen
name="explore"
options={{
title: 'Explore',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
<TabBarIcon
name={focused ? "home" : "home-outline"}
color={color}
/>
),
}}
/>
Expand Down
102 changes: 0 additions & 102 deletions integration-tests/basic-test-app/app/(tabs)/explore.tsx

This file was deleted.

27 changes: 23 additions & 4 deletions integration-tests/basic-test-app/app/(tabs)/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import { Image, StyleSheet, Button } from "react-native";
import { useCallback } from "react";
import { useCallback, useMemo } from "react";

import { ThemedView } from "@/components/ThemedView";
import { ThemedText } from "@/components/ThemedText";

import ParallaxScrollView from "@/components/ParallaxScrollView";
import { endSession, logError } from "@embrace-io/react-native";
import { endSession } from "@embrace-io/react-native";
import {
generateNestedSpans,
generateTestSpans,
} from "@/helpers/generateSpans";
import { Tracer } from "@opentelemetry/api";
import { EmbraceNativeTracerProvider } from "@embrace.io/react-native-tracer-provider";

const HomeScreen = () => {
const handleEndSession = useCallback(() => {
console.log("end session was clicked");
endSession();
}, []);
const tracer = useMemo<Tracer>(() => {
return new EmbraceNativeTracerProvider().getTracer("span-test", "1.0");
}, []);

return (
<ParallaxScrollView
Expand All @@ -24,9 +32,20 @@ const HomeScreen = () => {
}
>
<ThemedView style={styles.stepContainer}>
<ThemedText type="subtitle">End Session</ThemedText>
<ThemedText type="subtitle">Session</ThemedText>
<Button onPress={handleEndSession} title="END SESSION" />
</ThemedView>
<ThemedView style={styles.stepContainer}>
<ThemedText type="subtitle">Span</ThemedText>
<Button
onPress={() => generateTestSpans(tracer)}
title={"GENERATE TEST SPANS"}
/>
<Button
onPress={() => generateNestedSpans(tracer)}
title={"GENERATE NESTED SPANS"}
/>
</ThemedView>
</ParallaxScrollView>
);
};
Expand Down
83 changes: 83 additions & 0 deletions integration-tests/basic-test-app/helpers/generateSpans.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* 'use strict'; */
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
context,
SpanKind,
SpanStatusCode,
trace,
Tracer,
} from "@opentelemetry/api";

export function generateTestSpans(tracer: Tracer) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Random thought: is it possible to construct a span where the end-time is before the start-time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a good point I can add an example of that to see how it's handled, I believe the interface allows that so it would be up to our implementation how it would treat that case

const span1 = tracer.startSpan("test-1");
const span2 = tracer.startSpan("test-2", { kind: SpanKind.CLIENT });
const span3 = tracer.startSpan("test-3");
// Not ended so shouldn't be part of the output

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates an implicit dependency where generateTestSpans needs to be called before generateNestedSpans right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they should be independent the idea would be to call generateTestSpans followed by ending the session so the payload can be verified then separately in a following test we'll call generateNestedSpans and end that session so the payload shouldn't include data from the previous run

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah OK. That makes sense. Is that documented or implicit anywhere that I missed?

Copy link
Contributor Author

@jpmunz jpmunz Jun 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let me add some comments to this file, I wasn't sure if I was going to stick with this approach as there were 2 options:

  1. in the basic test app expose buttons/inputs for interacting with the spans API so that the test case can do all the individual setup (e.g. start span, add attributes, etc.)
  2. in the basic test app expose a single "test this scenario" button and do the asserts in the test case
  1. I think is ideal because then you can read all the setup and assertions together in the test, however when I started to implement this way I found it was just very time consuming to create the full interface that was needed to do all the setup that is being done here

  2. simplifies things but creates this disconnect between the assertions in the test spec and what setup was actually done, probably going to stick with this for now but I'll add comments to this file to make it clear why that was separated

tracer.startSpan("test-4");

// Set some attributes
span1.setAttributes({
"string-attr": "my-attr",
"number-attr": 22,
});
span1.setAttribute("bool-attr", true);

// Misc updates
span1.setStatus({ code: SpanStatusCode.OK, message: "ok span" });
span1.updateName("test-1-updated");

// Make sure isRecording reports correctly
if (span1.isRecording()) {
span1.end();
}
if (span1.isRecording()) {
span1.setAttribute("after-recording", "should not exist");
}

// Add some span events
span2.addEvent("test-2-event-1");
span2.addEvent("test-2-event-2", 1700001002000);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these constant values have specific meanings?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, just arbitrary values that can we can assert got added later in the test

span2.addEvent(
"test-2-event-3",
{ "test-2-event-attr": "my-event-attr" },
1700009002000
);
span2.end(new Date("2099-01-01T00:00:00Z"));

// Add some links
span3.addLink({ context: span1.spanContext() });
span3.addLinks([
{
context: span2.spanContext(),
attributes: { "test-3-link-attr": "my-link-attr" },
},
]);
span3.recordException({ message: "span exception" });
span3.end();
}

export function generateNestedSpans(tracer: Tracer) {
const span1 = tracer.startSpan("test-1");
const span1Context = trace.setSpan(context.active(), span1);
const span2 = tracer.startSpan(
"test-2",
{ attributes: { "test-2-attr": "my-attr" } },
span1Context
);
const span3 = tracer.startSpan(
"test-3",
{ attributes: { "test-3-attr": "my-attr" }, root: true },
span1Context
);

tracer.startActiveSpan("test-4", (span4) => {
const span5 = tracer.startSpan("test-5");
span5.end();

span4.end();
});
span1.end();
span2.end();
span3.end();
}
1 change: 1 addition & 0 deletions integration-tests/basic-test-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"dependencies": {
"@embrace-io/react-native": "file:../artifacts/embrace-io-react-native-local.tgz",
"@embrace.io/react-native-tracer-provider": "file:../artifacts/embrace-io-react-native-tracer-provider-local.tgz",
"@expo/vector-icons": "^14.0.0",
"@react-navigation/native": "^6.0.2",
"expo": "~51.0.9",
Expand Down
20 changes: 10 additions & 10 deletions integration-tests/helpers/embrace_server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { start_mockserver, stop_mockserver } from 'mockserver-node';
import { EmbraceRequestBody, SessionPayload } from '../typings/embrace';
import { start_mockserver, stop_mockserver } from "mockserver-node";
import { EmbraceRequestBody, SessionMessage } from "../typings/embrace";

import { mockServerClient } from 'mockserver-client';
import { mockServerClient } from "mockserver-client";

const PORT = 8877;

Expand All @@ -19,26 +19,26 @@ const stopServer = () => {
};

const clearServer = async () => {
return await mockServerClient('localhost', PORT).clear({}, 'LOG');
return await mockServerClient("localhost", PORT).clear({}, "LOG");
};

const getSessionPayloads = async (delay = 2000): Promise<SessionPayload[]> => {
const getSessionMessages = async (delay = 2000): Promise<SessionMessage[]> => {
if (delay) {
await new Promise((r) => setTimeout(r, delay));
}

const requests = await mockServerClient(
'localhost',
"localhost",
PORT
).retrieveRecordedRequests({
path: '/v1/log/sessions',
method: 'POST',
path: "/v1/log/sessions",
method: "POST",
});

return requests.map((r) => {
const body = r.body as EmbraceRequestBody;
return body.json.s;
return body.json;
});
};

export { startServer, stopServer, clearServer, getSessionPayloads };
export { startServer, stopServer, clearServer, getSessionMessages };
14 changes: 7 additions & 7 deletions integration-tests/specs/session.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { driver } from '@wdio/globals';
import { driver } from "@wdio/globals";

import { getSessionPayloads } from '../helpers/embrace_server';
import { getSessionMessages } from "../helpers/embrace_server";

describe('Sessions', () => {
it('should be recorded as foreground', async () => {
const endSession = await driver.$('~END SESSION');
describe("Sessions", () => {
it("should be recorded as foreground", async () => {
const endSession = await driver.$("~END SESSION");
await endSession.click();

const sessionPayloads = await getSessionPayloads();
const sessionPayloads = await getSessionMessages();

expect(sessionPayloads).toHaveLength(1);
if (sessionPayloads.length > 0) {
expect(sessionPayloads[0].as).toBe('foreground');
expect(sessionPayloads[0].s.as).toBe("foreground");
}
});
});
Loading