Skip to content

Commit a65d648

Browse files
authored
Add basic component initialization tracing (#3986)
* Add basic component initialization tracing * Review changes * Add unit test and review changes * Add missing copyright header * Formatting
1 parent eefb794 commit a65d648

File tree

5 files changed

+169
-0
lines changed

5 files changed

+169
-0
lines changed

firebase-common/src/main/java/com/google/firebase/FirebaseApp.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
import com.google.firebase.heartbeatinfo.DefaultHeartBeatController;
5252
import com.google.firebase.inject.Provider;
5353
import com.google.firebase.internal.DataCollectionConfigStorage;
54+
import com.google.firebase.tracing.ComponentMonitor;
55+
import com.google.firebase.tracing.FirebaseTrace;
5456
import java.nio.charset.Charset;
5557
import java.util.ArrayList;
5658
import java.util.Collections;
@@ -415,18 +417,25 @@ protected FirebaseApp(Context applicationContext, String name, FirebaseOptions o
415417
this.name = Preconditions.checkNotEmpty(name);
416418
this.options = Preconditions.checkNotNull(options);
417419

420+
FirebaseTrace.pushTrace("Firebase");
421+
422+
FirebaseTrace.pushTrace("ComponentDiscovery");
418423
List<Provider<ComponentRegistrar>> registrars =
419424
ComponentDiscovery.forContext(applicationContext, ComponentDiscoveryService.class)
420425
.discoverLazy();
426+
FirebaseTrace.popTrace(); // ComponentDiscovery
421427

428+
FirebaseTrace.pushTrace("Runtime");
422429
componentRuntime =
423430
ComponentRuntime.builder(UI_EXECUTOR)
424431
.addLazyComponentRegistrars(registrars)
425432
.addComponentRegistrar(new FirebaseCommonRegistrar())
426433
.addComponent(Component.of(applicationContext, Context.class))
427434
.addComponent(Component.of(this, FirebaseApp.class))
428435
.addComponent(Component.of(options, FirebaseOptions.class))
436+
.setProcessor(new ComponentMonitor())
429437
.build();
438+
FirebaseTrace.popTrace(); // Runtime
430439

431440
dataCollectionConfigStorage =
432441
new Lazy<>(
@@ -443,6 +452,8 @@ protected FirebaseApp(Context applicationContext, String name, FirebaseOptions o
443452
defaultHeartBeatController.get().registerHeartBeat();
444453
}
445454
});
455+
456+
FirebaseTrace.popTrace(); // Firebase
446457
}
447458

448459
private void checkNotDeleted() {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.tracing;
16+
17+
import com.google.firebase.components.Component;
18+
import com.google.firebase.components.ComponentRegistrar;
19+
import com.google.firebase.components.ComponentRegistrarProcessor;
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
23+
/** Wraps components to trace their initialization time. */
24+
public class ComponentMonitor implements ComponentRegistrarProcessor {
25+
@Override
26+
public List<Component<?>> processRegistrar(ComponentRegistrar registrar) {
27+
List<Component<?>> components = new ArrayList<>();
28+
for (Component comp : registrar.getComponents()) {
29+
String name = comp.getName();
30+
if (name != null) {
31+
@SuppressWarnings("unchecked")
32+
Component<Object> old = (Component<Object>) comp;
33+
comp =
34+
old.withFactory(
35+
c -> {
36+
try {
37+
FirebaseTrace.pushTrace(name);
38+
return old.getFactory().create(c);
39+
} finally {
40+
FirebaseTrace.popTrace();
41+
}
42+
});
43+
}
44+
components.add(comp);
45+
}
46+
return components;
47+
}
48+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.tracing;
16+
17+
import android.os.Build;
18+
import android.os.Trace;
19+
20+
/** Utility to consistently wrap trace calls with version checking. */
21+
public final class FirebaseTrace {
22+
23+
private FirebaseTrace() {}
24+
25+
public static void pushTrace(String name) {
26+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
27+
Trace.beginSection(name);
28+
}
29+
}
30+
31+
public static void popTrace() {
32+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
33+
Trace.endSection();
34+
}
35+
}
36+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/** @hide */
16+
package com.google.firebase.tracing;
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.tracing;
16+
17+
import static com.google.common.truth.Truth.assertThat;
18+
19+
import androidx.test.ext.junit.runners.AndroidJUnit4;
20+
import com.google.firebase.components.Component;
21+
import com.google.firebase.components.ComponentContainer;
22+
import java.util.ArrayList;
23+
import java.util.List;
24+
import org.junit.Test;
25+
import org.junit.runner.RunWith;
26+
27+
@RunWith(AndroidJUnit4.class)
28+
public class ComponentMonitorTest {
29+
30+
@Test
31+
public void testComponentMonitorTransformation() {
32+
List<Component<?>> list = new ArrayList<Component<?>>();
33+
list.add(
34+
Component.builder(ComponentHolder.class)
35+
.factory(ComponentHolder::new)
36+
.name("test")
37+
.build());
38+
list.add(
39+
Component.builder(ComponentHolder.class).factory(ComponentHolder::new).name("foo").build());
40+
list.add(
41+
Component.builder(ComponentHolder.class).factory(ComponentHolder::new).name("bar").build());
42+
ComponentMonitor monitor = new ComponentMonitor();
43+
List<Component<?>> transformed = monitor.processRegistrar(() -> list);
44+
assertThat(list.size()).isEqualTo(transformed.size());
45+
for (int i = 0; i < list.size(); i++) {
46+
assertThat(list.get(i).getName()).isEqualTo(transformed.get(i).getName());
47+
assertThat(transformed.get(i).getFactory().create(null)).isNotNull();
48+
}
49+
}
50+
51+
private static final class ComponentHolder {
52+
private final ComponentContainer container;
53+
54+
public ComponentHolder(ComponentContainer container) {
55+
this.container = container;
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)