Skip to content

Conversation

@Zylphrex
Copy link
Member

@Zylphrex Zylphrex commented Nov 24, 2025

ingest-profiles is now using vroomrs to ingest profiles instead of writing through vroom. For self-hosted, we need to make sure filestore for profiles is properly configured so vroom can find the ingested profiles.

Fixes the issue in #4012 (comment)

`ingest-profiles` is now using vroomrs to ingest profiles instead of writing
through vroom. For self-hosted, we need to make sure filestore for profiles is
properly configured so vroom can find the ingested profiles.
@codecov
Copy link

codecov bot commented Nov 24, 2025

❌ 2 Tests Failed:

Tests completed Failed Passed Skipped
11 2 9 1
View the top 2 failed test(s) by shortest run time
_integration-test.test_01_basics::test_receive_transaction_events
Stack Traces | 128s run time
client_login = (<httpx.Client object at 0x7fe700278980>, <Response [200 OK]>)

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.skipif(os.environ.get(#x1B[33m"#x1B[39;49;00m#x1B[33mCOMPOSE_PROFILES#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m) != #x1B[33m"#x1B[39;49;00m#x1B[33mfeature-complete#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, reason=#x1B[33m"#x1B[39;49;00m#x1B[33mOnly run if feature-complete#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m #x1B[92mtest_receive_transaction_events#x1B[39;49;00m(client_login):#x1B[90m#x1B[39;49;00m
        client, _ = client_login#x1B[90m#x1B[39;49;00m
        sentry_sdk.init(#x1B[90m#x1B[39;49;00m
            dsn=get_sentry_dsn(client), profiles_sample_rate=#x1B[94m1.0#x1B[39;49;00m, traces_sample_rate=#x1B[94m1.0#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mdef#x1B[39;49;00m #x1B[92mplaceholder_fn#x1B[39;49;00m():#x1B[90m#x1B[39;49;00m
            #x1B[96msum#x1B[39;49;00m = #x1B[94m0#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m i #x1B[95min#x1B[39;49;00m #x1B[96mrange#x1B[39;49;00m(#x1B[94m5#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
                #x1B[96msum#x1B[39;49;00m += i#x1B[90m#x1B[39;49;00m
                time.sleep(#x1B[94m0.25#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m sentry_sdk.start_transaction(op=#x1B[33m"#x1B[39;49;00m#x1B[33mtask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, name=#x1B[33m"#x1B[39;49;00m#x1B[33mTest Transactions#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            placeholder_fn()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>       poll_for_response(#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33m{#x1B[39;49;00mSENTRY_TEST_HOST#x1B[33m}#x1B[39;49;00m#x1B[.../organizations/sentry/events/?dataset=profiles&field=profile.id&project=1&statsPeriod=1h#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            client,#x1B[90m#x1B[39;49;00m
            #x1B[94mlambda#x1B[39;49;00m x: #x1B[96mlen#x1B[39;49;00m(json.loads(x)[#x1B[33m"#x1B[39;49;00m#x1B[33mdata#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]) > #x1B[94m0#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31m_integration-test/test_01_basics.py#x1B[0m:399: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

request = 'http://localhost:.../organizations/sentry/events/?dataset=profiles&field=profile.id&project=1&statsPeriod=1h'
client = <httpx.Client object at 0x7fe700278980>
validator = <function test_receive_transaction_events.<locals>.<lambda> at 0x7fe700272660>

    #x1B[0m#x1B[94mdef#x1B[39;49;00m #x1B[92mpoll_for_response#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        request: #x1B[96mstr#x1B[39;49;00m, client: httpx.Client, validator: Callable = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    ) -> httpx.Response:#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m i #x1B[95min#x1B[39;49;00m #x1B[96mrange#x1B[39;49;00m(TIMEOUT_SECONDS):#x1B[90m#x1B[39;49;00m
            response = client.get(#x1B[90m#x1B[39;49;00m
                request, follow_redirects=#x1B[94mTrue#x1B[39;49;00m, headers={#x1B[33m"#x1B[39;49;00m#x1B[33mReferer#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m: SENTRY_TEST_HOST}#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m response.status_code == #x1B[94m200#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
                #x1B[94mif#x1B[39;49;00m validator #x1B[95mis#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mor#x1B[39;49;00m validator(response.text):#x1B[90m#x1B[39;49;00m
                    #x1B[94mbreak#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            time.sleep(#x1B[94m1#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
>           #x1B[94mraise#x1B[39;49;00m #x1B[96mAssertionError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mtimeout waiting for response status code 200 or valid data#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           AssertionError: timeout waiting for response status code 200 or valid data#x1B[0m

#x1B[1m#x1B[31m_integration-test/test_01_basics.py#x1B[0m:41: AssertionError
_integration-test.test_01_basics::test_initial_redirect
Stack Traces | 587s run time
request = <SubRequest 'configure_self_hosted_environment' for <Function test_initial_redirect>>

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture(scope=#x1B[33m"#x1B[39;49;00m#x1B[33msession#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, autouse=#x1B[94mTrue#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m #x1B[92mconfigure_self_hosted_environment#x1B[39;49;00m(request):#x1B[90m#x1B[39;49;00m
>       subprocess.run(#x1B[90m#x1B[39;49;00m
            [#x1B[33m"#x1B[39;49;00m#x1B[33mdocker#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcompose#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33m--ansi#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mnever#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mup#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33m--wait#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
            check=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            capture_output=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31m_integration-test/conftest.py#x1B[0m:15: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

input = None, capture_output = True, timeout = None, check = True
popenargs = (['docker', 'compose', '--ansi', 'never', 'up', '--wait'],)
kwargs = {'stderr': -1, 'stdout': -1}
process = <Popen: returncode: 1 args: ['docker', 'compose', '--ansi', 'never', 'up', '...>
stdout = b''
stderr = b' Volume "sentry-self-hosted_sentry-taskbroker"  Creating\n Volume "sentry-self-hosted_sentry-taskbroker"  Created\n ...ner sentry-self-hosted-relay-1  Error\ndependency failed to start: container sentry-self-hosted-relay-1 is unhealthy\n'
retcode = 1

    #x1B[0m#x1B[94mdef#x1B[39;49;00m #x1B[92mrun#x1B[39;49;00m(*popenargs,#x1B[90m#x1B[39;49;00m
            #x1B[96minput#x1B[39;49;00m=#x1B[94mNone#x1B[39;49;00m, capture_output=#x1B[94mFalse#x1B[39;49;00m, timeout=#x1B[94mNone#x1B[39;49;00m, check=#x1B[94mFalse#x1B[39;49;00m, **kwargs):#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Run command with arguments and return a CompletedProcess instance.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    The returned instance will have attributes args, returncode, stdout and#x1B[39;49;00m
    #x1B[33m    stderr. By default, stdout and stderr are not captured, and those attributes#x1B[39;49;00m
    #x1B[33m    will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them,#x1B[39;49;00m
    #x1B[33m    or pass capture_output=True to capture both.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If check is True and the exit code was non-zero, it raises a#x1B[39;49;00m
    #x1B[33m    CalledProcessError. The CalledProcessError object will have the return code#x1B[39;49;00m
    #x1B[33m    in the returncode attribute, and output & stderr attributes if those streams#x1B[39;49;00m
    #x1B[33m    were captured.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If timeout is given, and the process takes too long, a TimeoutExpired#x1B[39;49;00m
    #x1B[33m    exception will be raised.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    There is an optional argument "input", allowing you to#x1B[39;49;00m
    #x1B[33m    pass bytes or a string to the subprocess's stdin.  If you use this argument#x1B[39;49;00m
    #x1B[33m    you may not also use the Popen constructor's "stdin" argument, as#x1B[39;49;00m
    #x1B[33m    it will be used internally.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    By default, all communication is in bytes, and therefore any "input" should#x1B[39;49;00m
    #x1B[33m    be bytes, and the stdout and stderr will be bytes. If in text mode, any#x1B[39;49;00m
    #x1B[33m    "input" should be a string, and stdout and stderr will be strings decoded#x1B[39;49;00m
    #x1B[33m    according to locale encoding, or by "encoding" if set. Text mode is#x1B[39;49;00m
    #x1B[33m    triggered by setting any of text, encoding, errors or universal_newlines.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    The other arguments are the same as for the Popen constructor.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96minput#x1B[39;49;00m #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m kwargs.get(#x1B[33m'#x1B[39;49;00m#x1B[33mstdin#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m) #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
                #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[33m'#x1B[39;49;00m#x1B[33mstdin and input arguments may not both be used.#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            kwargs[#x1B[33m'#x1B[39;49;00m#x1B[33mstdin#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m] = PIPE#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m capture_output:#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m kwargs.get(#x1B[33m'#x1B[39;49;00m#x1B[33mstdout#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m) #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mor#x1B[39;49;00m kwargs.get(#x1B[33m'#x1B[39;49;00m#x1B[33mstderr#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m) #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
                #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[33m'#x1B[39;49;00m#x1B[33mstdout and stderr arguments may not be used #x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                                 #x1B[33m'#x1B[39;49;00m#x1B[33mwith capture_output.#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            kwargs[#x1B[33m'#x1B[39;49;00m#x1B[33mstdout#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m] = PIPE#x1B[90m#x1B[39;49;00m
            kwargs[#x1B[33m'#x1B[39;49;00m#x1B[33mstderr#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m] = PIPE#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m Popen(*popenargs, **kwargs) #x1B[94mas#x1B[39;49;00m process:#x1B[90m#x1B[39;49;00m
            #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
                stdout, stderr = process.communicate(#x1B[96minput#x1B[39;49;00m, timeout=timeout)#x1B[90m#x1B[39;49;00m
            #x1B[94mexcept#x1B[39;49;00m TimeoutExpired #x1B[94mas#x1B[39;49;00m exc:#x1B[90m#x1B[39;49;00m
                process.kill()#x1B[90m#x1B[39;49;00m
                #x1B[94mif#x1B[39;49;00m _mswindows:#x1B[90m#x1B[39;49;00m
                    #x1B[90m# Windows accumulates the output in a single blocking#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                    #x1B[90m# read() call run on child threads, with the timeout#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                    #x1B[90m# being done in a join() on those threads.  communicate()#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                    #x1B[90m# _after_ kill() is required to collect that and add it#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                    #x1B[90m# to the exception.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                    exc.stdout, exc.stderr = process.communicate()#x1B[90m#x1B[39;49;00m
                #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
                    #x1B[90m# POSIX _communicate already populated the output so#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                    #x1B[90m# far into the TimeoutExpired exception.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                    process.wait()#x1B[90m#x1B[39;49;00m
                #x1B[94mraise#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[94mexcept#x1B[39;49;00m:  #x1B[90m# Including KeyboardInterrupt, communicate handled that.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                process.kill()#x1B[90m#x1B[39;49;00m
                #x1B[90m# We don't call process.wait() as .__exit__ does that for us.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[94mraise#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            retcode = process.poll()#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m check #x1B[95mand#x1B[39;49;00m retcode:#x1B[90m#x1B[39;49;00m
>               #x1B[94mraise#x1B[39;49;00m CalledProcessError(retcode, process.args,#x1B[90m#x1B[39;49;00m
                                         output=stdout, stderr=stderr)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE               subprocess.CalledProcessError: Command '['docker', 'compose', '--ansi', 'never', 'up', '--wait']' returned non-zero exit status 1.#x1B[0m

#x1B[1m#x1B[.../usr/lib/python3.12/subprocess.py#x1B[0m:571: CalledProcessError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Copy link
Member

@BYK BYK left a comment

Choose a reason for hiding this comment

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

Looks okay but without any tests, hard to be sure. Also added some comments I'd like to see addressed.

# 3. Point `filestore-profiles` and vroom to the SeaweedFS "profiles" bucket.

start_service_and_wait_ready seaweedfs
$dc exec -e "HTTP_PROXY=${HTTP_PROXY:-}" -e "HTTPS_PROXY=${HTTPS_PROXY:-}" -e "NO_PROXY=${NO_PROXY:-}" -e "http_proxy=${http_proxy:-}" -e "https_proxy=${https_proxy:-}" -e "no_proxy=${no_proxy:-}" seaweedfs apk add --no-cache s3cmd
Copy link
Member

Choose a reason for hiding this comment

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

@aldy505 we should have a shortcut for this monstrosity:

$dc exec -e "HTTP_PROXY=${HTTP_PROXY:-}" -e "HTTPS_PROXY=${HTTPS_PROXY:-}" -e "NO_PROXY=${NO_PROXY:-}" -e "http_proxy=${http_proxy:-}" -e "https_proxy=${https_proxy:-}" -e "no_proxy=${no_proxy:-}" 

Copy link
Collaborator

Choose a reason for hiding this comment

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

Fun fact, there's a little problem. Surprisingly seaweedfs only reads the lowercased http_proxy :)

curses at myself

# 3. Point `filestore-profiles` and vroom to the SeaweedFS "profiles" bucket.

start_service_and_wait_ready seaweedfs
$dc exec -e "HTTP_PROXY=${HTTP_PROXY:-}" -e "HTTPS_PROXY=${HTTPS_PROXY:-}" -e "NO_PROXY=${NO_PROXY:-}" -e "http_proxy=${http_proxy:-}" -e "https_proxy=${https_proxy:-}" -e "no_proxy=${no_proxy:-}" seaweedfs apk add --no-cache s3cmd
Copy link
Collaborator

Choose a reason for hiding this comment

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

Fun fact, there's a little problem. Surprisingly seaweedfs only reads the lowercased http_proxy :)

curses at myself

Co-authored-by: Burak Yigit Kaya <[email protected]>
@aldy505 aldy505 force-pushed the txiao/fix/ingest-profile-file-path branch from 3cc8e38 to e61c180 Compare November 27, 2025 10:22
Comment on lines +106 to +116
</Rule>
</LifecycleConfiguration>
EOF
)

$dc exec seaweedfs sh -c "printf '%s' '$lifecycle_policy' > /tmp/profiles-lifecycle-policy.xml"
$s3cmd --access_key=sentry --secret_key=sentry --no-ssl --region=us-east-1 --host=localhost:8333 --host-bucket='localhost:8333/%(bucket)' setlifecycle /tmp/profiles-lifecycle-policy.xml s3://profiles

echo "Making sure the bucket lifecycle policy is all set up correctly..."
$s3cmd --access_key=sentry --secret_key=sentry --no-ssl --region=us-east-1 --host=localhost:8333 --host-bucket='localhost:8333/%(bucket)' getlifecycle s3://profiles
fi

This comment was marked as outdated.

Comment on lines +106 to +116
</Rule>
</LifecycleConfiguration>
EOF
)

$dc exec seaweedfs sh -c "printf '%s' '$lifecycle_policy' > /tmp/profiles-lifecycle-policy.xml"
$s3cmd --access_key=sentry --secret_key=sentry --no-ssl --region=us-east-1 --host=localhost:8333 --host-bucket='localhost:8333/%(bucket)' setlifecycle /tmp/profiles-lifecycle-policy.xml s3://profiles

echo "Making sure the bucket lifecycle policy is all set up correctly..."
$s3cmd --access_key=sentry --secret_key=sentry --no-ssl --region=us-east-1 --host=localhost:8333 --host-bucket='localhost:8333/%(bucket)' getlifecycle s3://profiles
fi

This comment was marked as outdated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

5 participants