Connect with us

FACEBOOK

Async stack traces in folly: Introduction

Published

on

This article was written by Lee Howes and Lewis Baker from Facebook.

Facebook’s infrastructure is highly distributed and relies heavily on asynchronous programming. Most of our services that are written in C++ are implemented using async programming frameworks like folly::Futures and folly::coro. Async programming is an important tool for scaling a process with a relatively small number of threads to handle a much larger number of concurrent requests. However, these async programming models have typically come with some downsides.

One of these downsides is that existing debugging and profiling tools that make use of stack-traces to provide information about what your program was doing generally give poor quality data for async code.

This is the first in a short series of blog posts about how we are leveraging C++ coroutines to improve this situation, and describing the technical details of our solution. This first post gives a high level background, and later posts in the series go into fairly deep technical detail about the implementation in folly and surrounding tooling to assist debugging and profiling of coroutine code.

Why async stack traces?

For some years, the library we have relied on for async programming at Facebook is folly’s Futures library, which allows code like the following:

Advertisement
free widgets for website
Executor& e = ...;
Future<void> s = makeSemiFuture() .via(&e) .thenValue([](auto&&) { doWork(); });
doComplexOperation();
Future<void> s2 = std::move(s) .thenValue([](auto&&) { doMoreWork(); }); 

where the lambda containing doWork will run at some point on the thread pool represented by e.

Async code like the example above generally involves launching an operation and then attaching a callback or continuation to that operation that will be executed when that operation completes. doComplexOperation can run on the main thread concurrently with doWork running on some other thread owned by the Executor. In general, this avoids much of the overhead of thread-context switches that you get when using thread-per-task concurrency. However, this also means that the callback is often executed in a different context from the context that launched it, usually from an executor’s event-loop.

Under normal circumstances, when code is launched on an executor, for example a thread pool, a stack trace will represent the path from the thread’s execution loop to the function being run. Conceptually, the threads in the executor do something like:

Executor::run() { while(!cancelled) { auto t = queue_.getTask(); t(); }
} 

If we run this in a debugger and break inside doWork the stack trace will look like:

- doWork
- <some function type-erasure internals...>
- Executor::run
- <some executor / thread startup internals...>
- __thread_start 

The trace will only cover stack frames from doWork’s body down to the run method of the executor. The connection to the calling code, and to doMoreWork is lost. This loss of context can make debugging or profiling such code very challenging.

Advertisement
free widgets for website

It is hard to fix this loss of context in futures code like the example above. With a normal stack-trace, when one function calls another, the full call stack is preserved for the duration of the call, allowing any stack walks performed while the function is executing to be able to easily trace back through the calling code without having to do any more work. However, with futures, the code that launches an operation continues executing and may unwind its call-stack before the continuation attached to the future runs. The calling context is not preserved and we’d need to effectively take a snapshot of the call stack at the time when the operation is launched to be able to later reconstruct the full call stack, incurring a large runtime overhead. Coroutines offer us a nesting that makes this cleaner:

Executor& e = ...;
auto l = []() -> Task<void> { co_await doWork(); co_await doMoreWork();
};
l().scheduleOn(e).start(); 

The compiler transforms this to something like the futures code above, but structurally there is a big difference: the next continuation is in the same scope as the parent. This makes the idea of a “stack” of coroutines make much more sense, at least syntactically. Taking advantage of this and helping us with debugging is still a technical challenge.

See also  Facebook (FB) Dips More Than Broader Markets: What You Should Know

Coroutines as callbacks

C++ uses a style of coroutines that suspend by return from a function: that is to say that we do not suspend the entire stack, we return from the coroutine and have the suspended state stored separately. This is distinct from the “fiber” style of coroutine where we suspend the entire stack. The implementation of this looks something like a series of callbacks, and a hidden linked list of chained coroutine frames exposed through the sequence of function calls.

There are big advantages to the style of coroutines chosen for C++, which we will not go into here, but one downside is that while the nested structure is there in the code, it is not directly apparent in the stack frames visible to a debugger or profiling tool.

To illustrate this problem, consider the following more complicated code snippet of folly::coro code, during the execution of which we want to sample a stack trace:

Advertisement
free widgets for website
void normal_function_1() { // ... expensive code - sample taken here.
} void normal_function_2() { // ... normal_function_1(); // ...
} folly::coro::Task<void> coro_function_1() { // ... normal_function_2(); // ... co_return;
} folly::coro::Task<void> coro_function_2() { // ... co_await coro_function_1(); // ...
} void run_application() { // ... folly::coro::blockingWait( coro_function_2().scheduleOn(folly::getGlobalCPUExecutor())); // ...
} int main() { run_application();
} 

Currently, if the profiler captures a sample when code is executing within normal_function_1() then it might show a stack trace that looks something like:

- normal_function_1
- normal_function_2
- coro_function_1
- std::coroutine_handle::resume
- folly::coro::TaskWithExecutor::Awaiter::await_suspend::$lambda0::operator()
- folly::Function::operator()
- folly::CPUThreadPoolExecutor::run
- std::thread::_invoke
- __thread_start 

Notice how only coro_function_1 appears with coro_function_2 missing. From coro_function_1 the trace moves into internal details of the framework and executor. We can’t see from this stack-trace that coro_function_1() is called from coro_function_2() and that coro_function_2() is in turn called from run_application() and main().

See also  Facebook 'misplaced' important rule exception on discussing dangerous individuals, says ...

Further, if there were multiple call-sites for coro_function_1(), in a sampled profiling system, all of their samples from different call sites will probably get merged together, making it difficult to determine which call sites are expensive. This can make it difficult to determine where you should focus your efforts when looking for performance optimisations.

Ideally, both profiling tools and debuggers would be able to capture the logical stack-trace instead The result would show the relationship between coro_function_1 and its caller coro_function_2, and we’d end up with a stack trace for this sample that looks more like this:

- normal_function_1
- normal_function_2
- coro_function_1
- coro_function_2
- blockingWait
- run_application
- main 

folly support for async stack traces

folly now implements a set of tools to support async stack traces for coroutines. The library provides fundamental hooks that are used by internal code profiling libraries. Those same hooks provide access to stack traces for debugging purposes.

Advertisement
free widgets for website

These are briefly summarised here and we will go into detail in a later post.

Printing async stack traces when the program crashes

Probably the most frequent place where developers see stack traces is when programs crash. The folly library already provides a signal handler that prints the stack trace of the thread that is causing the program to crash. The signal handler now prints the async stack trace if there is a coroutine active on the current thread when the crash happens.

Printing async stack traces on demand

During development, a frequent question developers have is: What is the series of function calls that led to this function being called? folly provides a convenience function to easily print the async stack trace on demand, helping developers quickly see how a function or coroutine is called:

#include <iostream>
#include <folly/experimental/symbolizer/Symbolizer.h> folly::coro::Task<void> co_foo() { std::cerr << folly::symbolizer::getAsyncStackTraceStr() << std::endl;
} 

GDB extension to print async stack traces

C++ developers often need to use debuggers like GDB to debug crashes after-the-fact or to investigate buggy behavior in running programs. We recently implemented a GDB extension to easily print the async stack trace for the current thread from within the debugger:

# Print the async stack trace for the current thread
(gdb) co_bt
0x... in crash() ()
0x... in co_funcC() [clone .resume] ()
0x... in co_funcB() [clone .resume] ()
0x... in co_funcA() [clone .resume] ()
0x... in main ()
0x... in folly::detached_task() () 

Tracking where exceptions are thrown

We want to be able to tell where an exception was constructed/thrown from when it is later caught. To meet this need, folly provides an exception tracer library to hook into the Itanium C++ ABI for exception handling to track exception information. We have recently expanded the set of helper functions this library provides to easily track where exceptions are thrown, including both normal and async stack traces. Below is an example program that uses these helpers:

Advertisement
free widgets for website
folly::coro::Task<void> co_funcA() { try { co_await co_funcB(); } catch (const std::exception& ex) { // Prints where the exception was thrown std::cerr << "what(): " << ex.what() << ", " << folly::exception_tracer::getAsyncTrace(ex) << std::endl; }
} 

Concluding

This new functionality brings coroutines much closer to the level of debugging and tracing support we see with normal stacks. Facebook developers already benefit from these changes, and they are open source in the folly library for anybody to use.

See also  Mashpee TikToker gets real about neighborhood Facebook groups

In subsequent posts in this series, we will go into more detail about how this is implemented. Next week, we will discuss the differences between synchronous and asynchronous stack traces and the technical challenges of implementing traces on top of C++20 coroutines. Stay tuned!

Facebook Developers

Continue Reading
Advertisement free widgets for website

FACEBOOK

Creating Apps with App Use Cases

Published

on

By

creating-apps-with-app-use-cases

With the goal of making Meta’s app creation process easier for developers to create and customize their apps, we are announcing the rollout of an updated process using App Use Cases instead of the former product-focused process. App Use Cases will enable developers to quickly create apps by selecting the use case that best represents their reason for creating an app.

Currently, the product-focused app creation process requires developers to select an app type and individually request permission to API endpoints. After listening to feedback from developers saying this process was, at times, confusing and difficult to navigate, we’re updating our approach that’s based on App Use Cases. With App Use Cases, user permissions and features will be bundled with each use case so developers can now confidently select the right data access for their needs. This change sets developers up for success to create their app and navigate app review, ensuring they only get the exact data access they need to accomplish their goals.

Starting today Facebook Login will be the first use case to become available to developers. This will be the first of many use cases that will be built into the app creation process that will roll out continually in 2023. For more information please reference our Facebook Login documentation.

First seen at developers.facebook.com

See also  Facebook 'misplaced' important rule exception on discussing dangerous individuals, says ...
Continue Reading

FACEBOOK

Understanding Authorization Tokens and Access for the WhatsApp Business Platform

Published

on

By

understanding-authorization-tokens-and-access-for-the-whatsapp-business-platform

The WhatsApp Business Platform makes it easy to send WhatsApp messages to your customers and automate replies. Here, we’ll explore authentication using the Cloud API, hosted by Meta.

We’ll start with generating and using a temporary access token and then replace it with a permanent access token. This tutorial assumes you’re building a server-side application and won’t need additional steps to keep your WhatsApp application secrets securely stored.

Managing Access and Authorization Tokens

First, let’s review how to manage authorization tokens and safely access the API.

Prerequisites

Start by making sure you have a developer account on Meta for Developers. You’ll also need WhatsApp installed on a mobile device to send test messages to.

Creating an App

Before you can authenticate, you’ll need an application to authenticate you.

Advertisement
free widgets for website

Once you’re signed in, you see the Meta for Developers App Dashboard. Click Create App to get started.

Next, you’ll need to choose an app type. Choose Business.

After that, enter a display name for your application. If you have a business account to link to your app, select it. If not, don’t worry. The Meta for Developers platform creates a test business account you can use to experiment with the API. When done, click Create App.

Then, you’ll need to add products to your app. Scroll down until you see WhatsApp and click the Set up button:

Finally, choose an existing Meta Business Account or ask the platform to create a new one and click Continue:

Advertisement
free widgets for website

And with that, your app is created and ready to use. You’re automatically directed to the app’s dashboard.

Note that you have a temporary access token. For security reasons, the token expires in less than 24 hours. However, you can use it for now to test accessing the API. Later, we’ll cover how to generate a permanent access token that your server applications can use. Also, note your app’s phone number ID because you’ll need it soon.

See also  Facebook 'misplaced' important rule exception on discussing dangerous individuals, says ...

Click the dropdown under the To field, and then click Manage phone number list.

In the popup that appears, enter the phone number of a WhatsApp account to send test messages to.

Then, scroll further down the dashboard page and you’ll see an example curl call that looks similar to this:

Advertisement
free widgets for website
curl -i -X POST https://graph.facebook.com/v13.0//messages -H 'Authorization: Bearer ' -H 'Content-Type: application/json' -d '{ "messaging_product": "whatsapp", "to": "", "type": "template", "template": { "name": "hello_world", "language": { "code": "en_US" } } }'

Note that the Meta for Developers platform inserts your app’s phone number ID and access token instead of the and placeholders shown above. If you have curl installed, paste the command into your terminal and run it. You should receive a “hello world” message in WhatsApp on your test device.

If you’d prefer, you can convert the curl request into an HTTP request in your programming language by simply creating a POST request that sets the Authorization and Content-Type headers as shown above, including the JSON payload in the request body.

Since this post is about authentication, let’s focus on that. Notice that you’ve included your app’s access token in the Authorization header. For any request to the API, you must set the Authorization header to Bearer .

Remember that you must use your token instead of the placeholder. Using bearer tokens will be familiar if you’ve worked with JWT or OAuth2 tokens before. If you’ve never seen one before, a bearer token is essentially a random secret string that you, as the bearer of the token, can present to an API to prove you’re allowed to access it.

Failure to include this header causes the API to return a 401 Unauthorized response code.

Advertisement
free widgets for website

Creating a Permanent Access Token

Knowing that you need to use a bearer token in the Authorization header of an HTTP request is helpful, but it’s not enough. The only access token you’ve seen so far is temporary. Chances are that you want your app to access the API for more than 24 hours, so you need to generate a longer-lasting access token.

Fortunately, the Meta for Developers platform makes this easy. All you need to do is add a System User to your business account to obtain an access token you can use to continue accessing the API. To create a system user, do the following:

  • Go to Business Settings.

  • Select the business account your app is associated with.
  • Below Users, click System Users.
  • Click Add.
  • Name the system user, choose Admin as the user role, and click Create System User.
  • Select the whatsapp_business_messaging permission.
  • Click Generate New Token.
  • Copy and save your token.

Your access token is a random string of letters and numbers. Now, try re-running the earlier request using the token you just created instead of the temporary one:

curl -i -X POST https://graph.facebook.com/v13.0//messages -H 'Authorization: Bearer ' -H 'Content-Type: application/json' -d '{ "messaging_product": "whatsapp", "to": "", "type": "template", "template": { "name": "hello_world", "language": { "code": "en_US" } } }'

Your test device should receive a second hello message sent via the API.

Best Practices for Managing Access Tokens

It’s important to remember that you should never embed an App Access Token in a mobile or desktop application. These tokens are only for use in server-side applications that communicate with the API. Safeguard them the same way you would any other application secrets, like your database credentials, as anyone with your token has access to the API as your business.

If your application runs on a cloud services provider like AWS, Azure, GCP, or others, those platforms have tools to securely store app secrets. Alternatively there are freely-available secret stores like Vault or Conjur. While any of these options may work for you, it’s important to evaluate your options and choose what works best for your setup. At the very least, consider storing access tokens in environment variables and not in a database or a file where they’re easy to find during a data breach.

Advertisement
free widgets for website

Conclusion

In this post, you learned how to create a Meta for Developers app that leverages the WhatsApp Business Platform. You now know how the Cloud API’s bearer access tokens work, how to send an access token using an HTTP authorization header, and what happens if you send an invalid access token. You also understand the importance of keeping your access tokens safe since an access token allows an application to access a business’ WhatsApp messaging capabilities.

Why not try using the Cloud API, hosted by Meta if you’re considering building an app for your business to manage WhatsApp messaging? Now that you know how to obtain and use access tokens, you can use them to access any endpoint in the API.

First seen at developers.facebook.com

Continue Reading

FACEBOOK

Now people can share directly to Instagram Reels from some of their favorite apps

Published

on

By

now-people-can-share-directly-to-instagram-reels-from-some-of-their-favorite-apps

More people are creating, sharing and watching Reels than ever before. We’ve seen the creator community dive deeply into video content – and use it to connect with their communities. We’re running a limited alpha test that lets creators share video content directly from select integrated apps to Instagram Reels. Now, creators won’t be interrupted in their workflow, making it easier for them share share and express themselves on Reels.

“With the shift to video happening across almost all online platforms, our innovative tools and services empower creativity and fuel the creator economy and we are proud to be able to offer a powerful editing tool like Videoleap that allows seamless content creation, while partnering with companies like Meta to make sharing content that much easier.”- Zeev Farbman, CEO and co-founder of Lightricks.

Starting this month, creators can share short videos directly to Instagram Reels from some of their favorite apps, including Videoleap, Reface, Smule, VivaVideo, SNOW, B612, VITA and Zoomerang, with more coming soon. These apps and others also allow direct sharing to Facebook , which is available for any business with a registered Facebook App to use.

We hope to expand this test to more partners in 2023. If you’re interested in being a part of that beta program, please fill out this form and we will keep track of your submission. We do not currently have information to share about general availability of this integration.

Learn more here about sharing Stories and Reels to Facebook and Instagram and start building today.

Advertisement
free widgets for website

FAQs

Q. What is the difference between the Instagram Content Publishing API and Instagram Sharing to Reels?

See also  WTF is server-side conversion tracking?

A: Sharing to Reels is different from the Instagram Content Publishing API, which allows Instagram Business accounts to schedule and publish posts to Instagram from third-party platforms. Sharing to Reels is specifically for mobile apps to display a ‘Share to Reels’ widget. The target audience for the Share to Reels widget is consumers, whereas the Content Publishing API is targeted towards businesses, including third-party publishing platforms such as Hootsuite and Sprout Social that consolidate sharing to social media platforms within their third-party app.

Q: Why is Instagram partnering with other apps?

A: Creators already use a variety of apps to create and edit videos before uploading them to Instagram Reels – now we’re making that experience faster and easier. We are currently doing a small test of an integration with mobile apps that creators know and love, with more coming soon.

Q: How can I share my video from another app to Reels on Instagram?

Advertisement
free widgets for website

A: How it works (Make sure to update the mobile app you’re using to see the new Share to Reels option):

  • Create and edit your video in one of our partner apps
  • Once your video is ready, tap share and then tap the Instagram Reels icon
  • You will enter the Instagram Camera, where you can customize your reel with audio, effects, Voiceover and stickers. Record any additional clips or swipe up to add an additional clip from your camera roll.
  • Tap ‘Next’ to add a caption, hashtag, location, tag others or use the paid partnerships label.
  • Tap ‘Share’. Your reel will be visible where you share reels today, depending on your privacy settings.
See also  Facebook's centralized metaverse a threat to the decentralized ecosystem?

Q: How were partners selected?

A. We are currently working with a small group of developers that focus on video creation and editing as early partners. We’ll continue to expand to apps with other types of creation experiences.

Q: When will other developers be able to access Sharing to Reels on Instagram?

A: We do not currently have a date for general availability, but are planning to expand further in 2023.

Q: Can you share to Facebook Reels from other apps?

Advertisement
free widgets for website

A: Yes, Facebook offers the ability for developers to integrate with Sharing to Reels. For more information on third-party sharing opportunities, check out our entire suite of sharing offerings .

First seen at developers.facebook.com

Continue Reading

Trending